Loginticket is now stored, which allows the storage server to properly process GetMyRecords.

Also added a check so an user may only edit his own records, I dunno if
the official server actually enforced this but it makes sense to.
This commit is contained in:
Admiral H. Curtiss 2014-05-24 04:02:52 +02:00
parent 3cbb56b090
commit cb2ba136aa
4 changed files with 47 additions and 23 deletions

View File

@ -35,7 +35,7 @@ class GamespyDatabase(object):
logger.log(-1, q)
c.execute(q)
q = "CREATE TABLE sessions (session TEXT, profileid INT)"
q = "CREATE TABLE sessions (session TEXT, profileid INT, loginticket TEXT)"
logger.log(-1, q)
c.execute(q)
@ -294,6 +294,18 @@ class GamespyDatabase(object):
c.close()
return profileid
def get_profileid_from_loginticket(self, loginticket):
q = "SELECT profileid FROM sessions WHERE loginticket = ?"
logger.log(-1, q.replace("?", "%s") % (loginticket))
c = self.conn.cursor()
c.execute(q, (loginticket,))
profileid = int(c.fetchone()[0])
c.close()
return profileid
def get_profile_from_session_key(self, session_key):
profileid = self.get_profileid_from_session_key(session_key)
@ -333,7 +345,7 @@ class GamespyDatabase(object):
c.execute(q, [profileid])
self.conn.commit()
def create_session(self, profileid):
def create_session(self, profileid, loginticket):
if profileid != None and self.check_profile_exists(profileid) == False:
return None
@ -343,12 +355,12 @@ class GamespyDatabase(object):
# Create new session
session_key = self.generate_session_key(8)
q ="INSERT INTO sessions VALUES (?, ?)"
q2 = q.replace("?", "%s") % (session_key, profileid)
q ="INSERT INTO sessions VALUES (?, ?, ?)"
q2 = q.replace("?", "%s") % (session_key, profileid, loginticket)
logger.log(-1, q2)
c = self.conn.cursor()
c.execute(q, [session_key, profileid])
c.execute(q, [session_key, profileid, loginticket])
self.conn.commit()
return session_key

View File

@ -213,7 +213,7 @@ class Gamestats(LineReceiver):
if profileid != None:
# Successfully logged in or created account, continue creating session.
sesskey = self.db.create_session(profileid)
sesskey = self.db.create_session(profileid, '')
self.sessions[profileid] = self

View File

@ -235,7 +235,8 @@ class PlayerSession(LineReceiver):
if profileid != None:
# Successfully logged in or created account, continue creating session.
self.sesskey = self.db.create_session(profileid)
loginticket = gs_utils.base64_encode(utils.generate_random_str(16))
self.sesskey = self.db.create_session(profileid, loginticket)
self.sessions[profileid] = self
@ -247,7 +248,7 @@ class PlayerSession(LineReceiver):
msg_d.append(('userid', userid))
msg_d.append(('profileid', profileid))
msg_d.append(('uniquenick', uniquenick))
msg_d.append(('lt', gs_utils.base64_encode(utils.generate_random_str(16)))) # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated.
msg_d.append(('lt', loginticket)) # Some kind of token... don't know it gets used or generated, but it doesn't seem to have any negative effects if it's not properly generated.
msg_d.append(('id', data_parsed['id']))
msg = gs_query.create_gamespy_message(msg_d)

View File

@ -6,6 +6,7 @@ import sqlite3
import xml.dom.minidom as minidom
import other.utils as utils
import gamespy.gs_database as gs_database
logger_output_to_console = True
logger_output_to_file = True
@ -26,6 +27,8 @@ class StorageHTTPServer(BaseHTTPServer.HTTPServer):
def __init__(self, server_address, RequestHandlerClass):
BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass)
self.gamespydb = gs_database.GamespyDatabase()
self.db = sqlite3.connect('storage.db')
self.tables = {}
@ -35,17 +38,19 @@ class StorageHTTPServer(BaseHTTPServer.HTTPServer):
cursor.execute('CREATE TABLE typedata (tbl TEXT, col TEXT, type TEXT)')
if not self.table_exists('g2050_box_us_eu'):
cursor.execute('CREATE TABLE g2050_box_us_eu (recordid INT PRIMARY KEY AUTOINCREMENT, ownerid INT, m_enable INT, m_type INT, m_index INT, m_file_id INT, m_header TEXT, m_file_id___size INT, m_file_id___create_time DATETIME, m_file_id___downloads INT)')
cursor.execute('CREATE TABLE g2050_box_us_eu (recordid INTEGER PRIMARY KEY AUTOINCREMENT, ownerid INT, m_enable INT, m_type INT, m_index INT, m_file_id INT, m_header TEXT, m_file_id___size INT, m_file_id___create_time DATETIME, m_file_id___downloads INT)')
cursor.execute('INSERT INTO typedata VALUES ("g2050_box_us_eu", "recordid", "intValue"), ("g2050_box_us_eu", "ownerid", "intValue"), ("g2050_box_us_eu", "m_enable", "booleanValue"), ("g2050_box_us_eu", "m_type", "intValue"), ("g2050_box_us_eu", "m_index", "intValue"), ("g2050_box_us_eu", "m_file_id", "intValue"), ("g2050_box_us_eu", "m_header", "binaryDataValue"), ("g2050_box_us_eu", "m_file_id___size", "intValue"), ("g2050_box_us_eu", "m_file_id___create_time", "dateAndTimeValue"), ("g2050_box_us_eu", "m_file_id___downloads", "intValue")')
cursor.execute('CREATE TRIGGER g2050ti_box_us_eu AFTER INSERT ON g2050_box_us_eu BEGIN UPDATE g2050_box_us_eu SET m_file_id___create_time = date(\'now\'), m_file_id___size = 0, m_file_id___downloads = 0 WHERE recordid = NEW.recordid; END')
cursor.execute('CREATE TRIGGER g2050tu_box_us_eu AFTER UPDATE ON g2050_box_us_eu BEGIN UPDATE g2050_box_us_eu SET m_file_id___create_time = date(\'now\') WHERE recordid = NEW.recordid; END')
if not self.table_exists('g2649_bbdx_player'):
cursor.execute('CREATE TABLE g2649_bbdx_player (recordid INT PRIMARY KEY AUTOINCREMENT, stat INT)')
cursor.execute('CREATE TABLE g2649_bbdx_player (recordid INTEGER PRIMARY KEY AUTOINCREMENT, stat INT)')
cursor.execute('INSERT INTO typedata VALUES ("g2649_bbdx_player", "recordid", "intValue"), ("g2649_bbdx_player", "stat", "intValue")')
if not self.table_exists('g2649_bbdx_info'):
cursor.execute('CREATE TABLE g2649_bbdx_info (serialid INT, stat INT, message TEXT)')
cursor.execute('INSERT INTO typedata VALUES ("g2649_bbdx_info", "serialid", "intValue"), ("g2649_bbdx_info", "stat", "intValue"), ("g2649_bbdx_info", "message", "unicodeStringValue")')
if not self.table_exists('g2649_bbdx_search'):
cursor.execute('CREATE TABLE g2649_bbdx_search (recordid INT PRIMARY KEY AUTOINCREMENT, song_name TEXT, creator_name TEXT, average_rating REAL, serialid INT, filestore INT, is_lyric INT, num_ratings INT)')
cursor.execute('CREATE TABLE g2649_bbdx_search (recordid INTEGER PRIMARY KEY AUTOINCREMENT, song_name TEXT, creator_name TEXT, average_rating REAL, serialid INT, filestore INT, is_lyric INT, num_ratings INT)')
cursor.execute('INSERT INTO typedata VALUES ("g2649_bbdx_search", "recordid", "intValue"), ("g2649_bbdx_search", "song_name", "asciiStringValue"), ("g2649_bbdx_search", "creator_name", "asciiStringValue"), ("g2649_bbdx_search", "average_rating", "floatValue"), ("g2649_bbdx_search", "serialid", "intValue"), ("g2649_bbdx_search", "filestore", "intValue"), ("g2649_bbdx_search", "is_lyric", "booleanValue"), ("g2649_bbdx_search", "num_ratings", "intValue")')
# load column info into memory, unfortunately there's no simple way
@ -114,6 +119,7 @@ class StorageHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
data = dom.getElementsByTagName('SOAP-ENV:Body')[0].getElementsByTagName('ns1:' + shortaction)[0]
gameid = str(int(data.getElementsByTagName('ns1:gameid')[0].firstChild.data))
tableid = data.getElementsByTagName('ns1:tableid')[0].firstChild.data
loginticket = data.getElementsByTagName('ns1:loginTicket')[0].firstChild.data
table = 'g' + gameid + '_' + tableid
@ -124,8 +130,6 @@ class StorageHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
ret += '<' + shortaction + 'Response xmlns="http://gamespy.net/sake">'
ret += '<' + shortaction + 'Result>Success</' + shortaction + 'Result>'
# TODO: Actually make GetMyRecords only return *my* records
# ownerid == profileid, ask profile server via login ticket
if shortaction == 'SearchForRecords' or shortaction == 'GetMyRecords' or shortaction == 'GetSpecificRecords':
columndata = data.getElementsByTagName('ns1:fields')[0].getElementsByTagName('ns1:string')
try:
@ -140,8 +144,12 @@ class StorageHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
for c in columns[1:]:
statement += ',' + c
statement += ' FROM ' + table
if shortaction == 'GetMyRecords':
profileid = self.server.gamespydb.get_profileid_from_loginticket(loginticket)
statement += ' WHERE ownerid = ' + str(profileid)
if shortaction == 'GetSpecificRecords':
elif shortaction == 'GetSpecificRecords':
recordids = data.getElementsByTagName('ns1:recordids')[0].getElementsByTagName('ns1:int')
# limit to requested records
@ -193,6 +201,8 @@ class StorageHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
if shortaction == 'UpdateRecord':
recordid = int(data.getElementsByTagName('ns1:recordid')[0].firstChild.data)
profileid = self.server.gamespydb.get_profileid_from_loginticket(loginticket)
columndata = []
values = data.getElementsByTagName('ns1:values')[0]
recordfields = values.getElementsByTagName('ns1:RecordField')
@ -222,22 +232,23 @@ class StorageHTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
statement += columns[0] + ' = ?'
for c in columns[1:]:
statement += ', ' + c + ' = ?'
statement += ' WHERE recordid = ?'
statement += ' WHERE recordid = ? AND ownerid = ?'
rowdata.append( recordid )
rowdata.append( profileid )
elif shortaction == 'CreateRecord':
statement = 'INSERT INTO ' + table + ' ('
statement += columns[0]
for c in columns[1:]:
statement += ', ' + c
statement += ') VALUES (?'
for i in xrange(len(columns)-1):
statement += ', ?'
statement += ')'
for c in columns:
statement += c + ', '
statement += 'ownerid) VALUES ('
for i in xrange(len(columns)):
statement += '?, '
statement += '?)'
rowdata.append( profileid )
else:
logger.log(logging.ERROR, 'Illegal Action %s in database insert/update path!', shortaction)
return
cursor = self.server.db.cursor()
cursor.execute(statement, tuple(rowdata))