diff options
| author | Peter LaFosse <peter@vector35.com> | 2017-08-10 15:30:42 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2017-08-11 13:35:47 -0400 |
| commit | 326253abc74f7d6b601e03463df6abe8b8929428 (patch) | |
| tree | 61abc2d887ab63d17fe168d240d6a584c6769e19 /python | |
| parent | ca2aaa21523b210157fb71c066acfbebf9dadc78 (diff) | |
Fixes to allow plugins to be installed and loaded from headless
Diffstat (limited to 'python')
| -rw-r--r-- | python/__init__.py | 42 | ||||
| -rw-r--r-- | python/pluginmanager.py | 17 |
2 files changed, 59 insertions, 0 deletions
diff --git a/python/__init__.py b/python/__init__.py index 45b115b9..f4a8fac8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -20,6 +20,8 @@ import atexit +import sys + # Binary Ninja components import _binaryninjacore as core from .enums import * @@ -75,6 +77,46 @@ def get_install_directory(): return core.BNGetInstallDirectory() +_plugin_api_name = "python2" + + +class PluginManagerLoadPluginCallback(object): + """Callback for BNLoadPluginForApi("python2", ...), dynamicly loads python plugins.""" + def __init__(self): + self.cb = ctypes.CFUNCTYPE( + ctypes.c_bool, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_void_p)(self._load_plugin) + + def _load_plugin(self, repo_path, plugin_path, ctx): + try: + repo = RepositoryManager()[repo_path] + plugin = repo[plugin_path] + + if plugin.api != _plugin_api_name: + raise ValueError("Plugin api name is not " + _plugin_api_name) + + if not plugin.installed: + plugin.installed = True + + if repo.full_path not in sys.path: + sys.path.append(repo.full_path) + + __import__(plugin.path) + log_info("Successfully loaded plugin: {}/{}: ".format(repo_path, plugin_path)) + return True + except KeyError: + log_error("Failed to find python plugin: {}/{}".format(repo_path, plugin_path)) + except ImportError as ie: + log_error("Failed to import python plugin: {}/{}: {}".format(repo_path, plugin_path, ie)) + return False + + +load_plugin = PluginManagerLoadPluginCallback() +core.BNRegisterForPluginLoading(_plugin_api_name, load_plugin.cb, 0) + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() diff --git a/python/pluginmanager.py b/python/pluginmanager.py index c0f70260..6896d699 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -144,6 +144,12 @@ class Repository(object): def __repr__(self): return "<{} - {}/{}>".format(self.path, self.remote_reference, self.local_reference) + def __getitem__(self, plugin_path): + for plugin in self.plugins: + if plugin_path == plugin.path: + return plugin + raise KeyError() + @property def url(self): """String url of the git repository where the plugin repository's are stored""" @@ -155,6 +161,11 @@ class Repository(object): return core.BNRepositoryGetRepoPath(self.handle) @property + def full_path(self): + """String full path the repository""" + return core.BNRepositoryGetPluginsPath(self.handle) + + @property def local_reference(self): """String for the local git reference (ie 'master')""" return core.BNRepositoryGetLocalReference(self.handle) @@ -190,6 +201,12 @@ class RepositoryManager(object): def __init__(self, handle=None): self.handle = core.BNGetRepositoryManager() + def __getitem__(self, repo_path): + for repo in self.repositories: + if repo_path == repo.path: + return repo + raise KeyError() + def check_for_updates(self): """Check for updates for all managed Repository objects""" return core.BNRepositoryManagerCheckForUpdates(self.handle) |
