Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: b37a2aab05
Fetching contributors…

Cannot retrieve contributors at this time

executable file 210 lines (202 sloc) 6.162 kb
#!/usr/bin/env python
from SocketServer import ThreadingMixIn
from collections import defaultdict
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import time
import sys
from datetime import datetime
from urlparse import urlparse
import urllib2
import json
from threading import Thread, Event
import threading
import uuid
import re
class Error:
USER_EXISTS=1
USER_INVALID=2
USER_RESERVED=3
def Err(code):
return {"error": code};
def d2j(dict, callback=None):
str = json.dumps(dict);
if callback != None:
return ''.join([callback,"(",str, ")"]);
return str
class TimeoutThread(Thread):
def __init__(self):
Thread.__init__(self)
self._finished = Event();
self._interval = 15.0;
def setInterval(self, timeout):
self._interval = timeout
def stop(self):
self._finished.set();
def run(self):
while 1:
if self._finished.isSet(): print("endin..."); return
self.task();
self._finished.wait(self._interval);
def task(self):
pass
class Users(dict):
user_regex = re.compile("^[a-zA-Z0-9_+\-]+$");
reserved_names= re.compile("(admin|system|administrator)");
def __init__(self):
self.max_users = 0;
self.thread = Users.InactiveUserMonitor(self);
print ("**** ALERT ****");
self.thread.start();
def userExists(self, username):
for u in self:
if username == self[u]["nick"]:
return True
return False
def userActivity(self, id):
self[id]["last_active"] = time.time();
def getUserNickById(self, id):
return self[id]["nick"]
def userExistsById(self, id):
return id in self
def addUser(self, username):
if self.userExists(username) == True:
raise Exception(-Error.USER_EXISTS);
if Users.user_regex.match(username) == None:
raise Exception(-Error.USER_INVALID);
if Users.reserved_names.match(username):
raise Exception(-Error.USER_RESERVED);
self.max_users = self.max_users + 1
id = str(uuid.uuid1());
self[id] = {"nick": username, "id": id, "last_active": time.time()};
return id
def getUsers(self):
list = [];
for u in self:
list += [self[u]['nick']]
return list
class InactiveUserMonitor(TimeoutThread):
def __init__(self, parent):
TimeoutThread.__init__(self);
self._users = parent
def task(self):
cTime = time.time();
for u in self._users.keys():
if cTime - self._users[u]["last_active"] > 60:
print("user %s(%s) is inactive!"%(self._users[u]["nick"], u));
print("*** DELETING USER ***")
del self._users[u]
class Messages(list):
def __init__(self):
pass
def addMessage(self, frm, message, time=int(time.time())):
self.append({"from": frm, "message": message, "time": time, "since": len(self)})
class WaitForMessages(TimeoutThread):
def __init__(self, parent):
self.parent = parent;
self.initCount = len(self.parent)
# self._stop = False
TimeoutThread.__init__(self);
'''def stop(self):
self._stop = True'''
def task(self):
##while initCount == len(self.parent):
## pass # do NOTHING!
##print(":D");
if self.initCount != len(self.parent):
self.stop();
def is_int(i):
try:
int(i);
except ValueError:
return False;
else:
return True;
def parse_qs(str):
s = str.split('&');
dict = {};
for x in s:
name, sep, value = x.partition('=')
dict[name] = urllib2.unquote(value)
return dict
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
pass
html_escape_table = {
"&": "&",
'"': """,
"'": "'",
">": ">",
"<": "&lt;",
}
def html_escape(text):
"""Produce entities within text."""
return "".join(html_escape_table.get(c,c) for c in text)
class HTTPHandler(BaseHTTPRequestHandler):
'''def __init__(self, a, b, c):
self.userList = Users();
self.messages = Messages();
BaseHTTPRequestHandler.__init__(self, a, b,c);'''
def do_GET(self):
self.send_response(200);
self.send_header("Content-type", "application/x-javascript");
self.end_headers();
path = urlparse(self.path);
pathArr = filter(None, path.path.split('/'))
query = parse_qs(path.query)
callback = query.get('callback', None);
timeout = int(query.get('timeout', 60));
uid = query.get("uid",None);
since = int(query.get("since", 0));
if uid!=None and self.server.users.userExistsById(uid):
self.server.users.userActivity(uid);
result = {"success": True};
if pathArr[0] == "api":
if uid != None and self.server.users.userExistsById(uid):
result["success"] = False
elif pathArr[1] == "get_messages":
if query.get("now","") != "1":
#t = Messages.WaitForMessages(self.server.messages)
#t.setInterval(0.5);
#t.start();
#t.join(timeout);
#t.stop();
t = time.time()
checking = True
l = since #len(self.server.messages);
while l == len(self.server.messages) and time.time() - t < timeout:
pass
result["users"] = self.server.users.getUsers();
result["messages"] = self.server.messages[since:]
elif pathArr[1]=="post_message":
message = query.get("message", "");
self.server.messages.addMessage(self.server.users.getUserNickById(uid), html_escape(message));
elif pathArr[1]=="user_list":
result["data"] = self.server.users.getUsers();
elif pathArr[1]=="new_user":
print "NEW USAH!";
uname = query.get("nick", "Guest_"+str(self.server.users.max_users));
try:
uid = self.server.users.addUser(uname);
except Exception as e:
result["success"]=False;
code = e[0]
if code == -1:
result["message"] = "Username taken!";
if code == -2 or code == -3:
result["message"]= "Invalid username!";
else:
result["data"] = self.server.users[uid];
self.wfile.write(d2j(result, callback));
if __name__ == "__main__":
server = ThreadedHTTPServer(('', 8080), HTTPHandler);
server.users = Users();
server.messages=Messages();
try:
server.serve_forever();
except (KeyboardInterrupt, SystemExit):
print("Exit...");
server.messages.addMessage("server", "Server shutting down...");
for thread in threading.enumerate():
if isinstance(thread,Messages.WaitForMessages) or isinstance(thread, Users.InactiveUserMonitor):
thread.stop();
# server.users.thread.stop();
sys.exit();
Jump to Line
Something went wrong with that request. Please try again.