summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2017-03-04 18:11:43 -0500
committerPeter LaFosse <peter@vector35.com>2017-03-04 18:11:43 -0500
commita0132eed82d28d4408a2475847e1804a157b3dc1 (patch)
tree3e1136b01b340f8cfcdf883311f153c22f1f2b24
parentffdcc904ea16467c51e3d36773be132b7aa4cb3f (diff)
Adding repo manager APIs
-rw-r--r--binaryninjaapi.cpp4
-rw-r--r--binaryninjaapi.h83
-rw-r--r--binaryninjacore.h117
-rw-r--r--pluginmanager.cpp261
-rw-r--r--python/__init__.py1
-rw-r--r--python/pluginmanager.py359
-rw-r--r--python/startup.py1
7 files changed, 825 insertions, 1 deletions
diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp
index e1dab528..1864e389 100644
--- a/binaryninjaapi.cpp
+++ b/binaryninjaapi.cpp
@@ -41,6 +41,10 @@ void BinaryNinja::InitUserPlugins()
BNInitUserPlugins();
}
+void BinaryNinja::InitRepoPlugins()
+{
+ BNInitRepoPlugins();
+}
string BinaryNinja::GetBundledPluginDirectory()
{
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index a918fc42..0ba18f05 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -341,6 +341,7 @@ namespace BinaryNinja
void InitCorePlugins();
void InitUserPlugins();
+ void InitRepoPlugins();
std::string GetBundledPluginDirectory();
void SetBundledPluginDirectory(const std::string& path);
std::string GetUserPluginDirectory();
@@ -2425,4 +2426,86 @@ namespace BinaryNinja
virtual BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text,
BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon) = 0;
};
+
+ typedef BNPluginOrigin PluginOrigin;
+ typedef BNPluginUpdateStatus PluginUpdateStatus;
+ typedef BNPluginType PluginType;
+ typedef BNRepositoryManifest RepositoryManifest;
+
+ class RepoPlugin: public CoreRefCountObject<BNRepoPlugin, BNNewPluginReference, BNFreePlugin>
+ {
+ public:
+ RepoPlugin(const std::string& path,
+ bool installed,
+ bool enabled,
+ const std::string& api,
+ const std::string& author,
+ const std::string& description,
+ const std::string& license,
+ const std::string& licenseText,
+ const std::string& longdescription,
+ const std::string& minimimVersions,
+ const std::string& name,
+ const std::vector<PluginType>& pluginTypes,
+ const std::string& url,
+ const std::string& version);
+ RepoPlugin(BNRepoPlugin* plugin);
+ std::string GetPath() const;
+ bool IsInstalled() const;
+ std::string GetPluginDirectory() const;
+ void SetEnabled(bool enabled);
+ bool IsEnabled() const;
+ PluginUpdateStatus GetPluginUpdateStatus() const;
+ std::string GetApi() const;
+ std::string GetAuthor() const;
+ std::string GetDescription() const;
+ std::string GetLicense() const;
+ std::string GetLicenseText() const;
+ std::string GetLongdescription() const;
+ std::string GetMinimimVersions() const;
+ std::string GetName() const;
+ std::vector<PluginType> GetPluginTypes() const;
+ std::string GetUrl() const;
+ std::string GetVersion() const;
+ };
+
+ class Repository: public CoreRefCountObject<BNRepository, BNNewRepositoryReference, BNFreeRepository>
+ {
+ public:
+ Repository(const std::string& url, // URL of the git repository containing the plugins
+ const std::string& repoPath, // Name of the directory to store this repository within the repositories directory
+ const std::string& repoManifest="plugins", // Name of the of the inner directory and .json file
+ const std::string& localReference="master",
+ const std::string& remoteReference="origin");
+ Repository(BNRepository* repository);
+ ~Repository();
+ std::string GetUrl() const;
+ std::string GetRepoPath() const;
+ std::string GetLocalReference() const;
+ std::string GetRemoteReference() const;
+ std::vector<Ref<RepoPlugin>> GetPlugins() const;
+ bool IsInitialized() const;
+ std::string GetPluginDirectory() const;
+ Ref<RepoPlugin> GetPluginByPath(const std::string& pluginPath);
+ std::string GetFullPath() const;
+ };
+
+ class RepositoryManager: public CoreRefCountObject<BNRepositoryManager, BNNewRepositoryManagerReference, BNFreeRepositoryManager>
+ {
+ bool m_core;
+ public:
+ RepositoryManager(std::vector<Ref<Repository>>& repoInfo, const std::string& enabledPluginsPath);
+ RepositoryManager(BNRepositoryManager* repoManager);
+ RepositoryManager();
+ ~RepositoryManager();
+ bool CheckForUpdates();
+ std::vector<Ref<Repository>> GetRepositories();
+ Ref<Repository> GetRepositoryByPath(const std::string& repoName);
+ bool AddRepository(Ref<Repository> repo);
+ bool EnablePlugin(const std::string& repoName, const std::string& pluginPath);
+ bool DisablePlugin(const std::string& repoName, const std::string& pluginPath);
+ bool InstallPlugin(const std::string& repoName, const std::string& pluginPath);
+ bool UninstallPlugin(const std::string& repoName, const std::string& pluginPath);
+ Ref<Repository> GetDefaultRepository();
+ };
}
diff --git a/binaryninjacore.h b/binaryninjacore.h
index b2ed7cd3..44ae666b 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -45,6 +45,12 @@
#endif
#endif
+#ifdef WIN32
+#define PATH_SEP "\\"
+#else
+#define PATH_SEP "/"
+#endif
+
#define BN_MAX_INSTRUCTION_LENGTH 256
#define BN_DEFAULT_NSTRUCTION_LENGTH 16
#define BN_DEFAULT_OPCODE_DISPLAY 8
@@ -104,6 +110,11 @@ extern "C"
struct BNScriptingInstance;
struct BNMainThreadAction;
struct BNBackgroundTask;
+ struct BNRepository;
+ struct BNRepoPlugin;
+ struct BNRepositoryManager;
+
+ typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx);
//! Console log levels
enum BNLogLevel
@@ -567,6 +578,27 @@ extern "C"
ComparisonResultValue
};
+ enum BNPluginOrigin
+ {
+ OfficialPluginOrigin,
+ CommunityPluginOrigin,
+ OtherPluginOrigin
+ };
+
+ enum BNPluginUpdateStatus
+ {
+ UpToDatePluginStatus,
+ UpdatesAvailablePluginStatus
+ };
+
+ enum BNPluginType
+ {
+ CorePluginType,
+ UiPluginType,
+ ArchitecturePluginType,
+ BinaryViewPluginType
+ };
+
struct BNLookupTableEntry
{
int64_t* fromValues;
@@ -1187,6 +1219,12 @@ extern "C"
uint64_t end;
};
+ struct BNRepositoryManifest
+ {
+ const char* ManifestFile;
+ const char* RepoDirectory;
+ };
+
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
BINARYNINJACOREAPI void BNFreeString(char* str);
BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count);
@@ -1204,10 +1242,13 @@ extern "C"
// Plugin initialization
BINARYNINJACOREAPI void BNInitCorePlugins(void);
BINARYNINJACOREAPI void BNInitUserPlugins(void);
+ BINARYNINJACOREAPI void BNInitRepoPlugins(void);
+
BINARYNINJACOREAPI char* BNGetBundledPluginDirectory(void);
BINARYNINJACOREAPI void BNSetBundledPluginDirectory(const char* path);
BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void);
-
+ BINARYNINJACOREAPI char* BNGetUserDirectory(void);
+ BINARYNINJACOREAPI char* BNGetRepositoriesDirectory(void);
BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path);
BINARYNINJACOREAPI char* BNGetPathRelativeToUserPluginDirectory(const char* path);
@@ -2243,6 +2284,80 @@ extern "C"
char*** outVarName,
size_t* outVarNameElements);
BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements);
+
+ // Plugin repository APIs
+ BINARYNINJACOREAPI const char* BNPluginGetApi(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetAuthor(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetDescription(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetLicense(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetLicenseText(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetLongdescription(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetMinimimVersions(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetName(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetUrl(BNRepoPlugin* p);
+ BINARYNINJACOREAPI const char* BNPluginGetVersion(BNRepoPlugin* p);
+ BINARYNINJACOREAPI void BNFreePluginTypes(BNPluginType* r);
+ BINARYNINJACOREAPI BNRepoPlugin* BNCreatePlugin(const char* path,
+ bool installed,
+ bool enabled,
+ const char* api,
+ const char* author,
+ const char* description,
+ const char* license,
+ const char* licenseText,
+ const char* longdescription,
+ const char* minimimVersions,
+ const char* name,
+ const BNPluginType* pluginTypes,
+ size_t pluginTypesSize,
+ const char* url,
+ const char* version);
+ BINARYNINJACOREAPI BNRepoPlugin* BNNewPluginReference(BNRepoPlugin* r);
+ BINARYNINJACOREAPI void BNFreePlugin(BNRepoPlugin* plugin);
+ BINARYNINJACOREAPI const char* BNPluginGetPath(BNRepoPlugin* p);
+ BINARYNINJACOREAPI bool BNPluginIsInstalled(BNRepoPlugin* p);
+ BINARYNINJACOREAPI void BNPluginSetEnabled(BNRepoPlugin* p, bool enabled);
+ BINARYNINJACOREAPI bool BNPluginIsEnabled(BNRepoPlugin* p);
+ BINARYNINJACOREAPI BNPluginUpdateStatus BNPluginGetPluginUpdateStatus(BNRepoPlugin* p);
+ BINARYNINJACOREAPI BNPluginType* BNPluginGetPluginTypes(BNRepoPlugin* p, size_t* count);
+ BINARYNINJACOREAPI BNRepository* BNCreateRepository(const char* url,
+ const char* repoPath,
+ const char* localReference,
+ const char* remoteReference);
+ BINARYNINJACOREAPI BNRepository* BNNewRepositoryReference(BNRepository* r);
+ BINARYNINJACOREAPI void BNFreeRepository(BNRepository* r);
+ BINARYNINJACOREAPI char* BNRepositoryGetUrl(BNRepository* r);
+ BINARYNINJACOREAPI char* BNRepositoryGetRepoPath(BNRepository* r);
+ BINARYNINJACOREAPI char* BNRepositoryGetLocalReference(BNRepository* r);
+ BINARYNINJACOREAPI char* BNRepositoryGetRemoteReference(BNRepository* r);
+ BINARYNINJACOREAPI BNRepoPlugin** BNRepositoryGetPlugins(BNRepository* r, size_t* count);
+ BINARYNINJACOREAPI void BNFreeRepositoryPluginList(BNRepoPlugin** r);
+ BINARYNINJACOREAPI bool BNRepositoryIsInitialized(BNRepository* r);
+ BINARYNINJACOREAPI void BNRepositoryFreePluginDirectoryList(char** list, size_t count);
+ BINARYNINJACOREAPI BNRepoPlugin* BNRepositoryGetPluginByPath(BNRepository* r, const char* pluginPath);
+ BINARYNINJACOREAPI const char* BNRepositoryGetPluginsPath(BNRepository* r);
+
+ BINARYNINJACOREAPI BNRepositoryManager* BNCreateRepositoryManager(BNRepository** repos,
+ size_t reposSize,
+ const char* enabledPluginsPath);
+ BINARYNINJACOREAPI BNRepositoryManager* BNNewRepositoryManagerReference(BNRepositoryManager* r);
+ BINARYNINJACOREAPI void BNFreeRepositoryManager(BNRepositoryManager* r);
+ BINARYNINJACOREAPI bool BNRepositoryManagerCheckForUpdates(BNRepositoryManager* r);
+ BINARYNINJACOREAPI BNRepository** BNRepositoryManagerGetRepositories(BNRepositoryManager* r, size_t* count);
+ BINARYNINJACOREAPI void BNFreeRepositoryManagerRepositoriesList(BNRepository** r);
+ BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, BNRepository* repo);
+ BINARYNINJACOREAPI bool BNRepositoryManagerEnablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath);
+ BINARYNINJACOREAPI bool BNRepositoryManagerDisablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath);
+ BINARYNINJACOREAPI bool BNRepositoryManagerInstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath);
+ BINARYNINJACOREAPI bool BNRepositoryManagerUninstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath);
+ BINARYNINJACOREAPI bool BNRepositoryManagerUpdatePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath);
+ BINARYNINJACOREAPI BNRepository* BNRepositoryGetRepositoryByPath(BNRepositoryManager* r, const char* repoPath);
+ BINARYNINJACOREAPI BNRepositoryManager* BNGetRepositoryManager();
+
+ BINARYNINJACOREAPI BNRepository* BNRepositoryManagerGetDefaultRepository(BNRepositoryManager* r);
+ BINARYNINJACOREAPI void BNRegisterForPluginLoading(const char* pluginApiName, BNLoadPluginCallback cb, void* ctx);
+ BINARYNINJACOREAPI bool BNLoadPluginForApi(const char* pluginApiName, const char* repoPath, const char* pluginPath);
+
#ifdef __cplusplus
}
#endif
diff --git a/pluginmanager.cpp b/pluginmanager.cpp
new file mode 100644
index 00000000..24f6f09f
--- /dev/null
+++ b/pluginmanager.cpp
@@ -0,0 +1,261 @@
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+#define RETURN_STRING(s) do { \
+ char* contents = (char*)(s); \
+ string result(contents); \
+ BNFreeString(contents); \
+ return result; \
+}while(0)
+
+RepoPlugin::RepoPlugin(const string& path,
+ bool installed,
+ bool enabled,
+ const string& api,
+ const string& author,
+ const string& description,
+ const string& license,
+ const string& licenseText,
+ const string& longdescription,
+ const string& minimimVersions,
+ const string& name,
+ const vector<PluginType>& pluginTypes,
+ const string& url,
+ const string& version)
+{
+ m_object = BNCreatePlugin(path.c_str(),
+ installed,
+ enabled,
+ api.c_str(),
+ author.c_str(),
+ description.c_str(),
+ license.c_str(),
+ licenseText.c_str(),
+ longdescription.c_str(),
+ minimimVersions.c_str(),
+ name.c_str(),
+ &pluginTypes[0],
+ pluginTypes.size(),
+ url.c_str(),
+ version.c_str());
+}
+
+RepoPlugin::RepoPlugin(BNRepoPlugin* plugin)
+{
+ m_object = plugin;
+}
+
+string RepoPlugin::GetPath() const
+{
+ RETURN_STRING(BNPluginGetPath(m_object));
+}
+
+bool RepoPlugin::IsInstalled() const
+{
+ return BNPluginIsInstalled(m_object);
+}
+
+void RepoPlugin::SetEnabled(bool enabled)
+{
+ return BNPluginSetEnabled(m_object, enabled);
+}
+
+bool RepoPlugin::IsEnabled() const
+{
+ return BNPluginIsEnabled(m_object);
+}
+
+PluginUpdateStatus RepoPlugin::GetPluginUpdateStatus() const
+{
+ return BNPluginGetPluginUpdateStatus(m_object);
+}
+
+string RepoPlugin::GetApi() const
+{
+ RETURN_STRING(BNPluginGetApi(m_object));
+}
+
+string RepoPlugin::GetAuthor() const
+{
+ RETURN_STRING(BNPluginGetAuthor(m_object));
+}
+
+string RepoPlugin::GetDescription() const
+{
+ RETURN_STRING(BNPluginGetDescription(m_object));
+}
+
+string RepoPlugin::GetLicense() const
+{
+ RETURN_STRING(BNPluginGetLicense(m_object));
+}
+
+string RepoPlugin::GetLicenseText() const
+{
+ RETURN_STRING(BNPluginGetLicenseText(m_object));
+}
+
+string RepoPlugin::GetLongdescription() const
+{
+ RETURN_STRING(BNPluginGetLongdescription(m_object));
+}
+
+string RepoPlugin::GetMinimimVersions() const
+{
+ RETURN_STRING(BNPluginGetMinimimVersions(m_object));
+}
+
+string RepoPlugin::GetName() const
+{
+ RETURN_STRING(BNPluginGetName(m_object));
+}
+
+vector<PluginType> RepoPlugin::GetPluginTypes() const
+{
+ size_t count;
+ BNPluginType* pluginTypesPtr = BNPluginGetPluginTypes(m_object, &count);
+ vector<PluginType> pluginTypes;
+ for (size_t i = 0; i < count; i++)
+ {
+ pluginTypes.push_back((PluginType)pluginTypesPtr[i]);
+ }
+ BNFreePluginTypes(pluginTypesPtr);
+ return pluginTypes;
+}
+
+string RepoPlugin::GetUrl() const
+{
+ RETURN_STRING(BNPluginGetUrl(m_object));
+}
+
+string RepoPlugin::GetVersion() const
+{
+ RETURN_STRING(BNPluginGetVersion(m_object));
+}
+
+Repository::Repository(const string& url,
+ const string& repoPath,
+ const string& repoManifest,
+ const string& localReference,
+ const string& remoteReference)
+{
+ m_object = BNCreateRepository(url.c_str(),
+ repoPath.c_str(),
+ localReference.c_str(),
+ remoteReference.c_str());
+}
+
+Repository::Repository(BNRepository* r)
+{
+ m_object = r;
+}
+
+Repository::~Repository()
+{
+ BNFreeRepository(m_object);
+}
+string Repository::GetUrl() const
+{
+ RETURN_STRING(BNRepositoryGetUrl(m_object));
+}
+string Repository::GetRepoPath() const
+{
+ RETURN_STRING(BNRepositoryGetRepoPath(m_object));
+}
+
+string Repository::GetLocalReference() const
+{
+ RETURN_STRING(BNRepositoryGetLocalReference(m_object));
+}
+
+string Repository::GetRemoteReference() const
+{
+ RETURN_STRING(BNRepositoryGetRemoteReference(m_object));
+}
+
+vector<Ref<RepoPlugin>> Repository::GetPlugins() const
+{
+ vector<Ref<RepoPlugin>> plugins;
+ size_t count = 0;
+ BNRepoPlugin** pluginsPtr = BNRepositoryGetPlugins(m_object, &count);
+ for (size_t i = 0; i < count; i++)
+ plugins.push_back(new RepoPlugin(BNNewPluginReference(pluginsPtr[i])));
+ BNFreeRepositoryPluginList(pluginsPtr);
+ return plugins;
+}
+
+bool Repository::IsInitialized() const
+{
+ return BNRepositoryIsInitialized(m_object);
+}
+
+Ref<RepoPlugin> Repository::GetPluginByPath(const string& pluginPath)
+{
+ return new RepoPlugin(BNNewPluginReference(BNRepositoryGetPluginByPath(m_object, pluginPath.c_str())));
+}
+
+string Repository::GetFullPath() const
+{
+ RETURN_STRING(BNRepositoryGetPluginsPath(m_object));
+}
+
+RepositoryManager::RepositoryManager(vector<Ref<Repository>>& repoInfo, const string& enabledPluginsPath)
+ :m_core(false)
+{
+ BNRepository** buffer = new BNRepository*[repoInfo.size()];
+ for (size_t i = 0; i < repoInfo.size(); i++)
+ buffer[i] = repoInfo[i]->m_object;
+ m_object = BNCreateRepositoryManager(buffer, repoInfo.size(), enabledPluginsPath.c_str());
+ delete[] buffer;
+}
+
+RepositoryManager::RepositoryManager(BNRepositoryManager* mgr)
+ :m_core(false)
+{
+ m_object = mgr;
+}
+
+RepositoryManager::RepositoryManager()
+ :m_core(true)
+{
+ m_object = BNGetRepositoryManager();
+}
+
+RepositoryManager::~RepositoryManager()
+{
+ if (!m_core)
+ BNFreeRepositoryManager(m_object);
+}
+
+bool RepositoryManager::CheckForUpdates()
+{
+ return BNRepositoryManagerCheckForUpdates(m_object);
+}
+
+vector<Ref<Repository>> RepositoryManager::GetRepositories()
+{
+ vector<Ref<Repository>> repos;
+ size_t count = 0;
+ BNRepository** reposPtr = BNRepositoryManagerGetRepositories(m_object, &count);
+ for (size_t i = 0; i < count; i++)
+ repos.push_back(new Repository(BNNewRepositoryReference(reposPtr[i])));
+ BNFreeRepositoryManagerRepositoriesList(reposPtr);
+ return repos;
+}
+
+bool RepositoryManager::AddRepository(Ref<Repository> repo)
+{
+ return BNRepositoryManagerAddRepository(m_object, repo->GetObject());
+}
+
+Ref<Repository> RepositoryManager::GetRepositoryByPath(const std::string& repoPath)
+{
+ return new Repository(BNNewRepositoryReference(BNRepositoryGetRepositoryByPath(m_object, repoPath.c_str())));
+}
+
+Ref<Repository> RepositoryManager::GetDefaultRepository()
+{
+ return new Repository(BNNewRepositoryReference(BNRepositoryManagerGetDefaultRepository(m_object)));
+}
diff --git a/python/__init__.py b/python/__init__.py
index a1ea02f5..5df7c7f1 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -45,6 +45,7 @@ from .lineardisassembly import *
from .undoaction import *
from .highlight import *
from .scriptingprovider import *
+from .pluginmanager import *
def shutdown():
diff --git a/python/pluginmanager.py b/python/pluginmanager.py
new file mode 100644
index 00000000..348f13fb
--- /dev/null
+++ b/python/pluginmanager.py
@@ -0,0 +1,359 @@
+# Copyright (c) 2015-2016 Vector 35 LLC
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import ctypes
+
+# Binary Ninja components
+import _binaryninjacore as core
+from .enums import PluginType, PluginUpdateStatus
+import startup
+
+
+class RepoPlugin(object):
+ """
+ ``Plugin`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins.
+ """
+ def __init__(self, handle):
+ self.handle = core.handle_of_type(handle, core.BNRepoPlugin)
+
+ def __del__(self):
+ core.BNFreePlugin(self.handle)
+
+ def __repr__(self):
+ return "<{} {}/{}>".format(self.path, "installed" if self.installed else "not-installed", "enabled" if self.enabled else "disabled")
+
+ @property
+ def path(self):
+ """Relative path from the base of the repository to the actual plugin"""
+ return core.BNPluginGetPath(self.handle)
+
+ @property
+ def installed(self):
+ """Boolean True if the plugin is installed, False otherwise"""
+ return core.BNPluginIsInstalled(self.handle)
+
+ @property
+ def enabled(self):
+ """Boolean True if the plugin is currently enabled, False otherwise"""
+ return core.BNPluginIsEnabled(self.handle)
+
+ @property
+ def api(self):
+ """string indicating the api used by the plugin"""
+ return core.BNPluginGetApi(self.handle)
+
+ @property
+ def description(self):
+ """String short description of the plugin"""
+ return core.BNPluginGetDescription(self.handle)
+
+ @property
+ def license(self):
+ """String short license description (ie MIT, BSD, GPLv2, etc)"""
+ return core.BNPluginGetLicense(self.handle)
+
+ @property
+ def license_text(self):
+ """String complete license text for the given plugin"""
+ return core.BNPluginGetLicenseText(self.handle)
+
+ @property
+ def long_description(self):
+ """String long description of the plugin"""
+ return core.BNPluginGetLongdescription(self.handle)
+
+ @property
+ def minimum_version(self):
+ """String minimum version the plugin was tested on"""
+ return core.BNPluginGetMinimimVersions(self.handle)
+
+ @property
+ def name(self):
+ """String name of the plugin"""
+ return core.BNPluginGetName(self.handle)
+
+ @property
+ def plugin_types(self):
+ """List of PluginType enumeration objects indicating the plugin type(s)"""
+ result = []
+ count = ctypes.c_ulonglong(0)
+ plugintypes = core.BNPluginGetPluginTypes(self.handle, count)
+ for i in xrange(count.value):
+ result.append(PluginType(plugintypes[i]))
+ core.BNFreePluginTypes(plugintypes)
+ return result
+
+ @property
+ def url(self):
+ """String url of the plugin's git repository"""
+ return core.BNPluginGetUrl(self.handle)
+
+ @property
+ def version(self):
+ """String version of the plugin"""
+ return core.BNPluginGetVersion(self.handle)
+
+ @property
+ def update_status(self):
+ """PluginUpdateStatus enumeration indicating if the plugin is up to date or not"""
+ return PluginUpdateStatus(core.BNPluginGetPluginUpdateStatus(self.handle))
+
+
+class Repository(object):
+ """
+ ``Repository`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins.
+ """
+ def __init__(self, handle):
+ self.handle = core.handle_of_type(handle, core.BNRepository)
+
+ def __del__(self):
+ core.BNFreeRepository(self.handle)
+
+ def __repr__(self):
+ return "<{} - {}/{}>".format(self.path, self.remote_reference, self.local_reference)
+
+ @property
+ def url(self):
+ """String url of the git repository where the plugin repository's are stored"""
+ return core.BNRepositoryGetUrl(self.handle)
+
+ @property
+ def path(self):
+ """String local path to store the given plugin repository"""
+ return core.BNRepositoryGetRepoPath(self.handle)
+
+ @property
+ def local_reference(self):
+ """String for the local git reference (ie 'master')"""
+ return core.BNRepositoryGetLocalReference(self.handle)
+
+ @property
+ def remote_reference(self):
+ """String for the remote git reference (ie 'origin')"""
+ return core.BNRepositoryGetRemoteReference(self.handle)
+
+ @property
+ def plugins(self):
+ """List of Plugin objects contained within this repository"""
+ pluginlist = []
+ count = ctypes.c_ulonglong(0)
+ result = core.BNRepositoryGetPlugins(self.handle, count)
+ for i in xrange(count.value):
+ pluginlist.append(RepoPlugin(handle=result[i]))
+ core.BNFreeRepositoryPluginList(result, count.value)
+ del result
+ return pluginlist
+
+ @property
+ def initialized(self):
+ """Boolean True when the repository has been initialized"""
+ return core.BNRepositoryIsInitialized(self.handle)
+
+
+class RepositoryManager(object):
+ def __init__(self, handle=None):
+ self.handle = core.BNGetRepositoryManager()
+
+ def check_for_updates(self):
+ """Check for updates for all managed Repository objects"""
+ return core.BNRepositoryManagerCheckForUpdates(self.handle)
+
+ @property
+ def repositories(self):
+ """List of Repository objects being managed"""
+ result = []
+ count = ctypes.c_ulonglong(0)
+ repos = core.BNRepositoryManagerGetRepositories(self.handle, count)
+ for i in xrange(count.value):
+ result.append(Repository(handle=repos[i]))
+ core.BNFreeRepositoryManagerRepositoriesList(repos)
+ return result
+
+ @property
+ def plugins(self):
+ """List of all RepoPlugins in each repository"""
+ plgs = {}
+ for repo in self.repositories:
+ plgs[repo.path] = repo.plugins
+ return plgs
+
+ @property
+ def default_repository(self):
+ """Gets the default Repository"""
+ startup._init_plugins()
+ return Repository(handle=core.BNRepositoryManagerGetDefaultRepository(self.handle))
+
+ def enable_plugin(self, plugin, install=True, repo=None):
+ """
+ ``enable_plugin`` Enables the installed plugin 'plugin', optionally installing the plugin if `install` is set to
+ True (default), and optionally using the non-default repository.
+
+ :param str name: Name of the plugin to enable
+ :param Boolean install: Optionally install the repo, defaults to True.
+ :param str repo: Optional, specify a repository other than the default repository.
+ :return: Boolean value True if the plugin was successfully enabled, False otherwise
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.enable_plugin('binaryninja-bookmarks')
+ True
+ >>>
+ """
+ if install:
+ if not self.install_plugin(plugin, repo):
+ return False
+
+ if repo is None:
+ repo = self.default_repository
+ repopath = repo
+ pluginpath = plugin
+ if not isinstance(repo, str):
+ repopath = repo.path
+ if not isinstance(plugin, str):
+ pluginpath = plugin.path
+ return core.BNRepositoryManagerEnablePlugin(self.handle, repopath, pluginpath)
+
+ def disable_plugin(self, plugin, repo=None):
+ """
+ ``disable_plugin`` Disable the specified plugin, pluginpath
+
+ :param Repository or str repo: Repository containing the plugin to disable
+ :param Plugin or str plugin: Plugin to disable
+ :return: Boolean value True if the plugin was successfully disabled, False otherwise
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.disable_plugin('binaryninja-bookmarks')
+ True
+ >>>
+ """
+ if repo is None:
+ repo = self.default_repository
+ repopath = repo
+ pluginpath = plugin
+ if not isinstance(repo, str):
+ repopath = repo.path
+ if not isinstance(plugin, str):
+ pluginpath = plugin.path
+ return core.BNRepositoryManagerDisablePlugin(self.handle, repopath, pluginpath)
+
+ def install_plugin(self, plugin, repo=None):
+ """
+ ``install_plugin`` install the specified plugin, pluginpath
+
+ :param Repository or str repo: Repository containing the plugin to install
+ :param Plugin or str plugin: Plugin to install
+ :return: Boolean value True if the plugin was successfully installed, False otherwise
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.install_plugin('binaryninja-bookmarks')
+ True
+ >>>
+ """
+ if repo is None:
+ repo = self.default_repository
+ repopath = repo
+ pluginpath = plugin
+ if not isinstance(repo, str):
+ repopath = repo.path
+ if not isinstance(plugin, str):
+ pluginpath = plugin.path
+ return core.BNRepositoryManagerInstallPlugin(self.handle, repopath, pluginpath)
+
+ def uninstall_plugin(self, plugin, repo=None):
+ """
+ ``uninstall_plugin`` uninstall the specified plugin, pluginpath
+
+ :param Repository or str repo: Repository containing the plugin to uninstall
+ :param Plugin or str plugin: Plugin to uninstall
+ :return: Boolean value True if the plugin was successfully uninstalled, False otherwise
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.uninstall_plugin('binaryninja-bookmarks')
+ True
+ >>>
+ """
+ if repo is None:
+ repo = self.default_repository
+ repopath = repo
+ pluginpath = plugin
+ if not isinstance(repo, str):
+ repopath = repo.path
+ if not isinstance(plugin, str):
+ pluginpath = plugin.path
+ return core.BNRepositoryManagerUninstallPlugin(self.handle, repopath, pluginpath)
+
+ def update_plugin(self, plugin, repo=None):
+ """
+ ``update_plugin`` update the specified plugin, pluginpath
+
+ :param Repository or str repo: Repository containing the plugin to update
+ :param Plugin or str plugin: Plugin to update
+ :return: Boolean value True if the plugin was successfully updated, False otherwise
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.update_plugin('binaryninja-bookmarks')
+ True
+ >>>
+ """
+ if repo is None:
+ repo = self.default_repository
+ repopath = repo
+ pluginpath = plugin
+ if not isinstance(repo, str):
+ repopath = repo.path
+ if not isinstance(plugin, str):
+ pluginpath = plugin.path
+ return core.BNRepositoryManagerUpdatePlugin(self.handle, repopath, pluginpath)
+
+ def add_repository(self, url=None, repopath=None, localreference="master", remotereference="origin"):
+ """
+ ``add_repository`` adds a new plugin repository for the manager to track.
+
+ :param str url: Url to the git repository where the plugins are stored.
+ :param str repopath: path to where the repository will be stored on disk locally
+ :param str localreference: Optional reference to the local tracking branch typically "master"
+ :param str remotereference: Optional reference to the remote tracking branch typically "origin"
+ :return: Boolean value True if the repository was successfully added, False otherwise.
+ :rtype: Boolean
+ :Example:
+
+ >>> mgr = RepositoryManager()
+ >>> mgr.add_repository(url="https://github.com/vector35/binaryninja-plugins.git",
+ repopath="myrepo",
+ repomanifest="plugins",
+ localreference="master", remotereference="origin")
+ True
+ >>>
+ """
+ if not (isinstance(url, str) and isinstance(repopath, str) and
+ isinstance(localreference, str) and isinstance(remotereference, str)):
+ raise ValueError("Parameter is incorrect type")
+ repo = core.BNCreateRepository(url, repopath, localreference, remotereference)
+
+ return core.BNRepositoryManagerAddRepository(self.handle, repo)
diff --git a/python/startup.py b/python/startup.py
index 809f185b..324cc690 100644
--- a/python/startup.py
+++ b/python/startup.py
@@ -30,5 +30,6 @@ def _init_plugins():
_plugin_init = True
core.BNInitCorePlugins()
core.BNInitUserPlugins()
+ core.BNInitRepoPlugins()
if not core.BNIsLicenseValidated():
raise RuntimeError("License is not valid. Please supply a valid license.")