예제 #1
0
    def onLoadConfig(self):
        """
        Load plugin configuration.
        """
        try:

            if self.config.get('settings', 'output_file')[0:6] == 'ftp://':
                self._ftpstatus = True
                self._ftpinfo = functions.splitDSN(self.config.get('settings', 'output_file'))
                self.debug('using custom remote path for settings/output_file: %s/%s' % (self._ftpinfo['host'], self._ftpinfo['path']))
            else:
                self._outputFile = self.config.getpath('settings', 'output_file')
                self.debug('using custom local path for settings/output_file: %s' % self._outputFile)

        except NoOptionError:
            self._outputFile = os.path.normpath(os.path.expanduser(self._outputFile))
            self.warning('could not find settings/output_file in config file, using default: %s' % self._outputFile)

        self._tkPlugin = self.console.getPlugin('tk')

        try:
            self._interval = self.config.getint('settings', 'interval')
            self.debug('using custom value for settings/interval: %s' % self._interval)
        except NoOptionError:
            self.warning('could not find settings/interval in config file, using default: %s' % self._interval)
        except ValueError, e:
            self.error('could not load settings/interval config value: %s' % e)
            self.debug('using default value (%s) for settings/interval' % self._interval)
예제 #2
0
    def onLoadConfig(self):
        if self.config.get('settings','output_file')[0:6] == 'ftp://':
                self._ftpinfo = functions.splitDSN(self.config.get('settings','output_file'))
                self._ftpstatus = True
        else:        
                self._outputFile = os.path.expanduser(self.config.get('settings', 'output_file'))
                
        self._tkPlugin = self.console.getPlugin('tk')
        self._interval = self.config.getint('settings', 'interval')
        try:
            self._enableDBsvarSaving = self.config.getboolean('settings', 'enableDBsvarSaving')
        except:
            self._enableDBsvarSaving = False

        try:
            self._enableDBclientSaving = self.config.getboolean('settings', 'enableDBclientSaving')
        except:
            self._enableDBclientSaving = False

        if self._enableDBsvarSaving:
            sql = "CREATE TABLE IF NOT EXISTS `current_svars` (`id` int(11) NOT NULL auto_increment,`name` varchar(255) NOT NULL,`value` varchar(255) NOT NULL, PRIMARY KEY  (`id`), UNIQUE KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"
            self.console.storage.query(sql)
        if self._enableDBclientSaving:
            sql = "CREATE TABLE IF NOT EXISTS `current_clients` (`id` INT(3) NOT NULL AUTO_INCREMENT,`Updated` VARCHAR( 255 ) NOT NULL ,`Name` VARCHAR( 255 ) NOT NULL ,`Level` VARCHAR( 255 ) NOT NULL ,`DBID` VARCHAR( 255 ) NOT NULL ,`CID` VARCHAR( 255 ) NOT NULL ,`Joined` VARCHAR( 255 ) NOT NULL ,`Connections` VARCHAR( 255 ) NOT NULL ,`State` VARCHAR( 255 ) NOT NULL ,`Score` VARCHAR( 255 ) NOT NULL ,`IP` VARCHAR( 255 ) NOT NULL ,`GUID` VARCHAR( 255 ) NOT NULL ,`PBID` VARCHAR( 255 ) NOT NULL ,`Team` VARCHAR( 255 ) NOT NULL ,`ColorName` VARCHAR( 255 ) NOT NULL, PRIMARY KEY (`id`)) ENGINE = MYISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"
            self.console.storage.query(sql)

        if self._cronTab:
            # remove existing crontab
            self.console.cron - self._cronTab

        self._cronTab = b3.cron.PluginCronTab(self, self.update, '*/%s' % self._interval)
        self.console.cron + self._cronTab
 def __init__(self, dsn, console):
     self.console = console
     self._lock = thread.allocate_lock()
     self.db = None
     self.dsn = dsn
     self.dsnDict = functions.splitDSN(self.dsn)
     self.connect()
예제 #4
0
    def __init__(self, config):
        """
        Object constructor.
        :param config: The main configuration file
        """
        b3.console = self
        self._timeStart = self.time()
        logging.basicConfig(level=b3.output.VERBOSE2,
                            format='%(asctime)s\t%(levelname)s\t%(message)s')
        self.log = logging.getLogger('output')
        self.config = config

        if isinstance(config,
                      (b3.config.XmlConfigParser, b3.config.CfgConfigParser)):
            self.config = b3.config.MainConfig(config)
        elif isinstance(config, b3.config.MainConfig):
            self.config = config
        else:
            self.config = b3.config.MainConfig(b3.config.load(config))

        self.storage = SqliteStorage("sqlite://:memory:",
                                     splitDSN("sqlite://:memory:"), self)
        self.storage.connect()
        self.clients = b3.clients.Clients(self)
        self.game = b3.game.Game(self, "fakeGame")
        self.game.mapName = 'ut4_turnpike'
        self.cvars = {}
        self._handlers = defaultdict(list)

        self.input = StringIO()
예제 #5
0
 def init_thread(self, ftpfiledsn):
     self.ftpconfig = functions.splitDSN(ftpfiledsn)
     # the '/' is not part of the uri-path according to RFC 1738 3.1. Common Internet Scheme Syntax
     self.url_path = self.ftpconfig['path'][1:]
     thread1 = threading.Thread(target=self.update)
     self.info("starting ftpytail thread")
     thread1.start()
예제 #6
0
    def __init__(self, config):
        """
        Object constructor.
        :param config: The main configuration file
        """
        b3.console = self
        self._timeStart = self.time()
        logging.basicConfig(level=b3.output.VERBOSE2, format='%(asctime)s\t%(levelname)s\t%(message)s')
        self.log = logging.getLogger('output')
        self.config = config

        if isinstance(config, b3.config.XmlConfigParser) or isinstance(config, b3.config.CfgConfigParser):
            self.config = b3.config.MainConfig(config)
        elif isinstance(config, b3.config.MainConfig):
            self.config = config
        else:
            self.config = b3.config.MainConfig(b3.config.load(config))

        self.storage = SqliteStorage("sqlite://:memory:", splitDSN("sqlite://:memory:"), self)
        self.storage.connect()
        self.clients = b3.clients.Clients(self)
        self.game = b3.game.Game(self, "fakeGame")
        self.game.mapName = 'ut4_turnpike'
        self.cvars = {}
        self._handlers = {}
        
        if not self.config.has_option('server', 'punkbuster') or self.config.getboolean('server', 'punkbuster'):
            self.PunkBuster = b3.parsers.punkbuster.PunkBuster(self)
        
        self.input = StringIO.StringIO()
        self.working = True
예제 #7
0
 def initThread(self, httpfileDSN):
     self.httpconfig = functions.splitDSN(httpfileDSN)
     self.url = httpfileDSN
     self.stop_event.clear()
     self.thread1 = threading.Thread(target=self.update)
     self.info("Starting httpytail thread")
     self.thread1.start()
예제 #8
0
 def initThread(self, httpfileDSN):
     self.httpconfig = functions.splitDSN(httpfileDSN)
     self.url = httpfileDSN
     self.stop_event.clear()
     self.thread1 = threading.Thread(target=self.update)
     self.info("Starting httpytail thread")
     self.thread1.start()
예제 #9
0
 def update(self):
     self.debug('Sending heartbeat to B3 master...')
     socket.setdefaulttimeout(10)
     
     plugins = []
     for pname in self.console._pluginOrder:
         plugins.append("%s/%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', 'Unknown Version')))
       
     try:
         database = functions.splitDSN(self.console.storage.dsn)['protocol']
     except:
         database = "unknown"
         
     version = getattr(b3, '__version__', 'Unknown Version')
     if b3.functions.main_is_frozen():
         version += " win32"
         
     info = {
         'action' : 'update',
         'ip' : self.console._publicIp,
         'port' : self.console._port,
         'rconPort' : self.console._rconPort,
         'version' : version,
         'parser' : self.console.gameName,
         'parserversion' : getattr(getModule(self.console.__module__), '__version__', 'Unknown Version'),
         'database' : database,
         'plugins' : ','.join(plugins),
         'os' : os.name,
         'python_version': sys.version
     }
     #self.debug(info)
     self.sendInfo(info)
예제 #10
0
  def update(self):
    self.debug('Sending heartbeat to B3 master...')
    
    
    def getModule(name):
      mod = __import__(name)
      components = name.split('.')
      for comp in components[1:]:
        mod = getattr(mod, comp)
      return mod
      
    plugins = []
    for pname in self.console._pluginOrder:
      plugins.append("%s/%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', 'Unknown Version')))
      
    info = {
      'ip' : self.console._publicIp,
      'port' : self.console._port,
      'version' : getattr(b3, '__version__', 'Unknown Version'),
      'parser' : self.console.gameName,
      'parserversion' : getattr(getModule(self.console.__module__), '__version__', 'Unknown Version'),
      'database' : functions.splitDSN(self.console.storage.dsn)['protocol'],
      'plugins' : ','.join(plugins),
      'os' : os.name
    }
    #self.debug(info)

    f = urllib.urlopen('%s?%s' % (self._url, urllib.urlencode(info)))
    self.debug(f.read())
    f.close()

      
예제 #11
0
    def startup(self):
        self.debug("startup()")
        
        # create the 'Server' client
        self.clients.newClient('Server', guid='Server', name='Server', hide=True, pbid='Server', team=b3.TEAM_UNKNOWN)

        if self.config.has_option('server','inifile'):
            # open ini file
            ini_file = self.config.get('server','inifile')
            if ini_file[0:6] == 'ftp://':
                    self.ftpconfig = functions.splitDSN(ini_file)
                    self._ini_file = 'ftp'
                    self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('Getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input  = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug('Incorrect ini file or no ini file specified, map commands other than nextmap not available')
            
        # start crontab to trigger playerlist events
        self._cronTab = b3.cron.CronTab(self.retrievePlayerList, second='*/%s' % self._playerlistInterval)
        self.cron + self._cronTab

        # add specific events
        self.Events.createEvent('EVT_CLIENT_SQUAD_SAY', 'Squad Say')
        self.Events.createEvent('EVT_SERVER_SAY', 'Server Chatter')
        self.Events.createEvent('EVT_CLIENT_CLAN_CHANGE', 'Client Clan Change')
예제 #12
0
    def onLoadConfig(self):
        """
        Load plugin configuration.
        """
        try:

            if self.config.get('settings', 'output_file')[0:6] == 'ftp://':
                self._ftpstatus = True
                self._ftpinfo = functions.splitDSN(self.config.get('settings', 'output_file'))
                self.debug('using custom remote path for settings/output_file: %s/%s' % (self._ftpinfo['host'], self._ftpinfo['path']))
            else:
                self._outputFile = self.config.getpath('settings', 'output_file')
                self.debug('using custom local path for settings/output_file: %s' % self._outputFile)

        except NoOptionError:
            self._outputFile = os.path.normpath(os.path.expanduser(self._outputFile))
            self.warning('could not find settings/output_file in config file, using default: %s' % self._outputFile)

        self._tkPlugin = self.console.getPlugin('tk')

        try:
            self._interval = self.config.getint('settings', 'interval')
            self.debug('using custom value for settings/interval: %s' % self._interval)
        except NoOptionError:
            self.warning('could not find settings/interval in config file, using default: %s' % self._interval)
        except ValueError, e:
            self.error('could not load settings/interval config value: %s' % e)
            self.debug('using default value (%s) for settings/interval' % self._interval)
 def setUp(self):
     """this method is called before each test"""
     B3TestCase.setUp(self)
     self.storage = self.console.storage = SqliteStorage(
         'sqlite://' + SQLITE_DB, splitDSN('sqlite://' + SQLITE_DB),
         self.console)
     self.storage.connect()
예제 #14
0
 def __init__(self, dsn, console):
     self.console = console
     self._lock = thread.allocate_lock()
     self.db = None
     self.dsn = dsn
     self.dsnDict = functions.splitDSN(self.dsn)
     self.connect()
예제 #15
0
    def onLoadConfig(self):
        """
        Load plugin configuration.
        """
        try:

            if self.config.get("settings", "output_file")[0:6] == "ftp://":
                self._ftpstatus = True
                self._ftpinfo = functions.splitDSN(self.config.get("settings", "output_file"))
                self.debug(
                    "using custom remote path for settings/output_file: %s/%s"
                    % (self._ftpinfo["host"], self._ftpinfo["path"])
                )
            else:
                self._outputFile = self.config.getpath("settings", "output_file")
                self.debug("using custom local path for settings/output_file: %s" % self._outputFile)

        except NoOptionError:
            self._outputFile = os.path.normpath(os.path.expanduser(self._outputFile))
            self.warning("could not find settings/output_file in config file, using default: %s" % self._outputFile)

        self._tkPlugin = self.console.getPlugin("tk")

        try:
            self._interval = self.config.getint("settings", "interval")
            self.debug("using custom value for settings/interval: %s" % self._interval)
        except NoOptionError:
            self.warning("could not find settings/interval in config file, using default: %s" % self._interval)
        except ValueError, e:
            self.error("could not load settings/interval config value: %s" % e)
            self.debug("using default value (%s) for settings/interval" % self._interval)
예제 #16
0
 def init_thread(self, ftpfiledsn):
     self.ftpconfig = functions.splitDSN(ftpfiledsn)
     # the '/' is not part of the uri-path according to RFC 1738 3.1. Common Internet Scheme Syntax
     self.url_path = self.ftpconfig['path'][1:]
     thread1 = threading.Thread(target=self.update)
     self.info("starting ftpytail thread")
     thread1.start()
예제 #17
0
    def startup(self):
        """
        Called after the parser is created before run().
        """
        self.debug("startup")
        # create the 'Admin' client
        self.clients.newClient('Admin',
                               guid='Server',
                               name='Admin',
                               hide=True,
                               pbid='Server',
                               team=b3.TEAM_UNKNOWN)
        if self.config.has_option('server', 'ro2admin'):
            self.username = self.config.get('server', 'ro2admin')
        else:
            self.username = "******"

        if self.config.has_option('server', 'inifile'):
            # open ini file
            ini_file = self.config.get('server', 'inifile')
            if ini_file[0:6] == 'ftp://':
                self.ftpconfig = functions.splitDSN(ini_file)
                self._ini_file = 'ftp'
                self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug(
                'Incorrect ini file or no ini file specified: map commands other than nextmap not available'
            )

        self.cron.add(
            b3.cron.CronTab(self.retrievePlayerList,
                            second='*/%s' % self._playerlistInterval))

        self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
        self.headers = {
            'User-Agent': self.user_agent,
            "Accept":
            "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "en-us,en;q =0.5",
            "Content-type": "application/x-www-form-urlencoded",
            "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
            "Referer": ''
        }

        self.site = self._publicIp + ':' + str(self._rconPort)
        self.login_page = "ServerAdmin"
        self.password = self._rconPassword
        self.password_hash = "$sha1$%s" % hashlib.sha1(
            "%s%s" % (self.password, self.username)).hexdigest()
        self.url = "http://%s/%s" % (self.site, self.login_page)
예제 #18
0
 def onLoadConfig(self):
     if self.config.get('settings','output_file')[0:6] == 'ftp://':
         self._ftpinfo = functions.splitDSN(self.config.get('settings','output_file'))
         self._ftpstatus = True
     else:        
         self._outputFile = os.path.expanduser(self.config.get('settings', 'output_file'))
     self._cvars = [var.strip() for var in self.config.get('settings', 'cvars').split(',')]
     self.dump = self.config.get('settings','time').split(':')
예제 #19
0
    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug('Sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            plugins.append(
                "%s/%s" %
                (pname,
                 getattr(getModule(self.console.getPlugin(pname).__module__),
                         '__version__', 'Unknown Version')))

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except:
            database = "unknown"

        version = getattr(b3, '__version__', 'Unknown Version')
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'Unknown Version'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version
        }

        if self.console.gameName in ('bfbc2', 'moh'):
            try:
                cvarDescription = self.console.getCvar('serverDescription')
                if cvarDescription is not None:
                    info.update({'serverDescription': cvarDescription.value})
                cvarBannerUrl = self.console.getCvar('bannerUrl')
                if cvarBannerUrl is not None:
                    info.update({'bannerUrl': cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
예제 #20
0
    def startup(self):
        self.debug("startup()")
        
        # create the 'Server' client
        self.clients.newClient('Server', guid='Server', name='Server', hide=True, pbid='Server', team=b3.TEAM_UNKNOWN)

        if self.config.has_option('server','inifile'):
            # open ini file
            ini_file = self.config.get('server','inifile')
            if ini_file[0:6] == 'ftp://':
                    self.ftpconfig = functions.splitDSN(ini_file)
                    self._ini_file = 'ftp'
                    self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('Getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input  = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug('Incorrect ini file or no ini file specified, map commands other than nextmap not available')
            
        # start crontab to trigger playerlist events
        self.cron + b3.cron.CronTab(self.retrievePlayerList, second='*/%s' % self._playerlistInterval)

        # add specific events
        self.Events.createEvent('EVT_CLIENT_SQUAD_SAY', 'Squad Say')
        self.Events.createEvent('EVT_SERVER_SAY', 'Server Chatter')
        self.Events.createEvent('EVT_CLIENT_CLAN_CHANGE', 'Client Clan Change')
        self.Events.createEvent('EVT_CLIENT_VOTE_START', 'Client Vote Start')
        self.Events.createEvent('EVT_CLIENT_VOTE', 'Client Vote')
        self.Events.createEvent('EVT_SERVER_VOTE_END', 'Server Vote End')
        #self.Events.createEvent('EVT_CLIENT_SQUAD_CHANGE', 'Client Squad Change')
                
        ## read game server info and store as much of it in self.game wich
        ## is an instance of the b3.game.Game class
        sq = SourceQuery.SourceQuery(self._publicIp, self._port, timeout=10)
        try:
            serverinfo = sq.info()
            self.debug("server info : %r", serverinfo)
            if 'map' in serverinfo:
                self.game.mapName = serverinfo['map'].lower()
            if 'steamid' in serverinfo:
                self.game.steamid = serverinfo['steamid']
            if 'hostname' in serverinfo:
                self.game.sv_hostname = serverinfo['hostname']
            if 'maxplayers' in serverinfo:
                self.game.sv_maxclients = serverinfo['maxplayers']
        except Exception, err:
            self.exception(err)
    def startup(self):
        self.debug("startup()")
        
        # create the 'Server' client
        self.clients.newClient('Server', guid='Server', name='Server', hide=True, pbid='Server', team=b3.TEAM_UNKNOWN)

        if self.config.has_option('server','inifile'):
            # open ini file
            ini_file = self.config.get('server','inifile')
            if ini_file[0:6] == 'ftp://':
                    self.ftpconfig = functions.splitDSN(ini_file)
                    self._ini_file = 'ftp'
                    self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('Getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input  = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug('Incorrect ini file or no ini file specified, map commands other than nextmap not available')
            
        # start crontab to trigger playerlist events
        self.cron + b3.cron.CronTab(self.retrievePlayerList, second='*/%s' % self._playerlistInterval)

        # add specific events
        self.Events.createEvent('EVT_CLIENT_SQUAD_SAY', 'Squad Say')
        self.Events.createEvent('EVT_SERVER_SAY', 'Server Chatter')
        self.Events.createEvent('EVT_CLIENT_CLAN_CHANGE', 'Client Clan Change')
        self.Events.createEvent('EVT_CLIENT_VOTE_START', 'Client Vote Start')
        self.Events.createEvent('EVT_CLIENT_VOTE', 'Client Vote')
        self.Events.createEvent('EVT_SERVER_VOTE_END', 'Server Vote End')
        #self.Events.createEvent('EVT_CLIENT_SQUAD_CHANGE', 'Client Squad Change')
                
        ## read game server info and store as much of it in self.game wich
        ## is an instance of the b3.game.Game class
        sq = SourceQuery.SourceQuery(self._publicIp, self._port, timeout=10)
        try:
            serverinfo = sq.info()
            self.debug("server info : %r", serverinfo)
            if 'map' in serverinfo:
                self.game.mapName = serverinfo['map'].lower()
            if 'steamid' in serverinfo:
                self.game.steamid = serverinfo['steamid']
            if 'hostname' in serverinfo:
                self.game.sv_hostname = serverinfo['hostname']
            if 'maxplayers' in serverinfo:
                self.game.sv_maxclients = serverinfo['maxplayers']
        except Exception, err:
            self.exception(err)
예제 #22
0
    def onLoadConfig(self):
        if self.config.get('settings', 'output_file')[0:6] == 'ftp://':
            self._ftpinfo = functions.splitDSN(
                self.config.get('settings', 'output_file'))
            self._ftpstatus = True
        else:
            self._outputFile = self.config.getpath('settings', 'output_file')

        self._tkPlugin = self.console.getPlugin('tk')
        self._interval = self.config.getint('settings', 'interval')
        try:
            self._enableDBsvarSaving = self.config.getboolean(
                'settings', 'enableDBsvarSaving')
        except:
            self._enableDBsvarSaving = False
        try:
            self._enableDBclientSaving = self.config.getboolean(
                'settings', 'enableDBclientSaving')
        except:
            self._enableDBclientSaving = False

        try:
            self._svarTable = self.config.get('settings', 'svar_table')
            self.debug('Using custom table for saving server svars: %s' %
                       self._svarTable)
        except:
            self.debug('Using default table for saving server svars: %s' %
                       self._svarTable)
        try:
            self._clientTable = self.config.get('settings', 'client_table')
            self.debug('Using custom table for saving current clients: %s' %
                       self._clientTable)
        except:
            self.debug('Using default table for saving current clients: %s' %
                       self._clientTable)

        if self._enableDBsvarSaving:
            sql = "CREATE TABLE IF NOT EXISTS `%s` (`id` int(11) NOT NULL auto_increment,`name` varchar(255) NOT NULL,`value` varchar(255) NOT NULL, PRIMARY KEY  (`id`), UNIQUE KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;" % (
                self._svarTable)
            self.console.storage.query(sql)
        if self._enableDBclientSaving:
            sql = "CREATE TABLE IF NOT EXISTS `%s` (`id` INT(3) NOT NULL AUTO_INCREMENT,`Updated` VARCHAR( 255 ) NOT NULL ,`Name` VARCHAR( 255 ) NOT NULL ,`Level` VARCHAR( 255 ) NOT NULL ,`DBID` VARCHAR( 255 ) NOT NULL ,`CID` VARCHAR( 255 ) NOT NULL ,`Joined` VARCHAR( 255 ) NOT NULL ,`Connections` VARCHAR( 255 ) NOT NULL ,`State` VARCHAR( 255 ) NOT NULL ,`Score` VARCHAR( 255 ) NOT NULL ,`IP` VARCHAR( 255 ) NOT NULL ,`GUID` VARCHAR( 255 ) NOT NULL ,`PBID` VARCHAR( 255 ) NOT NULL ,`Team` VARCHAR( 255 ) NOT NULL ,`ColorName` VARCHAR( 255 ) NOT NULL, PRIMARY KEY (`id`)) ENGINE = MYISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;" % (
                self._clientTable)
            self.console.storage.query(sql)

        if self._cronTab:
            # remove existing crontab
            self.console.cron - self._cronTab

        self._cronTab = b3.cron.PluginCronTab(self, self.update,
                                              '*/%s' % self._interval)
        self.console.cron + self._cronTab
예제 #23
0
    def run(self):
        """
        Run the DB update
        """
        clearscreen()
        print("""
                        _\|/_
                        (o o)    {:>32}
                +----oOO---OOo----------------------------------+
                |                                               |
                |             UPDATING B3 DATABASE              |
                |                                               |
                +-----------------------------------------------+

        """.format('B3 : %s' % b3.__version__))

        input("press any key to start the update...")

        def _update_database(storage, update_version):
            """
            Update a B3 database.
            :param storage: the initialized storage module
            :param update_version: the update version
            """
            if B3version(b3.__version__) >= update_version:
                sql = b3.getAbsolutePath('@b3/sql/%s/b3-update-%s.sql' %
                                         (storage.protocol, update_version))
                if os.path.isfile(sql):
                    try:
                        print('>>> updating database to version %s' %
                              update_version)
                        sleep(.5)
                        storage.queryFromFile(sql)
                    except Exception as err:
                        print(
                            'WARNING: could not update database properly: %s' %
                            err)
                        sleep(3)

        dsn = self.config.get('b3', 'database')
        dsndict = splitDSN(dsn)
        database = getStorage(dsn, dsndict, StubParser())

        _update_database(database, '1.3.0')
        _update_database(database, '1.6.0')
        _update_database(database, '1.7.0')
        _update_database(database, '1.8.1')
        _update_database(database, '1.9.0')
        _update_database(database, '1.10.0')

        console_exit('B3 database update completed!')
    def test_getConnection_mysql(self):
        # mock the pymysql module so we can test in an environement which does not have this module installed
        dsn = "mysql://*****:*****@somehost:someport/somedbname"
        mock_pymysql = Mock()
        mock_pymysql.connect = Mock(return_value=sentinel)
        with patch.dict('sys.modules', {'pymysql': mock_pymysql}):

            # verify that a correct dsn does work as expected
            mock_pymysql.connect.reset_mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), Mock())
            when(storage).getTables().thenReturn(B3_DEFAULT_TABLES)
            storage.connect()
            assert mock_pymysql.connect.called, "expecting pymysql.connect to be called"
            self.assertEqual(sentinel, storage.db)

            # verify that B3 creates necessary tables when they are missing
            mock_pymysql.connect.reset_mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), Mock())
            when(storage).getTables().thenReturn([])
            storage.queryFromFile = Mock()
            storage.connect()
            assert storage.queryFromFile.called, "expecting MysqlStorage.queryFromFile to be called"
            self.assertEqual(sentinel, storage.db)

            # verify that whenever B3 is not able to create necessary tables, it stops
            mock_pymysql.connect.reset_mock()
            console_mock = Mock()
            console_mock.critical = Mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), console_mock)
            storage.shutdown = Mock()
            when(storage).getTables().thenReturn([])
            when(storage).queryFromFile(ANY()).thenRaise(Exception())
            storage.connect()
            assert storage.shutdown.called, "expecting MysqlStorage.shutdown to be called"
            assert console_mock.critical.called, "expecting console_mock.critical to be called"
            self.assertIn("Missing MySQL database tables",
                          console_mock.critical.call_args[0][0])
예제 #25
0
    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug("Sending heartbeat to B3 master...")
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            plugins.append(
                "%s/%s"
                % (
                    pname,
                    getattr(getModule(self.console.getPlugin(pname).__module__), "__version__", "Unknown Version"),
                )
            )

        try:
            database = functions.splitDSN(self.console.storage.dsn)["protocol"]
        except:
            database = "unknown"

        version = getattr(b3, "__version__", "Unknown Version")
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            "action": "update",
            "ip": self.console._publicIp,
            "port": self.console._port,
            "rconPort": self.console._rconPort,
            "version": version,
            "parser": self.console.gameName,
            "parserversion": getattr(getModule(self.console.__module__), "__version__", "Unknown Version"),
            "database": database,
            "plugins": ",".join(plugins),
            "os": os.name,
            "python_version": sys.version,
            "default_encoding": sys.getdefaultencoding(),
        }

        if self.console.gameName in ("bfbc2", "moh"):
            try:
                cvarDescription = self.console.getCvar("serverDescription")
                if cvarDescription is not None:
                    info.update({"serverDescription": cvarDescription.value})
                cvarBannerUrl = self.console.getCvar("bannerUrl")
                if cvarBannerUrl is not None:
                    info.update({"bannerUrl": cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
    def test_getConnection_mysql(self):
        # mock the pymysql module so we can test in an environement which does not have this module installed
        dsn = "mysql://*****:*****@somehost:someport/somedbname"
        mock_pymysql = Mock()
        mock_pymysql.connect = Mock(return_value=sentinel)
        with patch.dict('sys.modules', {'pymysql': mock_pymysql}):

            # verify that a correct dsn does work as expected
            mock_pymysql.connect.reset_mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), Mock())
            when(storage).getTables().thenReturn(B3_DEFAULT_TABLES)
            storage.connect()
            assert mock_pymysql.connect.called, "expecting pymysql.connect to be called"
            self.assertEqual(sentinel, storage.db)

            # verify that B3 creates necessary tables when they are missing
            mock_pymysql.connect.reset_mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), Mock())
            when(storage).getTables().thenReturn([])
            storage.queryFromFile = Mock()
            storage.connect()
            assert storage.queryFromFile.called, "expecting MysqlStorage.queryFromFile to be called"
            self.assertEqual(sentinel, storage.db)

            # verify that whenever B3 is not able to create necessary tables, it stops
            mock_pymysql.connect.reset_mock()
            console_mock = Mock()
            console_mock.critical = Mock()
            storage = MysqlStorage(dsn, splitDSN(dsn), console_mock)
            storage.shutdown = Mock()
            when(storage).getTables().thenReturn([])
            when(storage).queryFromFile(ANY()).thenRaise(Exception())
            storage.connect()
            assert storage.shutdown.called, "expecting MysqlStorage.shutdown to be called"
            assert console_mock.critical.called, "expecting console_mock.critical to be called"
            self.assertIn("Missing MySQL database tables", console_mock.critical.call_args[0][0])
예제 #27
0
    def onLoadConfig(self):
        if self.config.get('settings','output_file')[0:6] == 'ftp://':
                self._ftpinfo = functions.splitDSN(self.config.get('settings','output_file'))
                self._ftpstatus = True
        else:        
                self._outputFile = os.path.expanduser(self.config.get('settings', 'output_file'))
                
        self._tkPlugin = self.console.getPlugin('tk')
        self._interval = self.config.getint('settings', 'interval')

        if self._cronTab:
            # remove existing crontab
            self.console.cron - self._cronTab

        self._cronTab = b3.cron.PluginCronTab(self, self.update, '*/%s' % self._interval)
        self.console.cron + self._cronTab
    def setUp(self):
        """this method is called before each test"""
        B3TestCase.setUp(self)

        try:
            dsn = "postgresql://%s:%s@%s/%s" % (POSTGRESQL_TEST_USER, POSTGRESQL_TEST_PASSWORD, POSTGRESQL_TEST_HOST, POSTGRESQL_TEST_DB)
            self.storage = self.console.storage = PostgresqlStorage(dsn, splitDSN(dsn), self.console)
            self.storage.connect()

            tables = self.storage.getTables()
            if tables:
                # dont remove the groups table since we would need it in next tests
                tables.remove('groups')
                self.storage.truncateTable(tables)
        except Exception, e:
            self.fail("Error: %s" % e)
예제 #29
0
    def startup(self):
        """
        Called after the parser is created before run().
        """
        self.debug("startup")
        # create the 'Admin' client
        self.clients.newClient('Admin', guid='Server', name='Admin', hide=True, pbid='Server', team=b3.TEAM_UNKNOWN)
        if self.config.has_option('server','ro2admin'):
            self.username = self.config.get('server', 'ro2admin')
        else:
            self.username = "******"
        
        if self.config.has_option('server','inifile'):
            # open ini file
            ini_file = self.config.get('server','inifile')
            if ini_file[0:6] == 'ftp://':
                    self.ftpconfig = functions.splitDSN(ini_file)
                    self._ini_file = 'ftp'
                    self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input  = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug('Incorrect ini file or no ini file specified: map commands other than nextmap not available')

        self.cron.add(b3.cron.CronTab(self.retrievePlayerList, second='*/%s' % self._playerlistInterval))
    
        self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
        self.headers = {'User-Agent': self.user_agent,
                        "Accept": "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                        "Accept-Language": "en-us,en;q =0.5",
                        "Content-type": "application/x-www-form-urlencoded",
                        "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
                        "Referer": ''}

        self.site = self._publicIp + ':' + str(self._rconPort)
        self.login_page = "ServerAdmin"
        self.password = self._rconPassword
        self.password_hash = "$sha1$%s" % hashlib.sha1("%s%s" % (self.password, self.username)).hexdigest()
        self.url = "http://%s/%s" % (self.site, self.login_page)
예제 #30
0
    def startup(self):
        patchCod4Parser()
        self.readConfig()

        if self._logToDB:
            self._storage = b3.storage.getStorage(self._dsn,
                                                  splitDSN(self._dsn),
                                                  self.console)
            self.debug('succesfully connected to database: %s' %
                       self._storage.status())
            self.checkTablesExist()

        self.registerEvent(EVT_ROTU_STATS_GAME)
        self.registerEvent(EVT_ROTU_STATS_PLAYER)
        self.registerEvent(EVT_ROTU_STATS_DONE)

        self.debug('Started')
예제 #31
0
class Test_MySQL(B3TestCase, StorageAPITest):

    def setUp(self):
        """this method is called before each test"""

        B3TestCase.setUp(self)

        try:
            db = driver.connect(host=MYSQL_TEST_HOST, user=MYSQL_TEST_USER, password=MYSQL_TEST_PASSWORD)
        except driver.OperationalError, message:
            self.fail("Error %d:\n%s" % (message[0], message[1]))

        db.query("DROP DATABASE IF EXISTS `%s`" % MYSQL_TEST_DB)
        db.query("CREATE DATABASE `%s` CHARACTER SET utf8;" % MYSQL_TEST_DB)

        dsn = "mysql://%s:%s@%s/%s" % (MYSQL_TEST_USER, MYSQL_TEST_PASSWORD, MYSQL_TEST_HOST, MYSQL_TEST_DB)
        self.storage = self.console.storage = MysqlStorage(dsn, splitDSN(dsn), self.console)
        self.storage.connect()
예제 #32
0
 def update(self):
     """send an upate heartbeat to B3 master server"""
     self.debug('Sending heartbeat to B3 master...')
     socket.setdefaulttimeout(10)
     
     plugins = []
     for pname in self.console._pluginOrder:
         plugins.append("%s/%s" % (pname, getattr(getModule(self.console.getPlugin(pname).__module__), '__version__', 'Unknown Version')))
       
     try:
         database = functions.splitDSN(self.console.storage.dsn)['protocol']
     except:
         database = "unknown"
         
     version = getattr(b3, '__version__', 'Unknown Version')
     if b3.functions.main_is_frozen():
         version += " win32"
         
     info = {
         'action' : 'update',
         'ip' : self.console._publicIp,
         'port' : self.console._port,
         'rconPort' : self.console._rconPort,
         'version' : version,
         'parser' : self.console.gameName,
         'parserversion' : getattr(getModule(self.console.__module__), '__version__', 'Unknown Version'),
         'database' : database,
         'plugins' : ','.join(plugins),
         'os' : os.name,
         'python_version': sys.version,
         'default_encoding': sys.getdefaultencoding()
     }
     
     if self.console.gameName in ('bfbc2', 'moh'):
         try:
             cvarDescription = self.console.getCvar('serverDescription')
             if cvarDescription is not None:
                 info.update({'serverDescription': cvarDescription.value})
             cvarBannerUrl = self.console.getCvar('bannerUrl')
             if cvarBannerUrl is not None:
                 info.update({'bannerUrl': cvarBannerUrl.value})
         except Exception, err:
             self.debug(err)
예제 #33
0
    def onLoadConfig(self):
        if self.config.get('settings', 'output_file')[0:6] == 'ftp://':
            self._ftpinfo = functions.splitDSN(
                self.config.get('settings', 'output_file'))
            self._ftpstatus = True
        else:
            self._outputFile = self.config.getpath('settings', 'output_file')

        self._tkPlugin = self.console.getPlugin('tk')
        self._interval = self.config.getint('settings', 'interval')
        try:
            self._enableDBsvarSaving = self.config.getboolean(
                'settings', 'enableDBsvarSaving')
        except:
            self._enableDBsvarSaving = False

        try:
            self._enableDBclientSaving = self.config.getboolean(
                'settings', 'enableDBclientSaving')
        except:
            self._enableDBclientSaving = False
        try:
            self._matchinterval = self.config.getint('settings',
                                                     'match_interval')
        except:
            self._matchinterval = self._interval
        try:
            self._showpass = self.config.getboolean('settings',
                                                    'show_password')
        except:
            self._showpass = False

        if self._enableDBsvarSaving:
            sql = "CREATE TABLE IF NOT EXISTS `current_svars` (`id` int(11) NOT NULL auto_increment,`name` varchar(255) NOT NULL,`value` varchar(255) NOT NULL, PRIMARY KEY  (`id`), UNIQUE KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"
            self.console.storage.query(sql)
        if self._enableDBclientSaving:
            sql = "CREATE TABLE IF NOT EXISTS `current_clients` (`id` INT(3) NOT NULL AUTO_INCREMENT,`Updated` VARCHAR( 255 ) NOT NULL ,`Name` VARCHAR( 255 ) NOT NULL ,`Level` VARCHAR( 255 ) NOT NULL ,`DBID` VARCHAR( 255 ) NOT NULL ,`CID` VARCHAR( 255 ) NOT NULL ,`Joined` VARCHAR( 255 ) NOT NULL ,`Connections` VARCHAR( 255 ) NOT NULL ,`State` VARCHAR( 255 ) NOT NULL ,`Score` VARCHAR( 255 ) NOT NULL ,`IP` VARCHAR( 255 ) NOT NULL ,`GUID` VARCHAR( 255 ) NOT NULL ,`PBID` VARCHAR( 255 ) NOT NULL ,`Team` VARCHAR( 255 ) NOT NULL ,`ColorName` VARCHAR( 255 ) NOT NULL, PRIMARY KEY (`id`)) ENGINE = MYISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"
            self.console.storage.query(sql)

        if self._cronTab:
            # remove existing crontab
            self.console.cron - self._cronTab
        self._createCrontab(self._interval)
    def setUp(self):
        """this method is called before each test"""
        B3TestCase.setUp(self)

        try:
            dsn = "postgresql://%s:%s@%s/%s" % (
                POSTGRESQL_TEST_USER, POSTGRESQL_TEST_PASSWORD,
                POSTGRESQL_TEST_HOST, POSTGRESQL_TEST_DB)
            self.storage = self.console.storage = PostgresqlStorage(
                dsn, splitDSN(dsn), self.console)
            self.storage.connect()

            tables = self.storage.getTables()
            if tables:
                # dont remove the groups table since we would need it in next tests
                tables.remove('groups')
                self.storage.truncateTable(tables)
        except Exception, e:
            self.fail("Error: %s" % e)
예제 #35
0
    def update(self):
        self.debug("Sending heartbeat to B3 master...")
        socket.setdefaulttimeout(10)

        def getModule(name):
            mod = __import__(name)
            components = name.split(".")
            for comp in components[1:]:
                mod = getattr(mod, comp)
            return mod

        plugins = []
        for pname in self.console._pluginOrder:
            plugins.append(
                "%s/%s"
                % (
                    pname,
                    getattr(getModule(self.console.getPlugin(pname).__module__), "__version__", "Unknown Version"),
                )
            )

        try:
            database = functions.splitDSN(self.console.storage.dsn)["protocol"]
        except:
            database = "unknown"

        version = getattr(b3, "__version__", "Unknown Version")
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            "action": "update",
            "ip": self.console._publicIp,
            "port": self.console._port,
            "version": version,
            "parser": self.console.gameName,
            "parserversion": getattr(getModule(self.console.__module__), "__version__", "Unknown Version"),
            "database": database,
            "plugins": ",".join(plugins),
            "os": os.name,
        }
        # self.debug(info)
        self.sendInfo(info)
예제 #36
0
    def startup(self):
        self.debug("startup()")

        # create the 'Server' client
        self.clients.newClient('Server',
                               guid='Server',
                               name='Server',
                               hide=True,
                               pbid='Server',
                               team=b3.TEAM_UNKNOWN)

        if self.config.has_option('server', 'inifile'):
            # open ini file
            ini_file = self.config.get('server', 'inifile')
            if ini_file[0:6] == 'ftp://':
                self.ftpconfig = functions.splitDSN(ini_file)
                self._ini_file = 'ftp'
                self.bot('ftp supported')
            elif ini_file[0:7] == 'sftp://':
                self.bot('sftp currently not supported')
            else:
                self.bot('Getting configs from %s', ini_file)
                f = self.config.getpath('server', 'inifile')
                if os.path.isfile(f):
                    self.input = file(f, 'r')
                    self._ini_file = f

        if not self._ini_file:
            self.debug(
                'Incorrect ini file or no ini file specified, map commands other than nextmap not available'
            )

        # start crontab to trigger playerlist events
        self._cronTab = b3.cron.CronTab(self.retrievePlayerList,
                                        second='*/%s' %
                                        self._playerlistInterval)
        self.cron + self._cronTab

        # add specific events
        self.Events.createEvent('EVT_CLIENT_SQUAD_SAY', 'Squad Say')
        self.Events.createEvent('EVT_SERVER_SAY', 'Server Chatter')
        self.Events.createEvent('EVT_CLIENT_CLAN_CHANGE', 'Client Clan Change')
 def _write(self, text):
     if text.strip() == '':
         self._console.warning('AUTODOC: nothing to write')
         
     dsn = splitDSN(self._outputUrl)
     if dsn['protocol'] == 'ftp':
         self._console.debug('AUTODOC: uploading to FTP server %s' % dsn['host'])
         ftp = FTP(dsn['host'], dsn['user'], passwd=dsn['password'])
         ftp.cwd(os.path.dirname(dsn['path']))
         ftpfile = StringIO.StringIO()
         ftpfile.write(text)
         ftpfile.seek(0)
         ftp.storbinary('STOR ' + os.path.basename(dsn['path']), ftpfile)
     elif dsn['protocol'] == 'file':
         path = getWritableFilePath(dsn['path'], True)
         self._console.debug('AUTODOC: writing to %s', path)
         f = file(path, 'w')
         f.write(text)
         f.close()
     else:
         self._console.error('AUTODOC: protocol [%s] is not supported' % dsn['protocol'])
예제 #38
0
    def onLoadConfig(self):
        if self.config.get('settings','bans_file')[0:6] == 'ftp://':
            self._bansFile = self.config.get('settings','bans_file')
            self._remoteBansFile = True
            self._ftpConfig = functions.splitDSN(self._bansFile)
            self.info('Accessing pbbans.dat file in remote mode')
        else:
            self._bansFile = self.console.getAbsolutePath(self.config.get('settings', 'bans_file'))


        self._rebuildBans = self.config.get('settings', 'rebuild_bans')

        if self._cronTab:
            # remove old crontab
            self.console.cron - self._cronTab

        if self._rebuildBans == '0' or self._rebuildBans == 0:
            self._rebuildBans = 0
        else:
            minute, hour, day, month, dow = self._rebuildBans.split(' ')
            self._cronTab = b3.cron.PluginCronTab(self, self.rebuildBans, '0', minute, hour, day, month, dow)
            self.console.cron + self._cronTab
예제 #39
0
    def __init__(self, config):
        """
        Object constructor.
        :param config: The main configuration file
        """
        b3.console = self
        self._timeStart = self.time()
        logging.basicConfig(level=b3.output.VERBOSE2,
                            format='%(asctime)s\t%(levelname)s\t%(message)s')
        self.log = logging.getLogger('output')
        self.config = config

        if isinstance(config, b3.config.XmlConfigParser) or isinstance(
                config, b3.config.CfgConfigParser):
            self.config = b3.config.MainConfig(config)
        elif isinstance(config, b3.config.MainConfig):
            self.config = config
        else:
            self.config = b3.config.MainConfig(b3.config.load(config))

        self.storage = SqliteStorage("sqlite://:memory:",
                                     splitDSN("sqlite://:memory:"), self)
        self.storage.connect()
        self.clients = b3.clients.Clients(self)
        self.game = b3.game.Game(self, "fakeGame")
        self.game.mapName = 'ut4_turnpike'
        self.cvars = {}
        self._handlers = {}

        if not self.config.has_option('server',
                                      'punkbuster') or self.config.getboolean(
                                          'server', 'punkbuster'):
            self.PunkBuster = b3.parsers.punkbuster.PunkBuster(self)

        self.input = io.StringIO()
        self.working = True
예제 #40
0
 def assertDsnEqual(self, url, expected):
     tmp = functions.splitDSN(url)
     self.assertEqual(tmp, expected)
 def test_construct(self):
     self.assertRaises(AttributeError, MysqlStorage, 'foo://bar', splitDSN('foo://bar'), Mock())
예제 #42
0
 def initThread(self, ftpfileDSN):
     self.sftpconfig = functions.splitDSN(ftpfileDSN)
     thread1 = threading.Thread(target=self.update)
     self.info("Starting sftpytail thread")
     thread1.start()
예제 #43
0
 def test_sqlite(self):
     storage = getStorage('sqlite://:memory:',
                          splitDSN('sqlite://:memory:'), Mock())
     self.assertIsInstance(storage, SqliteStorage)
예제 #44
0
 def test_postgresql(self):
     storage = getStorage('postgresql://*****:*****@localhost/b3',
                          splitDSN('postgresql://*****:*****@localhost/b3'),
                          Mock())
     self.assertIsInstance(storage, PostgresqlStorage)
예제 #45
0
 def init_thread(self, ftpfiledsn):
     self.sftpconfig = functions.splitDSN(ftpfiledsn)
     thread1 = threading.Thread(target=self.update)
     self.info("starting sftpytail thread")
     thread1.start()
     return thread1
예제 #46
0
class PublistPlugin(b3.plugin.Plugin):
    _cronTab = None
    _url = 'http://www.bigbrotherbot.net/master/serverping.php'
    _secondUrl = None
    requiresConfigFile = False

    _heartbeat_sent = False
    _initial_heartbeat_delay_minutes = 5

    def onLoadConfig(self):
        try:
            self._secondUrl = self.config.get('settings', 'url')
            self.debug('Using second url : %s' % self._secondUrl)
        except:
            pass

        try:
            self._initial_heartbeat_delay_minutes = self.config.getint(
                'settings', 'delay')
            self.debug('delay : %s' % self._initial_heartbeat_delay_minutes)
        except:
            pass

    def onStartup(self):

        # get the plugin so we can register commands
        self._adminPlugin = self.console.getPlugin('admin')
        if not self._adminPlugin:
            # something is wrong, can't start without admin plugin
            self.error('Could not find admin plugin')
            return False

        # set cvar for advertising purposes
        try:
            cvarValue = 'B3 %s' % b3.versionId
            self.console.setCvar('_B3', cvarValue)
        except:
            pass

        if self.console._publicIp == '127.0.0.1':
            self.info(
                "publist will not send heartbeat to master server as publicIp is not public."
            )
            return

        rmin = random.randint(0, 59)
        rhour = random.randint(0, 23)
        self.debug("publist will send heartbeat at %02d:%02d every day" %
                   (rhour, rmin))
        self._cronTab = b3.cron.PluginCronTab(self, self.update, 0, rmin,
                                              rhour, '*', '*', '*')
        self.console.cron + self._cronTab

        # planning initial heartbeat
        # v1.9.1: Changing the threaded timer to a one time crontab to enable quick shutdown of the bot.
        _im = int(time.strftime('%M')) + self._initial_heartbeat_delay_minutes
        if _im >= 60:
            _im -= 60
        self.info(
            'initial heartbeat will be sent to B3 master server at %s minutes'
            % (str(_im).zfill(2)))
        self._cronTab = b3.cron.OneTimeCronTab(self.update, 0, _im, '*', '*',
                                               '*', '*')
        self.console.cron + self._cronTab

    def onEvent(self, event):
        if event.type == b3.events.EVT_STOP and self._heartbeat_sent:
            self.shutdown()

    def removeCrontab(self):
        try:
            self.console.cron - self._cronTab
        except KeyError:
            pass

    def shutdown(self):
        """Send a shutdown heartbeat to B3 master server"""
        self.info('Sending shutdown info to B3 master')
        info = {
            'action': 'shutdown',
            'ip': self.console._publicIp,
            'port': self.console._port,
            'rconPort': self.console._rconPort
        }
        #self.debug(info)
        self.sendInfo(info)

    def update(self):
        """send an upate heartbeat to B3 master server"""
        self.debug('Sending heartbeat to B3 master...')
        socket.setdefaulttimeout(10)

        plugins = []
        for pname in self.console._pluginOrder:
            try:
                p = self.console.getPlugin(pname)
                p_module = getModule(p.__module__)
                p_version = getattr(p_module, '__version__', 'Unknown Version')
                plugins.append("%s/%s" % (pname, p_version))
            except Exception, e:
                self.warning("Could not get version for plugin named '%s'" %
                             pname,
                             exc_info=e)

        try:
            database = functions.splitDSN(self.console.storage.dsn)['protocol']
        except:
            database = "unknown"

        version = getattr(b3, '__version__', 'Unknown Version')
        if b3.functions.main_is_frozen():
            version += " win32"

        info = {
            'action':
            'update',
            'ip':
            self.console._publicIp,
            'port':
            self.console._port,
            'rconPort':
            self.console._rconPort,
            'version':
            version,
            'parser':
            self.console.gameName,
            'parserversion':
            getattr(getModule(self.console.__module__), '__version__',
                    'Unknown Version'),
            'database':
            database,
            'plugins':
            ','.join(plugins),
            'os':
            os.name,
            'python_version':
            sys.version,
            'default_encoding':
            sys.getdefaultencoding()
        }

        if self.console.gameName in ('bfbc2', 'moh'):
            try:
                cvarDescription = self.console.getCvar('serverDescription')
                if cvarDescription is not None:
                    info.update({'serverDescription': cvarDescription.value})
                cvarBannerUrl = self.console.getCvar('bannerUrl')
                if cvarBannerUrl is not None:
                    info.update({'bannerUrl': cvarBannerUrl.value})
            except Exception, err:
                self.debug(err)
예제 #47
0
 def test_sqlite(self):
     storage = getStorage('sqlite://:memory:', splitDSN('sqlite://:memory:'), Mock())
     self.assertIsInstance(storage, SqliteStorage)
예제 #48
0
 def setUp(self):
     """this method is called before each test"""
     B3TestCase.setUp(self)
     self.storage = self.console.storage = SqliteStorage('sqlite://' + SQLITE_DB, splitDSN('sqlite://' + SQLITE_DB), self.console)
     self.storage.connect()
 def test_construct(self):
     self.assertRaises(AttributeError, MysqlStorage, 'foo://bar',
                       splitDSN('foo://bar'), Mock())
예제 #50
0
class PunkbusterPlugin(b3.plugin.Plugin):

    _adminPlugin = None
    _cronTab = None
    _remoteBansFile = False
    _ftpConfig = None
    _bansFile = '~/cod/pb/pbbans.dat'
    _rebuildBans = '0 0 * * *'

    ####################################################################################################################
    #                                                                                                                  #
    #    STARTUP                                                                                                       #
    #                                                                                                                  #
    ####################################################################################################################

    def onStartup(self):
        """
        Initialize the plugin.
        """
        self._adminPlugin = self.console.getPlugin('admin')

        if self.console.PunkBuster is None:
            self.warning(
                'could not register commands because Punkbuster is disabled in your b3 configuration file'
            )
            return False

        # register our commands
        if 'commands' in self.config.sections():
            for cmd in self.config.options('commands'):
                level = self.config.get('commands', cmd)
                sp = cmd.split('-')
                alias = None
                if len(sp) == 2:
                    cmd, alias = sp

                func = getCmd(self, cmd)
                if func:
                    self._adminPlugin.registerCommand(self, cmd, level, func,
                                                      alias)

    def onLoadConfig(self):
        """
        Load plugin configuration
        """
        try:
            self._bansFile = self.config.get('settings', 'bans_file')
            self.debug('loaded settings/bans_file: %s' % self._bansFile)
        except NoOptionError, e:
            self.error('could not load settings/bans_file config value: %s' %
                       e)
            self.debug('using default value (%s) for settings/bans_file' %
                       self._bansFile)

        if self._bansFile[0:6] == 'ftp://':
            self._remoteBansFile = True
            self._ftpConfig = functions.splitDSN(self._bansFile)
            self.info('accessing pbbans.dat file in remote mode')
        else:
            self._bansFile = self.console.getAbsolutePath(self._bansFile)

        try:
            self._rebuildBans = self.config.get('settings', 'rebuild_bans')
            self.debug('loaded settings/rebuild_bans: %s' % self._rebuildBans)
        except NoOptionError, e:
            self.error(
                'could not load settings/rebuild_bans config value: %s' % e)
            self.debug('using default value (%s) for settings/rebuild_bans' %
                       self._rebuildBans)
예제 #51
0
 def assertDsnEqual(self, url, expected):
     tmp = functions.splitDSN(url)
     self.assertEqual(tmp, expected)
예제 #52
0
    def __init__(self, config):
        self._timeStart = self.time()

        if not self.loadConfig(config):
            print 'COULD NOT LOAD CONFIG'
            raise SystemExit(220)

        # set up logging
        logfile = self.config.getpath('b3', 'logfile')
        self.log = b3.output.getInstance(logfile, self.config.getint('b3', 'log_level'))

        # save screen output to self.screen
        self.screen = sys.stdout
        print 'Activating log   : %s' % logfile
        sys.stdout = b3.output.stdoutLogger(self.log)
        sys.stderr = b3.output.stderrLogger(self.log)

        # setup ip addresses
        self._publicIp = self.config.get('server', 'public_ip')
        self._rconIp   = self.config.get('server', 'rcon_ip')
        self._port     = self.config.getint('server', 'port')

        if self._publicIp[0:1] == '~' or self._publicIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._publicIp))
            self._publicIp = f.read().strip()
            f.close()
    
        if self._rconIp[0:1] == '~' or self._rconIp[0:1] == '/':
            # load ip from a file
            f = file(self.getAbsolutePath(self._rconIp))
            self._rconIp = f.read().strip()
            f.close()

        self.bot('%s', b3.sversion)
        self.bot('Python: %s', sys.version)
        self.bot('Starting %s server for %s:%s', self.__class__.__name__, self._rconIp, self._port)

        # get events
        self.Events = b3.events.eventManager

        self.bot('--------------------------------------------')

        # setup bot
        bot_name = self.config.get('b3', 'bot_name')
        if bot_name:
            self.name = bot_name

        bot_prefix = self.config.get('b3', 'bot_prefix')
        if bot_prefix:
            self.prefix = bot_prefix

        self.msgPrefix = self.prefix

        # delay between log reads
        if self.config.has_option('server', 'delay'):
            delay = self.config.getfloat('server', 'delay')
            self.delay = delay

        # demo mode: use log time
        if self.config.has_option('server', 'replay'):
            self.replay = self.config.getboolean('server', 'replay')
            if self.replay:
                self._timeStart = 0
                self.bot('Replay mode enabled')

        self.storage = b3.storage.getStorage('database', self.config.get('b3', 'database'), self)

        # open log file
        if self.config.get('server','game_log')[0:6] == 'ftp://' :
            self.remoteLog = True
            self.bot('Working in Remote-Log-Mode')
            self.bot('Game log %s', self.config.get('server', 'game_log'))
            f = os.path.normpath(os.path.expanduser('games_mp.log'))
            ftptempfile = open(f, "w")
            ftptempfile.close()
            from b3 import functions
            from ftplib import FTP
            def handleDownload(block):
                self.file.write(block)
                self.file.flush()
            gamelog = self.config.get('server', 'game_log')
            ftpconfig = functions.splitDSN(gamelog)
            ftp=FTP(ftpconfig['host'], ftpconfig['user'], ftpconfig['password'])
            ftp.cwd(os.path.dirname(ftpconfig['path']))
            self.file = open('games_mp.log', 'ab')
            size=os.path.getsize('games_mp.log')
            self.debug('Logfile updating, please wait')
            ftp.retrbinary('RETR ' + os.path.basename(ftpconfig['path']), handleDownload, rest=size)          
        else:
            self.bot('Game log %s', self.config.getpath('server', 'game_log'))
            f = self.config.getpath('server', 'game_log')
        self.bot('Starting bot reading file %s', f)
        self.screen.write('Using Gamelog    : %s\n' % f)

        if os.path.isfile(f):
            self.output = None
            self.input  = file(f, 'r')

            # seek to point in log file?
            if self.replay:
                pass
            elif self.config.has_option('server', 'seek'):
                seek = self.config.getboolean('server', 'seek')
                if seek:
                    self.input.seek(0, 2)
            else:
                self.input.seek(0, 2)
        else:
            self.error('Error reading file %s', f)
            raise SystemExit('Error reading file %s\n' % f)

        # setup rcon
        self.output = self.OutputClass(self, (self._rconIp, self._port), self.config.get('server', 'rcon_password'))
        # testing rcon
        res = self.output.write('Initiating %s' % self.config.get('b3', 'bot_name'))
        self.output.flush()
        self.screen.write('Testing RCON     : ')
        self.screen.flush()
        if res == 'Bad rconpassword.':
            self.screen.write('>>> ERROR: Bad RCON password! This will lead to errors and render B3 without any power to interact!\n')
            self.screen.flush()
            time.sleep(10)
        elif res == '':
            self.screen.write('>>> ERROR: There is something wrong with the rcon connection to the server!\n>>> ERROR: Check your server-ip and port!\n')
            self.screen.flush()
            time.sleep(10)
        else:
            self.screen.write('OK\n')

        self.loadEvents()
        self.screen.write('Loading Events   : %s events loaded\n' % len(self._events))
        self.clients  = b3.clients.Clients(self)
        self.loadPlugins()
        self.loadArbPlugins()

        self.game = b3.game.Game(self, self.gameName)
        self.queue = Queue.Queue(15)    # event queue

        atexit.register(self.shutdown)

        self.say('%s ^2[ONLINE]' % b3.version)
예제 #53
0
 def onStartup(self):
   if self.console.config.get('server','game_log')[0:6] == 'ftp://' :
       gamelog = self.console.config.get('server', 'game_log')
       self.ftpconfig = functions.splitDSN(gamelog)
       thread1 = threading.Thread( target=self.update)
       thread1.start()
예제 #54
0
 def init_thread(self, ftpfiledsn):
     self.sftpconfig = functions.splitDSN(ftpfiledsn)
     thread1 = threading.Thread(target=self.update)
     self.info("starting sftpytail thread")
     thread1.start()
     return thread1
예제 #55
0
 def initThread(self, ftpfileDSN):
     self.sftpconfig = functions.splitDSN(ftpfileDSN)
     thread1 = threading.Thread(target=self.update)
     self.info("Starting sftpytail thread")
     thread1.start()
예제 #56
0
 def test_postgresql(self):
     storage = getStorage('postgresql://*****:*****@localhost/b3', splitDSN('postgresql://*****:*****@localhost/b3'), Mock())
     self.assertIsInstance(storage, PostgresqlStorage)
예제 #57
0
class DBUpdate(object):
    """
    Console database update procedure.
    """
    def __init__(self, config=None):
        """
        Object constructor.
        :param config: The B3 configuration file path
        """
        if config:
            # use the specified configuration file
            config = b3.getAbsolutePath(config, True)
            if not os.path.isfile(config):
                console_exit('ERROR: configuration file not found (%s).\n'
                             'Please visit %s to create one.' % (config, B3_CONFIG_GENERATOR))
        else:
            # search a configuration file
            for p in ('b3.%s', 'conf/b3.%s', 'b3/conf/b3.%s',
                      os.path.join(HOMEDIR, 'b3.%s'), os.path.join(HOMEDIR, 'conf', 'b3.%s'),
                      os.path.join(HOMEDIR, 'b3', 'conf', 'b3.%s'), '@b3/conf/b3.%s'):
                for e in ('ini', 'cfg', 'xml'):
                    path = b3.getAbsolutePath(p % e, True)
                    if os.path.isfile(path):
                        print "Using configuration file: %s" % path
                        config = path
                        sleep(3)
                        break

            if not config:
                console_exit('ERROR: could not find any valid configuration file.\n'
                             'Please visit %s to create one.' % B3_CONFIG_GENERATOR)
        try:
            self.config = b3.config.MainConfig(b3.config.load(config))
            if self.config.analyze():
                raise b3.config.ConfigFileNotValid
        except b3.config.ConfigFileNotValid:
            console_exit('ERROR: configuration file not valid (%s).\n'
                         'Please visit %s to generate a new one.' % (config, B3_CONFIG_GENERATOR))

    def run(self):
        """
        Run the DB update
        """
        clearscreen()
        print """
                        _\|/_
                        (o o)    {:>32}
                +----oOO---OOo----------------------------------+
                |                                               |
                |             UPDATING B3 DATABASE              |
                |                                               |
                +-----------------------------------------------+

        """.format('B3 : %s' % b3.__version__)

        raw_input("press any key to start the update...")

        def _update_database(storage, update_version):
            """
            Update a B3 database.
            :param storage: the initialized storage module
            :param update_version: the update version
            """
            if B3version(b3.__version__) >= update_version:
                sql = b3.getAbsolutePath('@b3/sql/%s/b3-update-%s.sql' % (storage.protocol, update_version))
                if os.path.isfile(sql):
                    try:
                        print '>>> updating database to version %s' % update_version
                        sleep(.5)
                        storage.queryFromFile(sql)
                    except Exception, err:
                        print 'WARNING: could not update database properly: %s' % err
                        sleep(3)

        dsn = self.config.get('b3', 'database')
        dsndict = splitDSN(dsn)
        database = getStorage(dsn, dsndict, StubParser())

        _update_database(database, '1.3.0')
        _update_database(database, '1.6.0')
        _update_database(database, '1.7.0')
        _update_database(database, '1.8.1')
        _update_database(database, '1.9.0')
        _update_database(database, '1.10.0')

        console_exit('B3 database update completed!')