From: <ch...@us...> - 2010-07-30 00:07:35
|
Revision: 347 http://virtplayground.svn.sourceforge.net/virtplayground/?rev=347&view=rev Author: chozone Date: 2010-07-30 00:07:29 +0000 (Fri, 30 Jul 2010) Log Message: ----------- [client] * Changed (fake login) user/pass to 'test'/'123' * Now connects with 'localhost' (temp!) [server] * Added base: * Loads config (asks user for values first time) * Opens database connection * Callback checks in database for logins [server-core] * Error corrections in comments * Modified code/comments for conversion to tabs with a width of 4 characters. * The server now uses select for it's main (listening) socket. socket.accept() blocks quite aggressively on Windows, making it impossible to close the server correctly. Using select fixes this. Modified Paths: -------------- trunk/client/VP.py trunk/client/playground.py trunk/server/core/callback.py trunk/server/core/functions.py trunk/server/core/parser.py trunk/server/core/server.py Added Paths: ----------- trunk/server/VPS.py trunk/server/callback.py trunk/server/database.py trunk/server/functions.py Modified: trunk/client/VP.py =================================================================== --- trunk/client/VP.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/client/VP.py 2010-07-30 00:07:29 UTC (rev 347) @@ -47,7 +47,7 @@ Callback(self.sh)) self.changestatus("connecting") - self.sh['client'].connect('vp.bluewolf.nl', 6653) + self.sh['client'].connect('localhost', 6653) # Wait for all the events to come Modified: trunk/client/playground.py =================================================================== --- trunk/client/playground.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/client/playground.py 2010-07-30 00:07:29 UTC (rev 347) @@ -22,7 +22,7 @@ if ev.type == KEYDOWN and ev.unicode == "\r": # Fake login self.drawlogin("logging in") - self.sh['client'].login("BlueWolf", "mypass") + self.sh['client'].login("test", "123") def changestatus(self, status): Added: trunk/server/VPS.py =================================================================== --- trunk/server/VPS.py (rev 0) +++ trunk/server/VPS.py 2010-07-30 00:07:29 UTC (rev 347) @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +## This file is part of Virtual Playground +## Copyright (c) 2009-2010 Jos Ratsma + Koen Koning + +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import core +from functions import * +from callback import Callback + + +server = core.Server(config, Callback()) +server.start_server() + +# Now we sit back and let the server do it's stuff. Only stop at +# Keyboardinterrupts (^C). +# TODO: *some* interactivity here? (so you can type in commands) +try: + while 1: + time.sleep(100) + +except KeyboardInterrupt: + print + + +server.exit() +sys.exit() Added: trunk/server/callback.py =================================================================== --- trunk/server/callback.py (rev 0) +++ trunk/server/callback.py 2010-07-30 00:07:29 UTC (rev 347) @@ -0,0 +1,48 @@ +## This file is part of Virtual Playground +## Copyright (c) 2009-2010 Jos Ratsma + Koen Koning + +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +from core import Callback as BaseCallback + +from functions import * + +class Callback(BaseCallback): + def data_received(self, cid, data): + print " --> " + cid + ": " + repr(data) + def data_send(self, cid, data): + print " <-- " + cid + ": " + repr(data) + def debug_crash(self, traceback): + print "\n*** Crash ***\n\n%s\n" % traceback + + + def server_online(self, clients): + print "*** SERVER ONLINE ***" + + def enters_vp(self, cid): + " > %s"%cid + def enters_vp(self, cid): + " < %s"%cid + + def check_login(self, usr, pwd): + db.execute("SELECT `username` FROM `users` WHERE \ + `username`=%s AND \ + `password`=%s", (usr, pwd)) + print "* Login %s %s" % (usr, pwd) + result = db.fetchone() + if result is None: + return False + else: + return result['username'] \ No newline at end of file Modified: trunk/server/core/callback.py =================================================================== --- trunk/server/core/callback.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/server/core/callback.py 2010-07-30 00:07:29 UTC (rev 347) @@ -16,24 +16,31 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. class Callback: - def server_online(self): + def server_online(self, clients): """ Called when the server is online and ready to accept incoming - connections. This means it has successfully bounded itself to a - port. Most of the times this will be called immediately after - calling Server.start() + connections. This means it has successfully bounded itself to a port. + Most of the times this will be called immediately after calling + Server.start() + clients: + This is a dict where the server will store all the clients. The + server itself stores the socket-class and status of the user here. + However, you can add as much of your own data as you want, as long + as you don't overwrite any existing keys. So you probably want to + save a reference to this dict for easy user management. - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass def connection_opened(self, cid, client, host, port): """ - Called when a new client connects and we accepted the - connection. You can, however, still kill the connection by - returning True in this function. + Called when a new client connects and we accepted the connection. + You can, however, still kill the connection by returning True in this + function. cid: The unique ID for this connection (connection-id). @@ -45,8 +52,8 @@ The current port for this connection. - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass @@ -75,8 +82,8 @@ get the precise error - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass @@ -90,16 +97,15 @@ current_connections: Amount of current open connections max_connections: - This is the same as in the config - 'max_connections'. + This is the same as in the config 'max_connections'. host: The IP adress for this user. port: The current port for this connection. - This is placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass @@ -112,8 +118,8 @@ The unique ID for this connection (connection-id) - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass @@ -128,57 +134,57 @@ Dict with the data that will be send. - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass - def debug_crash(self, tracback): + def debug_crash(self, traceback): """ - Usefull for debugging. Normally, when the parser (our any code - in the parser, like the callback) crashes, the connection will - be kicked and the error will be ignored. If you want to know the - precise error, use this function to get the trackback + Usefull for debugging. Normally, when the parser (or any code in the + parser, like the callback) crashes, the connection will be kicked and + the error will be ignored. If you want to know the precise error, use + this function to get the trackback traceback: A string... with a traceback, duh :-) - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ pass def check_login(self, usr, pwd): """ - This is used to verify the user's login. Return the real - username* when it's correct and False when it's not. This - function will return False by default. + This is used to verify the user's login. Return the real username* when + it's correct and False when it's not. This function will return False + by default. - * This is in case you decide to not make the username case - intensive. Now the clients knows the real username + * This is in case you decide to not make the username case sensetive. + Now the clients knows the real username. usr: The username pwd: The (double) sha-ed password - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ return False def may_login(self, username, screenname, ip, bot, bots): """ - This is called after (a succesfull) callback.check_login. Use - this to block certain users or IP's or block an additional bot - when the users reached the limit of connected bots. + This is called after (a succesfull) callback.check_login. Use this to + block certain users or IP's or block an additional bot when the users + reached the limit of connected bots. - Return True when the user (or bot) may log in and False when it - may not. This will send an "not allowed" error. If you wish to - send an other error, return the error. An example may be: + Return True when the user (or bot) may log in and False when it may not. + This will send an "not allowed" error. If you wish to send an other + error, return the error. An example may be: * "login not allowed" - Login is not allowed right now * "bot limit reached" - User has to much bots running * "login blocked" - User is blocked @@ -188,8 +194,8 @@ username: The username for this user / owner for this bot screenname: - The name the users see. This is only different from - username when a bot logs in + The name the users see. This is only different from username when a + bot logs in ip: The IP-adress this user has bot: @@ -198,8 +204,8 @@ List with the cids of all active active bots for this user. - This is a placeholder. If you want to catch this event, - overwrite this in your own callback. + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ return True @@ -209,7 +215,12 @@ cid: The unique ID for this connection. (connection-id) + + + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ + pass def leaves_vp(self, cid): """ @@ -217,4 +228,9 @@ cid: The unique ID for this connection. (connection-id) + + + This is a placeholder. If you want to catch this event, overwrite this + in your own callback class. """ + pass Modified: trunk/server/core/functions.py =================================================================== --- trunk/server/core/functions.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/server/core/functions.py 2010-07-30 00:07:29 UTC (rev 347) @@ -24,20 +24,20 @@ Examples of some expression are: Exact match: - '1.0.3' match ONLY that version (True if version equal given) + '1.0.3' match ONLY that version (True if version equals given) Greater than: - '>0.9.48' match all versions above version '0.9.48', AND '0.9.48' - itself (True if same or above given) + '>0.9.48' match all versions above version '0.9.48', AND '0.9.48' itself + (True if same or above given) Lower than: - '<10.4.0' match all versions below version '10.4.0', AND '10.4.0' - itself (True if same or below given) + '<10.4.0' match all versions below version '10.4.0', AND '10.4.0' itself + (True if same or below given) Range: - '0.9.3-0.9.11' match all versions between '0.9.3' and '0.9.11', - including those values themselves (True if same or - between two values) + '0.9.3-0.9.11' match all versions between '0.9.3' and '0.9.11', including + those values themselves + (True if same or between two values) If all conditions are met, this function will return True, otherwise @@ -49,25 +49,25 @@ This is because it's not a decimal number. """ - # Filter out invalid versions/expressions, so this function works - # correctly later on. + # Filter out invalid versions/expressions, so this function works correctly + # later on. if not expr: return True if not version: return False version = str(version) expr = str(expr) try: [int(i) for i in version.split('.')] - except ValueError: raise ValueError, "No valid version: '%s'"%version + except ValueError: raise ValueError("No valid version: '%s'"%version) try: [[int(i) for i in p.split('.')] \ for p in expr.strip('<>').split('-')] - except ValueError: raise ValueError, "No valid expression: '%s'"%expr + except ValueError: raise ValueError("No valid expression: '%s'"%expr) # Our first real tests. If version matches expression, we return True. # Also, if the expression, stripped of '<' and '>' characters at the # beginning (or end...) matched our version, we return True. - # This is for the 'Greater/Lower OR EQUAL than' behaviour of those + # This is for the 'Greater/Lower OR EQUAL than' behaviour of those # characters. if version == expr: return True if version == expr.strip('<>'): return True @@ -83,10 +83,9 @@ c1 = [int(i) for i in version.split('.')] c2 = [int(i) for i in expr.split('.')] - # Loops through major, minor, revision, in that order, and - # it tests whether the version is higher/lower. Note that if the - # version are the same, it has already been filtered out, before - # this if block. + # Loops through major, minor, revision, in that order, and it tests + # whether the version is higher/lower. Note that if the version are the + # same, it has already been filtered out, before this if block. for p1, p2 in zip(c1, c2): if p1 > p2: return True if p1 < p2: return False @@ -103,10 +102,9 @@ c1 = [int(i) for i in version.split('.')] c2 = [int(i) for i in expr.split('.')] - # Loops through major, minor, revision, in that order, and - # it tests whether the version is higher/lower. Note that if the - # version are the same, it has already been filtered out, before - # this if block. + # Loops through major, minor, revision, in that order, and it tests + # whether the version is higher/lower. Note that if the version are the + # same, it has already been filtered out, before this if block. for p1, p2 in zip(c1, c2): if p1 < p2: return True if p1 > p2: return False @@ -116,8 +114,8 @@ # Get the two versions r1, r2 = expr.split('-') - # Use this function to see if it's higher than the first, and - # lower than the second value :-) + # Use this function to see if it's higher than the first, and lower + # than the second value :-) if check_version(version, '>' + r1) \ and check_version(version, '<' + r2): return True Modified: trunk/server/core/parser.py =================================================================== --- trunk/server/core/parser.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/server/core/parser.py 2010-07-30 00:07:29 UTC (rev 347) @@ -163,13 +163,11 @@ # Check for double logins if msg['bot'] == False: # Just an ordinary user - if self._check_double_user(False, username, - data) == False: + if self._check_double_user(False, username, data) == False: return else: # Client is a bot - if self._check_double_user(True, screenname, - data) == False: + if self._check_double_user(True, screenname, data) == False: return Modified: trunk/server/core/server.py =================================================================== --- trunk/server/core/server.py 2010-07-29 22:04:01 UTC (rev 346) +++ trunk/server/core/server.py 2010-07-30 00:07:29 UTC (rev 347) @@ -15,7 +15,7 @@ ## along with this program; if not, write to the Free Software ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -import simplejson, socket, threading, time, random, sys, hashlib +import simplejson, socket, threading, time, random, sys, hashlib, select from functions import * from parser import Parser @@ -30,9 +30,8 @@ config: - This should be a dict with settings for the server. See the - bottom of this documentation for a list of all possible - settings. + This should be a dict with settings for the server. See the bottom of + this documentation for a list of all possible settings. callback_class: The callback class will be used to notify you for certain events @@ -47,22 +46,21 @@ The settings: -host: - Host to which the server binds itself. The default is an - empty string, an empty string, which means everyone can - connect to the server. + Host to which the server binds itself. The default is an empty + string, an empty string, which means everyone can connect + to the server. -port: - The port the server should listen on. Should be int - between 1 and 65535. Note that everything lower than 100 - usually needs to be run as root under Unix/Linux. + The port the server should listen on. Should be int between + 1 and 65535. Note that everything lower than 100 usually needs to + be run as root under Unix/Linux. Default is 5162. -max_connections: - Maximum amount of clients that can be connected - simultaneously. If this number is exceeded, the new - connection will dropped, unless specified otherwise - (see callback `connection_limit_exceeded`). Should be - int. If this value is either None or 0, there will be no + Maximum amount of clients that can be connected simultaneously. + If this number is exceeded, the new connection will dropped, unless + specified otherwise (see callback `connection_limit_exceeded`). + Should be int. If this value is either None or 0, there will be no limit. Default is 0. But it is wise to specify a limit. -rsa_bits: @@ -70,23 +68,21 @@ More = more secure but slower to generate. Default is 64 -bot_names: - How the name for a bot should be. Use %s where the - suggested name should be. Default is [%s]. When a bot - logs in as "test", it will be displayed as "[test]". - Choose something that won't interfere with existing - users. + How the name for a bot should be. Use %s where the suggested name + should be. Default is [%s]. When a bot logs in as "test", it will + be displayed as "[test]". Choose something that won't interfere + with existing users. -viewport: - A tuple of the client's viewport in pixels. This is very - important because it's used to calculate which objects - and people the client is able to see. By default this - is (1000, 700). + A tuple of the client's viewport in pixels. This is very important + because it's used to calculate which objects and people the client + is able to see. By default this is (1000, 700). -max_speed: The amount of pixels a user may move in a certain time. - The default is (50, 1.0) which basically means 50px per - 1 second. When a user exceeds this, the server will just - reset his position to his last known location. + The default is (50, 1.0) which basically means 50px per 1 second. + When a user exceeds this, the server will just reset his position + to his last known location. """ @@ -130,16 +126,14 @@ in the config. """ - #Isn't the server running already? + # Isn't the server running already? if self.__sock: raise ConnectionError("The server is already online!") - #Load our server socket - self.__sock = socket.socket(socket.AF_INET, - socket.SOCK_STREAM) - #Configure it to re-use the previous one - self.__sock.setsockopt(socket.SOL_SOCKET, - socket.SO_REUSEADDR, 1) + # Load our server socket + self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # Configure it to re-use the previous one + self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.start() #For more adventures of the socket, see `run` @@ -149,11 +143,11 @@ Used by threading, not for external usage. """ - #Try to claim the pre-specified port + # Try to claim the pre-specified port while 1: try: self.__sock.bind((self.__sh['config']['host'], - self.__sh['config']['port'])) + self.__sh['config']['port'])) break except: time.sleep(1) @@ -161,25 +155,31 @@ self.__sock.listen(20) self.__call.server_online(self.clients) - #Infinite loop that will wait for incomming connections - while 1: - try: sock, addr = self.__sock.accept() - except: + # Infinite loop that will wait for incomming connections + while 1: + r,w,e = select.select([self.__sock], [], [], 10) + + if not r: + # No new clients trying to connect, better luck next time + continue + if not self.__sock: # Server has gone offline return + sock, addr = r[0].accept() + + if self.__sh['config']['max_connections'] and \ - len(self.clients) >= \ - self.__sh['config']['max_connections']: - #We exceeded our connection limit, but maybe - #this is a special occasion? Send callback! + len(self.clients) >= self.__sh['config']['max_connections']: + # We exceeded our connection limit, but maybe this is a special + # occasion? Send callback! if not self.__call.connection_limit_exceeded( - len(self.clients), - self.__sh['config']['max_connections'], - addr[0], addr[1]): + len(self.clients), + self.__sh['config']['max_connections'], + addr[0], addr[1]): - #We're full, kick him out - #Tell him we're full + # We're full, kick him out + # Tell him we're full data = simplejson.dumps({ "disconnect":{"reason":"full"} }) @@ -192,18 +192,16 @@ # Create unique client-id cid = hashlib.sha1(addr[0] + str(addr[1])).hexdigest()[:8] while cid in self.clients: - cid = hashlib.sha1(addr[0] + str(addr[1]) + - str(random.random())).hexdigest()[:8] + cid = hashlib.sha1(addr[0] + str(addr[1]) + + str(random.random())).hexdigest()[:8] self.clients[cid] = { "status": "", - "con": Client(cid, sock, self.__sh, - self.__parse) + "con": Client(cid, sock, self.__sh, self.__parse) } - if self.__call.connection_opened(cid, - self.clients[cid], *addr): - #User returned True -> drop user + if self.__call.connection_opened(cid, self.clients[cid], *addr): + # User returned True -> drop user self.clients[cid]['con'].close() continue @@ -211,9 +209,9 @@ def exit(self, reason = "gone offline"): """ - Will shutdown the server and sends an 'gone offline' message to - all connected clients and then closes their connection. Use this - when you're about to shutdown your server. + Will shutdown the server and sends an 'gone offline' message to all + connected clients and then closes their connection. Use this when + you're about to shutdown your server. This will call the callback.connection_closed for all clients! Note that you'll not be able to start the server again @@ -225,6 +223,7 @@ for client in self.clients.values(): client['con'].close_msg(reason) + @@ -255,13 +254,12 @@ Will create a traceback and call the callback """ - #Get some debugging info + # Get some debugging info et, ev, tb = sys.exc_info() traceback = "" while tb: co = tb.tb_frame.f_code - traceback += str(co.co_filename) + ':' + \ - str(tb.tb_lineno) + '\n' + traceback += str(co.co_filename) + ':' + str(tb.tb_lineno) + '\n' tb = tb.tb_next traceback += ev.__class__.__name__ + ': ' + str(ev) @@ -294,19 +292,18 @@ Used by threading, not for external usage. """ - #Client must ping (at least) every 30 seconds. So we set a - #timeout of 45 seconds. + # Client must ping (at least) every 30 seconds. So we set a + # timeout of 45 seconds. self.__sock.settimeout(45) - # Before the client can log in, we first need to create a - # rsa-key + # Before the client can log in, we first need to create a rsa-key public, private = rsa.gen_pubpriv_keys( self.__sh['config']['rsa_bits']) self.__clients[self.__cid]['rsa'] = private self.send("rsa", {"public": public}) - #Infinite loop that receives data + # Infinite loop that receives data buffer = '' while 1: try: @@ -322,7 +319,7 @@ return buffer += data - #Each dataset must end with a delimiter: chr(1) + # Each dataset must end with a delimiter: chr(1) if chr(1) in buffer: data = buffer.split(chr(1)) buffer = data[-1] @@ -330,8 +327,7 @@ for msg in data: try: - self.__parser(self.__cid, - simplejson.loads(msg)) + self.__parser(self.__cid, simplejson.loads(msg)) except Exception, Er: self.__parser_crash() @@ -362,8 +358,8 @@ def close_msg(self, reason): """ - Same as Client.close, but this will send the reason to the - client before closing + Same as Client.close, but this will send the reason to the client + before closing. """ if self.is_online == False: return @@ -385,8 +381,8 @@ def send(self, data_header, data_body = {}): """ Sends `data_body` of type `data_header` to the client. It will - automatically be encoded as JSON, and the delimeter character - (chr(1)) will be send automatically too. + automatically be encoded as JSON, and the delimeter character (chr(1)) + will be send automatically too. `data_header` is a string, `data_body` a dict. """ self.__call.data_send(self.__cid, {data_header:data_body}) Added: trunk/server/database.py =================================================================== --- trunk/server/database.py (rev 0) +++ trunk/server/database.py 2010-07-30 00:07:29 UTC (rev 347) @@ -0,0 +1,83 @@ +## Copyright (c) 2009 Koen Koning + Thomas van Ophem + +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +import sys + +try: import MySQLdb +except: sys.exit("ERROR: You need the MySQLdb-module for this to work!") + +class DB(): + #Let's initialize the database + def __init__(self, host, database, user, passwd): + self.host = host + self.database = database + self.user = user + self.passwd = passwd + + self._connect() + + #Let's connect to the database.. + def _connect(self): + try: + self.dbcon = MySQLdb.Connect( + host=self.host, + user=self.user, + passwd=self.passwd, + db = self.database) + self.db = self.dbcon.cursor(MySQLdb.cursors.DictCursor) + except: + #sys.exit("Could not connect to the database!") + raise self.DBConnectionError("Could not connect to the database!") + + def __getattr__(self, attr): + """ + Called when function is not here in our class. + We pass everything through to our MySQLdb + """ + def exc (*arg): + """ + Will return the real function, from MySQLdb. + Will ping before every command, + so it will automatically reconnect. + """ + + # Uncomment for mysql-debugging! + #print '\tMySQLdb.' + attr + repr(arg) + + func = getattr(self.db, attr) + try: + dbfunc = func(*arg) + except MySQLdb.OperationalError, message: + if message[0] == 2006: #Mysql has gone away + self._connect() + func = getattr(self.db, attr) + dbfunc = func(*arg) + else: #Some other error we don't care about + raise MySQLdb.OperationalError, message + + return dbfunc + + return exc + + + + class DBConnectionError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + Added: trunk/server/functions.py =================================================================== --- trunk/server/functions.py (rev 0) +++ trunk/server/functions.py 2010-07-30 00:07:29 UTC (rev 347) @@ -0,0 +1,71 @@ +## This file is part of Virtual Playground +## Copyright (c) 2009-2010 Jos Ratsma + Koen Koning + +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. + +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import os, sys, time + +import database + +try: from configobj import ConfigObj +except: sys.exit("ERROR: You need the configobj-module for this to work!") + +def config_defaults(config): + if 'database' not in config: + config['database'] = {} + + intro_text = """ +Some settings are missing from the config. Because these settings are required, +We will now ask for them in this console. Please type in the correct value, and +press enter. It will be automatically written to the config. +""" + + if not 'host' in config['database']: + if intro_text: + print intro_text + intro_text = None + config['database']['host'] = raw_input("Database host: ") + if not 'database' in config['database']: + if intro_text: + print intro_text + intro_text = None + config['database']['database'] = raw_input("Database name: ") + if not 'user' in config['database']: + if intro_text: + print intro_text + intro_text = None + config['database']['user'] = raw_input("Database user: ") + if not 'password' in config['database']: + if intro_text: + print intro_text + intro_text = None + config['database']['password'] = raw_input("Database password: ") + + + +config = ConfigObj(os.path.join(sys.path[0], 'config')) +config_defaults(config) +config.write() + +print "Connecting to database..." +db = database.DB( config['database']['host'], + config['database']['database'], + config['database']['user'], + config['database']['password']) +print "Connected to database `%s` on `%s`" % (config['database']['database'], + config['database']['host']) + + + \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |