#! /usr/bin/python import cgi, os, string, time form = cgi.FieldStorage() def txtfilter(s): l = filter(lambda c: c in "!$*,-.0123456789:@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}", s) return string.join(l, '') def identity(s): return s def fieldlist(name, filter=txtfilter): result = [] if form.has_key(name): field = form[name] if type(field) is type([]): for f in field: result.append(filter(f.value)) else: result.append(filter(field.value)) return result def goodmatch(addr1, addr2): l1 = string.split(addr1, '.') if len(l1) >= 4: del l1[-1] l2 = string.split(addr2, '.') if len(l2) >= 4: del l2[-1] return l1 == l2 class Entry: Notice = '' FIELDS = [('server', 128), ('desc', 128), ('icon', 64), ('orig', 64), ('dele1', 64), ('dele2', 64)] def __init__(self, f): self.pos = f.tell() for fname, flen in self.FIELDS: s = f.read(flen) if not s: self.filled = 0 break setattr(self, fname, string.rstrip(s)) else: self.filled = 1 def __nonzero__(self): return self.filled def write(self, f): if not getattr(self, 'icon', ''): try: import random lst = os.listdir('../htdocs/images') except: pass else: lst = filter(lambda x: x[-4:]=='.png' and 'A'<=x[0]<='Z', lst) if lst: self.icon = random.choice(lst) f.seek(self.pos) for fname, flen in self.FIELDS: data = getattr(self, fname, '')[:flen] f.write(data + ' '*(flen-len(data))) def main(): DATABASE = 'servers' SIZEMAX = 65536 Serv = 0 Orig = 1 Dele1 = 2 REMOTE_ADDR = os.environ['REMOTE_ADDR'] REMOTE_ID = REMOTE_ADDR + time.strftime('@%d%m', time.localtime(time.time())) OPS = {} for srv in fieldlist('d'): OPS[srv] = 'd' for srv in fieldlist('a'): OPS[srv] = 'a' desc = (fieldlist('desc', identity) or [''])[0] f = open(DATABASE, 'r+b') freelist = [] published = [] while 1: e = Entry(f) if not e: break if e.server: if OPS.get(e.server) == 'a': validdesc = desc and goodmatch(REMOTE_ADDR, e.orig) if e.dele1 or e.dele2 or (validdesc and desc != e.desc): e.dele1 = e.dele2 = '' # re-enable server if validdesc: e.desc = desc e.write(f) del OPS[e.server] elif OPS.get(e.server) == 'd': if goodmatch(REMOTE_ADDR, e.orig) or ( REMOTE_ID != e.dele1 and REMOTE_ID != e.dele2): if goodmatch(REMOTE_ADDR, e.orig): e.server = '' # remove server elif e.dele1 == '': e.dele1 = REMOTE_ID elif e.dele2 == '': e.dele2 = REMOTE_ID else: e.server = '' # remove server e.write(f) Entry.Notice = 'd' if e.server: published.append((e.pos, e)) else: freelist.append(e) for srv, action in OPS.items(): if action == 'a': if freelist: e = freelist[-1] del freelist[-1] else: f.seek(0, 2) e = Entry(f) if e.pos >= SIZEMAX: raise Exception("Sorry, server database too big") hostname = string.split(srv, ':')[0] if '.' not in hostname: Entry.Notice = 'Server hostname "%s" incomplete.' % hostname else: import socket try: result = socket.gethostbyaddr(hostname) except socket.error, e: Entry.Notice = ('%s: %s' % (hostname, e)) else: if result[0] == 'projects.sourceforge.net': # ???? Entry.Notice = ('Server hostname "%s" does not exist.' % hostname) else: e.server = srv e.icon = '' e.desc = desc e.orig = REMOTE_ADDR e.dele1 = e.dele2 = '' e.write(f) published.append((e.pos, e)) Entry.Notice = 'a' f.close() published.sort() return map(lambda (pos, e): e, published) def publish_list(serverlist): url = (fieldlist('url', identity) or ['http://127.0.0.1:8000'])[0] query = [] for s in fieldlist('redirected'): query.append('redirected=' + s) for s in serverlist: query.append('s=' + txtfilter(s.server)) url = url + '?' + string.join(query, '&') for s in fieldlist('frag'): url = url + '#' + s print 'Content-Type: text/html' print 'Location:', url print print '
' print 'Please click here to continue.' % url print '' def publish_default(serverlist): import htmlentitydefs text_to_html = {} for key, value in htmlentitydefs.entitydefs.items(): text_to_html[value] = '&' + key + ';' for i in range(32): text_to_html[chr(i)] = '?' def htmlquote(s, getter=text_to_html.get): lst = [] for c in s: lst.append(getter(c, c)) return string.join(lst, '') REMOTE_ADDR = os.environ['REMOTE_ADDR'] f = open('started.html', 'r') header, row, footer = string.split(f.read(), '\\') f.close() import sys print 'Content-Type: text/html' print sys.stdout.write(header % "List of registered Internet Servers") counter = 0 for s in serverlist: if s.icon: s1 = '' % s.icon else: s1 = '' lst = string.split(txtfilter(s.server), ':') hostname, port, udpport, httpport = (lst+['?','?','?','?'])[:4] s2 = '%s' % hostname try: int(httpport) except ValueError: pass else: s2 = '%s:%s' % (hostname, httpport, s2, port) s2 = '' + s2 + '' if s.desc: s2 = s2 + ' playing %s' % htmlquote(s.desc) if goodmatch(REMOTE_ADDR, s.orig): s2 = s2 + ' (if this server is dead, click here to remove it)' % s.server sys.stdout.write(row % (s1, ('#C0D0D0', '#E0D0A8')[counter&1], s2)) counter = counter + 1 if not serverlist: sys.stdout.write(row % ('', '#FFFFFF', 'There is no registered server at the moment.')) sys.stdout.write(footer % "If your browser understands Java, you can click on a server to join the game. Note however that you will still need to install the whole Python client to benefit from the background musics, as this feature is missing from the Java client.