''' sessionManager.py Copyright 2006 Andres Riancho This file is part of w3af, w3af.sourceforge.net . w3af 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 version 2 of the License. w3af 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 w3af; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ''' import os try: import cPickle as pickle except ImportError: import pickle from core.controllers.w3afException import w3afException import core.controllers.outputManager as om import core.data.kb.knowledgeBase as kb import core.data.kb.config as cf import copy # only used for debugging memory problems of w3af import core.controllers.misc.memoryUsage as memoryUsage MAXUNSAVED = 5 class sessionManager: ''' This class manages a session Pickle _sessionData on every call to save. unPickle _sessionData when initing with a filename as paremeter to __init__. @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__( self ): self._sessionDirectory = '.sessions' self._sessionName = 'defaultSession' self._saveCount = 0 def saveSession( self, sessionName='defaultSession' ): self._sessionName = sessionName self._sessionData = {} def loadSession( self, sessionName ): self._sessionName = sessionName # Load the session self._loadSession() self._loadKb() self._loadCf() def setSessionDir( self, sessionDirectory ): self._sessionDirectory = sessionDirectory def save( self, variable, value ): ''' Saves the options to a file. @parameter variable: The variable that we want to save data to @parameter value: The value of that variable ''' # This is called for debugging, no session manager logic here... memoryUsage.dumpMemoryUsage() #om.out.debug( 'Saving: ' + str(variable) ) self._sessionData[ variable ] = value self._saveCount += 1 if self._saveCount == MAXUNSAVED: # Save to disk self._saveSessionData() self._saveKbData() self._saveCfData() # Restore count self._saveCount = 0 # Inform what i did om.out.debug('Written session to disk. This is done only after ' + str(MAXUNSAVED) + ' calls to save().') def getData( self, variable ): if variable in self._sessionData: #om.out.debug( 'I was saved: ' + str(variable) ) return self._sessionData[ variable ] else: return None def _loadCf( self ): cf.cf = self._load( self._sessionName + '.cf' ) def _loadKb( self ): kb.kb = self._load( self._sessionName + '.kb' ) kb.kb.createLock() def _loadSession( self ): try: self._sessionData = self._load( self._sessionName + '.data' ) except Exception, e: self._sessionData = {} self._save() om.out.error('Failed to load session file, starting a a new session.') def _load( self, fileName ): ''' Loads an object from the fileName. @parameter fileName: The filename where the options are read. @return: An object instance. ''' if not os.path.exists(self._sessionDirectory): raise w3afException('The session directory does not exist.') try: file = open( os.path.join(self._sessionDirectory, fileName) , 'rb' ) except IOError: raise w3afException('Could not open session file for reading, filename: ' + fileName ) else: try: try: return pickle.load(file) except pickle.PicklingError, pe: raise w3afException('The object cant be pickled. Error: ' + str(pe) ) finally: file.close() def _saveKbData( self ): pickable = self._makePickableKB( kb.kb ) # Now , save the kb to disk self._saveData( pickable , self._sessionName + '.kb' ) def _saveCfData( self ): # Now , save the config to disk self._saveData( cf.cf , self._sessionName + '.cf' ) def _saveSessionData( self ): pickable = self._makePickableData( self._sessionData ) self._saveData( pickable, self._sessionName + '.data' ) def _saveData( self, data, fileName ): if fileName != None: if not os.path.exists(self._sessionDirectory): os.mkdir(self._sessionDirectory) try: file = open( os.path.join(self._sessionDirectory, fileName) , 'w' ) except IOError: raise w3afException('Could not open session file for writing.') else: try: try: pickle.dump( data , file ) except pickle.PicklingError, pe: raise w3afException('The object cant be pickled. Error: ' + str(pe) ) finally: file.close() def _makePickableKB( self, data ): ''' Some plugins save data to the kb that cant be pickled (for example, error404page saves a instance method). So i remove the data from the kb AND also remove the entry from the self._sessionData that says : "error404Page" was already runned, dont run again. ''' res = data if data.getData( 'error404page','404' ) != []: functor = data.getData( 'error404page','404' ) data.save( 'error404page','404', [] ) data.destroyLock() res = copy.deepcopy( data ) data.createLock() data.save( 'error404page','404', functor ) else: # data is error404 free data.destroyLock() res = copy.deepcopy( data ) data.createLock() return res def _makePickableData( self, data ): ''' Some plugins save data to the kb that cant be pickled (for example, error404page saves a instance method). So i remove the data from the kb AND also remove the entry from the self._sessionData that says : "error404Page" was already runned, dont run again. ''' res = data for i in data: if i[0] == 'error404page': tmp = copy.copy( res ) tmp.pop( i ) res = tmp return res