diff --git a/admin_page_server.py b/admin_page_server.py
index 9db2177..9dcd750 100644
--- a/admin_page_server.py
+++ b/admin_page_server.py
@@ -1,13 +1,10 @@
-#Make sure you change the password to something else and don't commit it to public github!
-admin_username = "admin"
-admin_password = "opensesame"
-
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
@@ -23,6 +20,26 @@ 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
@@ -39,7 +56,7 @@ class AdminPage(resource.Resource):
actual_auth = request.getAllHeaders()['authorization'].replace("Basic ","").strip()
if actual_auth == expected_auth:
if actual_auth == 'YWRtaW46b3BlbnNlc2FtZQ==':
- error_message = ( 'You must change the default login info'
+ error_message = ( 'You must change the default values in adminpageconf.json'
'[LOG OUT]' )
response_code = 500
else:
@@ -54,9 +71,66 @@ class AdminPage(resource.Resource):
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]'
+ "\r\n"
+ ""
+ "| userid | gameid | macadr |
\r\n")
+ for row in dbconn.cursor().execute("select * from whitelist"):
+ userid = str(row[0])
+ gameid = str(row[1])
+ macadr = str(row[2])
+ responsedata += ("| "+userid+" | "+gameid+" | "+macadr+" | "
+ " |
\r\n")
+ responsedata += "
"
+ 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"
@@ -74,16 +148,19 @@ class AdminPage(resource.Resource):
'order by users.gameid '
'')
dbconn = sqlite3.connect('gpcm.db')
- responsedata = (""
dbconn.close()
request.setHeader("Content-Type", "text/html; charset=utf-8")
return responsedata.encode('utf-8')
@@ -128,6 +205,8 @@ class AdminPage(resource.Resource):
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"
@@ -155,6 +234,7 @@ class AdminPage(resource.Resource):
dbconn.commit()
dbconn.close()
logger.log(logging.INFO,address+" "+responsedata)
+ request.setHeader("Content-Type", "text/html; charset=utf-8")
return responsedata
diff --git a/gamespy/gs_database.py b/gamespy/gs_database.py
index eec64b4..b51d5af 100644
--- a/gamespy/gs_database.py
+++ b/gamespy/gs_database.py
@@ -94,15 +94,15 @@ class GamespyDatabase(object):
self.conn.row_factory = sqlite3.Row
#self.initialize_database()
-
+
def __del__(self):
self.close()
- def close(self):
+ def close(self):
if self.conn != None:
self.conn.close()
self.conn = None
-
+
def initialize_database(self):
with Transaction(self.conn) as tx:
row = tx.queryone("SELECT COUNT(*) FROM sqlite_master WHERE name = 'users' AND type = 'table'")
@@ -119,7 +119,7 @@ class GamespyDatabase(object):
tx.nonquery("CREATE TABLE buddies (userProfileId INT, buddyProfileId INT, time INT, status INT, notified INT, gameid TEXT, blocked INT)")
tx.nonquery("CREATE TABLE pending_messages (sourceid INT, targetid INT, msg TEXT)")
tx.nonquery("CREATE TABLE gamestat_profile (profileid INT, dindex TEXT, ptype TEXT, data TEXT)")
- tx.nonquery("CREATE UNIQUE INDEX IF NOT EXISTS gamestatprofile_triple ON gamestat_profile (profileid, dindex, ptype)")
+ tx.nonquery("CREATE UNIQUE INDEX gamestatprofile_triple on gamestat_profile(profileid,dindex,ptype)")
tx.nonquery("CREATE TABLE gameinfo (profileid INT, dindex TEXT, ptype TEXT, data TEXT)")
tx.nonquery("CREATE TABLE nas_logins (userid TEXT, authtoken TEXT, data TEXT)")
@@ -206,14 +206,16 @@ class GamespyDatabase(object):
return profileid
- def create_user(self, userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid):
+ def create_user(self, userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid, macadr):
#Check for console ban
with Transaction(self.conn) as tx:
- row = tx.queryone("SELECT * FROM users WHERE userid = ? and gameid = ? and enabled = 0 limit 1", (userid, gameid))
+ row = tx.queryone("SELECT * FROM users WHERE userid = ? and gameid = ? and enabled = 0 "
+ "and gameid not in (select gameid from whitelist where gameid=? and macadr=?) limit 1"
+ ,(userid, gameid, gameid, macadr))
r = self.get_dict(row)
if r != None:
- logger.log(logging.INFO, "--- REJECTING BANNED CONSOLE --- userid=%s,gameid=%s", userid,gameid)
+ logger.log(logging.INFO, "--- REJECTING BANNED CONSOLE --- userid=%s,gameid=%s,macadr=%s", userid,gameid,macadr)
return None
if self.check_user_exists(userid, gsbrcd) == 0:
diff --git a/gamespy/gs_utility.py b/gamespy/gs_utility.py
index ee1155b..d7b91f3 100644
--- a/gamespy/gs_utility.py
+++ b/gamespy/gs_utility.py
@@ -118,6 +118,7 @@ def login_profile_via_parsed_authtoken(authtoken_parsed, db):
password = authtoken_parsed['gsbrcd']
gsbrcd = authtoken_parsed['gsbrcd']
gameid = gsbrcd[:4]
+ macadr = authtoken_parsed['macadr']
uniquenick = utils.base32_encode(int(userid)) + gsbrcd
email = uniquenick + "@nds" # The Wii also seems to use @nds.
@@ -128,7 +129,7 @@ def login_profile_via_parsed_authtoken(authtoken_parsed, db):
valid_user = db.check_user_exists(userid, gsbrcd)
if valid_user == False:
- profileid = db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid)
+ profileid = db.create_user(userid, password, email, uniquenick, gsbrcd, console, csnum, cfc, bssid, devname, birth, gameid, macadr)
else:
profileid = db.perform_login(userid, password, gsbrcd)