summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2017-08-10 15:30:42 -0400
committerPeter LaFosse <peter@vector35.com>2017-08-11 13:35:47 -0400
commit326253abc74f7d6b601e03463df6abe8b8929428 (patch)
tree61abc2d887ab63d17fe168d240d6a584c6769e19 /python
parentca2aaa21523b210157fb71c066acfbebf9dadc78 (diff)
Fixes to allow plugins to be installed and loaded from headless
Diffstat (limited to 'python')
-rw-r--r--python/__init__.py42
-rw-r--r--python/pluginmanager.py17
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)