import BaseHTTPServer import os import time import base64 import re import supybot.utils as utils import sqlite3 import collections import urllib from StringIO import StringIO host = 'http://domain.tld' port = 80 standalone = True webpath = '/bantracker' username = 'username' password = 'password' filename = '/home/botaccount/data/networkname/ChanTracker.db' channels = [] # empty to allows view of all channels recorded, otherwise restrict the views to channels # usage python server.py base64string = base64.encodestring('%s:%s' % (username,password))[:-1] def timeElapsed(elapsed, short=False, leadingZeroes=False, years=True, weeks=True, days=True, hours=True, minutes=True, seconds=True): """Given seconds, returns a string with an English description of how much time as passed. leadingZeroes determines whether 0 days, 0 hours, etc. will be printed; the others determine what larger time periods should be used. """ ret = [] def Format(s, i): if i or leadingZeroes or ret: if short: ret.append('%s%s' % (i, s[0])) else: ret.append(format('%n', (i, s))) elapsed = int(elapsed) assert years or weeks or days or \ hours or minutes or seconds, 'One flag must be True' if years: (yrs, elapsed) = (elapsed // 31536000, elapsed % 31536000) Format('year', yrs) if weeks: (wks, elapsed) = (elapsed // 604800, elapsed % 604800) Format('week', wks) if days: (ds, elapsed) = (elapsed // 86400, elapsed % 86400) Format('day', ds) if hours: (hrs, elapsed) = (elapsed // 3600, elapsed % 3600) Format('hour', hrs) if minutes or seconds: (mins, secs) = (elapsed // 60, elapsed % 60) if leadingZeroes or mins: Format('minute', mins) if seconds: leadingZeroes = True Format('second', secs) if not ret: raise ValueError, 'Time difference not great enough to be noted.' if short: return ' '.join(ret) else: return format('%L', ret) class MyHandler( BaseHTTPServer.BaseHTTPRequestHandler ): server_version= "Ircd-Seven/1.1" if not standalone: def log_request(self, *args): pass # disable logging def do_GET( self ): self.page( self.path ) def page (self,query): if standalone: h = '%s:%s/' % (host,port) else: h = '%s/' % webpath body = [] if not query: return if query.startswith('/?username='): query = query.replace('/?','') a = query.split('&') u = p = None for item in a: aa = item.split('=') if aa[0] == 'username': u = aa[1] if aa[0] == 'password': p = aa[1] if u and p: raw = base64.encodestring('%s:%s' % (u,p))[:-1] if not raw == base64string: query = '' else: query = '/?hash=%s' % base64string if not query.startswith('/?hash='): body.append('\n\nChanTracker\n') body.append('\n') body.append("\n\n") body.append('
\n' % h) body.append('

Username:

\n') body.append('

Password:

\n') body.append('\n') body.append("
\n") body.append("\n\n") self.send_response(200) self.send_header("Content-type","text/html") full = ''.join(body) self.send_header("Content-length",str(len(full))) self.end_headers() self.wfile.write(full) return if query.startswith('/?hash='): a = query.split('&')[0] a = a.replace('/?hash=','') query = query.replace('%3D','=') query = query.replace('/?hash=%s' % base64string,'/') q = '?hash=%s' % base64string query = urllib.unquote( query ) print query body.append('\n\nBanTracker - %s\n' % query) body.append('\n') body.append('\n') # body.append('\n') body.append('\n\n') body.append('
\n') body.append('
\n' % q) body.append('
') body.append('' % base64string) body.append('\n') body.append('\n') body.append('
\n') body.append('
\n') db = self._getbandb() c = db.cursor() if query: ar = [] if query.startswith('/&id='): search = query.split('/&id=')[1] c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? ORDER BY id DESC""",(search,)) r = c.fetchall() if len(r): ban = r[0] (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban if not len(channels) or channel in channels: body.append('

#%s

\n' % id) body.append('

#%s by %s in %s : +%s : %s

\n' % (id,oper,channel,kind,mask)) body.append('

Begin at %s

\n' % time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(float(begin_at)))) was = float(begin_at) == float(end_at) if was: was = 'forever' else: was = timeElapsed(float(end_at) - float(begin_at)) body.append('

Original duration : %s

\n' % was) if not removed_at: if was != 'forever': body.append('

%s

\n' % 'It will expire in %s' % timeElapsed(float(end_at) - time.time())) else: body.append('

%s

\n' % 'Removed after %s on %s by %s' % (timeElapsed(float(removed_at)-float(begin_at)),time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(float(removed_at))),removed_by)) c.execute("""SELECT full, log FROM nicks WHERE ban_id=?""",(id,)) r = c.fetchall() if len(r): users = r body.append('

Logs

\n') for u in users: (full,log) = u body.append('

for %s

\n' % full) if log != '': body.append('\n') c.execute("""SELECT oper, at, comment FROM comments WHERE ban_id=?""",(id,)) r = c.fetchall() if len(r): body.append('

Comments

\n') body.append('\n') elif query.startswith('/&channel='): search = '#'+query.split('/&channel=')[1] c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE channel=? ORDER BY id DESC""",(search,)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban ar.append([int(id),channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by]) elif query.startswith('/&removed_by='): search = query.split('/&removed_by=')[1] c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE removed_by=? ORDER BY id DESC""",(search,)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban ar.append([int(id),channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by]) elif query.startswith('/&oper='): search = query.split('/&oper=')[1] c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE oper=? ORDER BY id DESC""",(search,)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban ar.append([int(id),channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by]) elif query.startswith('/&mask='): search = query.split('/&mask=')[1] glob = '*%s*' % search like = '%'+search+'%' c.execute("""SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? OR log GLOB ? OR log LIKE ? ORDER BY ban_id DESC""",(glob,like,glob,like)) L = [] a = {} r = c.fetchall() if len(r): bans = r d = {} for ban in bans: (id,full) = ban if not id in d: d[id] = id for id in d: c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? ORDER BY id DESC""",(int(id),)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban a[str(id)] = ban c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE mask GLOB ? OR mask LIKE ? ORDER BY id DESC""",(glob,like)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban a[str(id)] = ban if len(a): ar = [] for ban in a: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = a[ban] ar.append([int(id),channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by]) def sort_function (item): return item[0] ar.sort(key=sort_function) ar.sort(reverse=True) elif query.startswith('/&search='): search = query.split('/&search=')[1] search = search.replace('+','*') print search if search: s = '*%s*' % search qu = '%'+search+'%' c.execute("""SELECT ban_id, full FROM nicks WHERE full GLOB ? OR full LIKE ? OR log GLOB ? OR log LIKE ? ORDER BY ban_id DESC""",(s,qu,s,qu)) L = [] a = {} r = c.fetchall() if len(r): bans = r d = {} for ban in bans: (id,full) = ban if not id in d: d[id] = id for id in d: c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? ORDER BY id DESC""",(int(id),)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban a[id] = ban c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE mask GLOB ? OR mask LIKE ? OR channel GLOB ? OR channel LIKE ? OR oper GLOB ? OR oper LIKE ? ORDER BY id DESC""",(s,qu,s,qu,s,qu)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban a[id] = ban c.execute("""SELECT ban_id, comment FROM comments WHERE comment GLOB ? OR comment LIKE ? ORDER BY ban_id DESC""",(s,qu)) r = c.fetchall() d = {} if len(r): bans = r for ban in bans: (id,full) = ban d[id] = id for id in d: if not id in a: c.execute("""SELECT id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by FROM bans WHERE id=? ORDER BY id DESC LIMIT 1""",(int(id),)) r = c.fetchall() if len(r): bans = r for ban in bans: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ban a[id] = ban if len(a): ar = [] for ban in a: (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = a[ban] ar.append([int(id),channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by]) def sort_function (item): return item[0] ar.sort(key=sort_function) ar.sort(reverse=True) else: body.append('

nothing found

\n') if len(ar): print 'found %s results' % len(ar) i = 0 body.append('

results %s

' % search) body.append('
\n') body.append('\n') body.append('\n') while i < len(ar): (id,channel,oper,kind,mask,begin_at,end_at,removed_at,removed_by) = ar[i] if not len(channels) or channel in channels: body.append('\n') body.append('\n' % (h,q,id,id)) body.append('\n' % (h,q,channel.split('#')[1],channel)) body.append('\n' % (h,q,urllib.urlencode({'oper':oper}),oper)) body.append('\n' % kind) body.append('\n' % (h,q,urllib.urlencode({'mask':mask}),mask)) s = time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(float(begin_at))) body.append('\n' % s) if end_at and end_at != begin_at: s = time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(float(end_at))) body.append( '\n' % s) else: body.append( '') if removed_at: s = time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(float(removed_at))) body.append( '' % s) else: body.append( '\n' ) if removed_by: body.append( '\n' % (h,q,urllib.urlencode({'removed_by':removed_by}),removed_by)) else: body.append( '\n') # affected = '' # try: # c.execute("""SELECT full, log FROM nicks WHERE ban_id=?""",(id,)) # affected = len(c.fetchall()) # except: # affected = '' # body.append( '\n' % affected) body.append( '\n') i = i+1 body.append('\n') body.append('
IDChannelOperatorKindTargetBegin dateEnd dateRemoved dateRemoved by
%s%s%s+%s%s%s%s%s%s%s
\n') body.append("") self.send_response(200) self.send_header("Content-type","text/html") full = ''.join(body) print 'html lines %s' % len(full) self.send_header("Content-length",len(full)) self.end_headers() self.wfile.write(full) c.close() def _getbandb (self): if os.path.exists(filename): db = sqlite3.connect(filename,timeout=10) db.text_factory = str return db db = sqlite3.connect(filename) db.text_factory = str c = db.cursor() c.execute("""CREATE TABLE bans ( id INTEGER PRIMARY KEY, channel VARCHAR(100) NOT NULL, oper VARCHAR(1000) NOT NULL, kind VARCHAR(1) NOT NULL, mask VARCHAR(1000) NOT NULL, begin_at TIMESTAMP NOT NULL, end_at TIMESTAMP NOT NULL, removed_at TIMESTAMP, removed_by VARCHAR(1000) )""") c.execute("""CREATE TABLE nicks ( ban_id INTEGER, ban VARCHAR(1000) NOT NULL, full VARCHAR(1000) NOT NULL, log TEXT NOT NULL )""") c.execute("""CREATE TABLE comments ( ban_id INTEGER, oper VARCHAR(1000) NOT NULL, at TIMESTAMP NOT NULL, comment TEXT NOT NULL )""") db.commit() return db def httpd(handler_class=MyHandler, server_address = ('', port), ): srvr = BaseHTTPServer.HTTPServer(server_address, handler_class) srvr.serve_forever() if __name__ == "__main__": httpd( )