from twisted.web import server, resource from twisted.internet import reactor from twisted.internet.error import ReactorAlreadyRunning import base64 import codecs import sqlite3 import collections import json import time import datetime import logging import other.utils as utils import gamespy import gamespy.gs_utility as gs_utils logger_output_to_console = True logger_output_to_file = True logger_name = "AdminPage" logger_filename = "admin_page.log" logger = utils.create_logger(logger_name, logger_filename, -1, logger_output_to_console, logger_output_to_file) #Example of adminpageconf.json # # {"username":"admin","password":"opensesame"} # # NOTE: Must use double-quotes or json module will fail # NOTE2: Do not check the .json file into public git! adminpageconf = None try: adminpageconf = file('adminpageconf.json').read().strip() except Exception,e: logger.log(logging.INFO,"ERROR reading adminpageconf.json: "+str(e)) logger.log(logging.INFO," *** WARN: adminpageconf.json could not be read. Creating one with default values") adminpageconf = '{"username":"admin","password":"opensesame"}' fd = open('adminpageconf.json','w') fd.write(adminpageconf) fd.close() adminpageconf = json.loads(adminpageconf) admin_username = str(adminpageconf['username']) admin_password = str(adminpageconf['password']) class AdminPage(resource.Resource): isLeaf = True def __init__(self,adminpage): self.adminpage = adminpage def is_authorized(self, request): is_auth = False response_code = 401 error_message = "Authorization required!" address = request.getClientIP() try: expected_auth = base64.encodestring(admin_username+":"+admin_password).strip() actual_auth = request.getAllHeaders()['authorization'].replace("Basic ","").strip() if actual_auth == expected_auth: if actual_auth == 'YWRtaW46b3BlbnNlc2FtZQ==': error_message = ( 'You must change the default values in adminpageconf.json' '[LOG OUT]' ) response_code = 500 else: logger.log(logging.INFO,address+" Auth Success") is_auth = True except Exception,e: logger.log(logging.INFO,address+" Auth Error: "+str(e)) if not is_auth: logger.log(logging.INFO,address+" Auth Failure") request.setResponseCode(response_code) request.setHeader('WWW-Authenticate', 'Basic realm="ALTWFC"') request.write(error_message) return is_auth def update_whitelist(self, request): address = request.getClientIP() dbconn = sqlite3.connect('gpcm.db') userid = request.args['userid'][0].strip() gameid = request.args['gameid'][0].upper().strip() macadr = request.args['macadr'][0].strip() actiontype = request.args['actiontype'][0] if not userid.isdigit() or not gameid.isalnum() or not macadr.isalnum(): request.setResponseCode(500) logger.log(logging.INFO,address+" Bad data "+userid+" "+gameid+" "+macadr) return "Bad data" if actiontype == 'add': dbconn.cursor().execute('insert into whitelist values(?,?,?)',(userid,gameid,macadr)) responsedata = "Added macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid) else: dbconn.cursor().execute('delete from whitelist where userid=? and gameid=? and macadr=?',(userid,gameid,macadr)) responsedata = "Removed macadr=%s for gameid=%s, userid=%s" % (macadr,gameid,userid) dbconn.commit() dbconn.close() logger.log(logging.INFO,address+" "+responsedata) request.setHeader("Content-Type", "text/html; charset=utf-8") return responsedata def render_whitelist(self, request): address = request.getClientIP() dbconn = sqlite3.connect('gpcm.db') dbconn.cursor().execute('CREATE TABLE IF NOT EXISTS whitelist (userid TEXT, gameid TEXT, macadr TEXT)') logger.log(logging.INFO,address+" Viewed whitelist") responsedata = ("\r\n" "altwfc admin page - WhiteList" '[CLICK HERE TO LOG OUT]' "
" "userid:\r\n" "gameid:\r\n" "macadr:\r\n" "\r\n" "
\r\n" "" "\r\n") for row in dbconn.cursor().execute("select * from whitelist"): userid = str(row[0]) gameid = str(row[1]) macadr = str(row[2]) responsedata += ("" "\r\n") responsedata += "
useridgameidmacadr
"+userid+""+gameid+""+macadr+"
" "" "" "" "\r\n" "
" dbconn.close() request.setHeader("Content-Type", "text/html; charset=utf-8") return responsedata def render_GET(self, request): if not self.is_authorized(request): return "" if request.path == "/whitelist": return self.render_whitelist(request) if request.path != "/banhammer": request.setResponseCode(500) return "wrong url path" sqlstatement = ('' 'select users.profileid,enabled,data,users.gameid,console,users.userid ' 'from nas_logins ' 'inner join users ' 'on users.userid = nas_logins.userid ' 'inner join ( ' ' select max(profileid) newestpid, userid, gameid, devname ' ' from users ' ' group by userid,gameid) ' 'ij on ij.userid = users.userid and ' 'users.profileid = ij.newestpid ' 'order by users.gameid ' '') dbconn = sqlite3.connect('gpcm.db') responsedata = ("\r\n" "altwfc admin page" '[CLICK HERE TO LOG OUT]' "

" 'WhiteList' "" "" "" "\r\n") for row in dbconn.cursor().execute(sqlstatement): dwc_pid = str(row[0]) enabled = str(row[1]) nasdata = collections.defaultdict(lambda: '', json.loads(row[2])) gameid = str(row[3]) is_console = int(str(row[4])) userid = str(row[5]) gsbrcd = str(nasdata['gsbrcd']) ingamesn = '' if 'ingamesn' in nasdata: ingamesn = str(nasdata['ingamesn']) elif 'devname' in nasdata: ingamesn = str(nasdata['devname']) if ingamesn: ingamesn = gs_utils.base64_decode(ingamesn) if is_console: ingamesn = codecs.utf_16_be_decode(ingamesn)[0] else: ingamesn = codecs.utf_16_le_decode(ingamesn)[0] else: ingamesn = '[NOT AVAILABLE]' responsedata += "" responsedata += "" responsedata += "" responsedata += "" responsedata += "" responsedata += "" responsedata += "" if enabled == "1": responsedata += ("") else: responsedata += ("") responsedata += "
ingamesn or devnamegameidEnablednewest dwc_pidgsbrcduserid
"+ingamesn+""+gameid+""+enabled+""+dwc_pid+""+gsbrcd+""+userid+"
" "" "" "" "
" "" "" "" "
" dbconn.close() request.setHeader("Content-Type", "text/html; charset=utf-8") return responsedata.encode('utf-8') def render_POST(self, request): if not self.is_authorized(request): return "" if request.path == "/updatewhitelist": return self.update_whitelist(request) if request.path != "/enableuser" and request.path != "/disableuser": request.setResponseCode(500) return "wrong url path" address = request.getClientIP() responsedata = "" userid = request.args['userid'][0] gameid = request.args['gameid'][0].upper() ingamesn = request.args['ingamesn'][0] if not userid.isdigit() or not gameid.isalnum(): logger.log(logging.INFO,address+" Bad data "+userid+" "+gameid) return "Bad data" dbconn = sqlite3.connect('gpcm.db') if request.path == "/enableuser": dbconn.cursor().execute('update users set enabled=1 ' 'where gameid=? and userid=?',(gameid,userid)) responsedata = "Enabled %s with gameid=%s, userid=%s" % \ (ingamesn,gameid,userid) else: dbconn.cursor().execute('update users set enabled=0 ' 'where gameid=? and userid=?',(gameid,userid)) responsedata = "Disabled %s with gameid=%s, userid=%s" % \ (ingamesn,gameid,userid) dbconn.commit() dbconn.close() logger.log(logging.INFO,address+" "+responsedata) request.setHeader("Content-Type", "text/html; charset=utf-8") return responsedata class AdminPageServer(object): def start(self): site = server.Site(AdminPage(self)) reactor.listenTCP(9009, site) try: if reactor.running == False: reactor.run(installSignalHandlers=0) except ReactorAlreadyRunning: pass if __name__ == "__main__": AdminPageServer().start()