Codebase list python-faraday / debian/1.0.7-0kali1 persistence / orm.py
debian/1.0.7-0kali1

Tree @debian/1.0.7-0kali1 (Download .tar.gz)

orm.py @debian/1.0.7-0kali1raw · history · blame

'''
Faraday Penetration Test IDE - Community Version
Copyright (C) 2013  Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information

'''

import model
import threading
import traceback
from controllers.change import ChangeController


class WorkspacePersister(object):
    _instance = None
    _persister = None
    _workspace = None
    _workspace_autoloader = None
    _pending_actions = None
    _change_controller = ChangeController()

    def __new__(cls, *args, **kargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kargs)
        return cls._instance

    def setPersister(self, workspace, persister):
        WorkspacePersister._persister = persister
        WorkspacePersister._workspace = workspace
        WorkspacePersister._change_controller.setWorkspace(workspace)
        WorkspacePersister._workspace_autoloader = WorkspaceAutoSync(self.loadChanges, self.backendChangeListener)
        WorkspacePersister._workspace_autoloader.start()
        WorkspacePersister._pending_actions = PendingTransactionsQueue()

    @staticmethod
    def stopThreads():
        WorkspacePersister._workspace_autoloader.stop()

    def loadChanges(self, changes):
        self._change_controller.loadChanges(changes)

    def reloadWorkspace(self):
        WorkspacePersister._workspace.load()

    @staticmethod
    def addPendingAction(obj, func, args, kwargs):
        if "wait" not in func.__name__:
            WorkspacePersister._pending_actions.pushPendingTransaction(obj, func, args, kwargs)

    @staticmethod
    def reExecutePendingActions():
        for (obj, func, args, kwargs) in WorkspacePersister._pending_actions:
            func(obj, *args, **kwargs)
            
        model.api.devlog("Re executing")

    @staticmethod
    def notifyPersisterConnectionLost():
        WorkspacePersister._workspace.notifyWorkspaceNoConnection()

    def backendChangeListener(self): 
        changes = WorkspacePersister._persister.waitForDBChange(WorkspacePersister._workspace.name)
        return changes

    @staticmethod
    def save(obj):
        if WorkspacePersister._workspace is not None:
            WorkspacePersister._workspace.saveObj(obj)

    @staticmethod
    def delete(obj):
        if WorkspacePersister._workspace:
            WorkspacePersister._workspace.delObj(obj)

class WorkspaceAutoSync(threading.Thread):
    def __init__(self, action_callback, listener):
        threading.Thread.__init__(self)
        self.setDaemon(True)
        self._stop = False
        self._listener = listener
        self._action = action_callback

    def run(self):
        while not self._stop:
            try:
                result = self._listener()
                if result:
                    model.api.devlog("Changes found: %s" % result)
                    self._action(result)
            except Exception, e:
                model.api.devlog("An exception was captured while saving workspaces\n%s" % traceback.format_exc())

    def stop(self):
        self._stop = True

    def start(self):
        self._stop = False
        threading.Thread.start(self)


class PendingTransactionsQueue(object):
    def __init__(self):
        self.pending = []

    def pushPendingTransaction(self, obj, func, args, kwargs):
        self.pending.insert(0, (obj, func, args, kwargs))

    def __iter__(self):
        return self

    def next(self):
        try:
            return self.pending.pop()
        except IndexError:
            raise StopIteration