diff options
| author | Peter LaFosse <peter@vector35.com> | 2019-05-14 21:34:57 -0700 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2019-07-08 23:14:30 -0400 |
| commit | ad37832dd4ffa112b10b523a151d3fa9b86b6c9d (patch) | |
| tree | 364641f60f878150bb010c4b51f088e49c8ba058 | |
| parent | 7e7f0b41548057093fb48f1d8985712b619e9438 (diff) | |
PluginManager refactor for supporting plugin installation ui
Expose additional PluginManager APIs and update documentation
| -rw-r--r-- | binaryninjaapi.cpp | 13 | ||||
| -rw-r--r-- | binaryninjaapi.h | 49 | ||||
| -rw-r--r-- | binaryninjacore.h | 67 | ||||
| -rw-r--r-- | pluginmanager.cpp | 181 | ||||
| -rw-r--r-- | python/__init__.py | 60 | ||||
| -rw-r--r-- | python/binaryview.py | 20 | ||||
| -rw-r--r-- | python/downloadprovider.py | 7 | ||||
| -rw-r--r-- | python/generator.cpp | 7 | ||||
| -rw-r--r-- | python/pluginmanager.py | 284 | ||||
| -rw-r--r-- | ui/uitypes.h | 3 |
10 files changed, 385 insertions, 306 deletions
diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 66ddbffd..5dcc3ad1 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -368,3 +368,16 @@ map<string, uint64_t> BinaryNinja::GetMemoryUsageInfo() BNFreeMemoryUsageInfo(info, count); return result; } + + +vector<string> BinaryNinja::GetRegisteredPluginLoaders() +{ + size_t count = 0; + char** loaders = BNGetRegisteredPluginLoaders(&count); + vector<string> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(loaders[i]); + BNFreeRegisteredPluginLoadersList(loaders, count); + return result; +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 258d1d8a..b3be594a 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -707,6 +707,7 @@ namespace BinaryNinja std::string GetUniqueIdentifierString(); std::map<std::string, uint64_t> GetMemoryUsageInfo(); + std::vector<std::string> GetRegisteredPluginLoaders(); class DataBuffer { @@ -4263,30 +4264,51 @@ namespace BinaryNinja }; typedef BNPluginOrigin PluginOrigin; - typedef BNPluginUpdateStatus PluginUpdateStatus; + typedef BNPluginStatus PluginStatus; typedef BNPluginType PluginType; class RepoPlugin: public CoreRefCountObject<BNRepoPlugin, BNNewPluginReference, BNFreePlugin> { public: RepoPlugin(BNRepoPlugin* plugin); + PluginStatus GetPluginStatus() const; + std::vector<std::string> GetApis() const; + std::vector<std::string> GetInstallPlatforms() const; 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 GetPackageUrl() const; + std::string GetProjectUrl() const; + std::string GetAuthorUrl() const; std::string GetVersion() const; + std::string GetCommit() const; + std::string GetRepository() const; + std::string GetProjectData(); + std::string GetInstallInstructions(const std::string& platform) const; + uint64_t GetMinimimVersion() const; + uint64_t GetLastUpdate(); + bool IsBeingDeleted() const; + bool IsBeingUpdated() const; + bool IsInstalled() const; + bool IsEnabled() const; + bool IsRunning() const; + bool IsUpdatePending() const; + bool IsDisablePending() const; + bool IsDeletePending() const; + bool IsUpdateAvailable() const; + + bool Uninstall(); + bool Install(); + // `force` ignores optional checks for platform/api compliance + bool Enable(bool force); + bool Disable(); + bool Update(); }; class Repository: public CoreRefCountObject<BNRepository, BNNewRepositoryReference, BNFreeRepository> @@ -4298,7 +4320,6 @@ namespace BinaryNinja 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; @@ -4313,14 +4334,8 @@ namespace BinaryNinja bool CheckForUpdates(); std::vector<Ref<Repository>> GetRepositories(); Ref<Repository> GetRepositoryByPath(const std::string& repoName); - bool AddRepository(const std::string& url, - const std::string& repoPath, // Relative path within the repositories directory - const std::string& localReference="master", - const std::string& remoteReference="origin"); - 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); + bool AddRepository(const std::string& url, // URL to raw plugins.json file + const std::string& repoPath); // Relative path within the repositories directory Ref<Repository> GetDefaultRepository(); }; diff --git a/binaryninjacore.h b/binaryninjacore.h index c4b90f7e..842a2a50 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -161,7 +161,7 @@ extern "C" struct BNDataRendererContainer; struct BNDisassemblyTextRenderer; - typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx); + typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, bool force, void* ctx); //! Console log levels enum BNLogLevel @@ -779,10 +779,18 @@ extern "C" OtherPluginOrigin }; - enum BNPluginUpdateStatus + enum BNPluginStatus { - UpToDatePluginStatus, - UpdatesAvailablePluginStatus + NotInstalledPluginStatus = 0x00000000, + InstalledPluginStatus = 0x00000001, + EnabledPluginStatus = 0x00000002, + UpdateAvailablePluginStatus = 0x00000010, + DeletePendingPluginStatus = 0x00000020, + UpdatePendingPluginStatus = 0x00000040, + DisablePendingPluginStatus = 0x00000080, + PendingRestartPluginStatus = 0x00000200, + BeingUpdatedPluginStatus = 0x00000400, + BeingDeletedPluginStatus = 0x00000800 }; enum BNPluginType @@ -790,7 +798,8 @@ extern "C" CorePluginType, UiPluginType, ArchitecturePluginType, - BinaryViewPluginType + BinaryViewPluginType, + HelperPluginType }; struct BNLookupTableEntry @@ -3717,39 +3726,53 @@ extern "C" BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements); // Plugin repository APIs - BINARYNINJACOREAPI const char* BNPluginGetApi(BNRepoPlugin* p); + BINARYNINJACOREAPI char** BNPluginGetApis(BNRepoPlugin* p, size_t* count); 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 uint64_t BNPluginGetMinimimVersion(BNRepoPlugin* p); BINARYNINJACOREAPI const char* BNPluginGetName(BNRepoPlugin* p); - BINARYNINJACOREAPI const char* BNPluginGetUrl(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetProjectUrl(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetPackageUrl(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetAuthorUrl(BNRepoPlugin* p); BINARYNINJACOREAPI const char* BNPluginGetVersion(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetCommit(BNRepoPlugin* p); BINARYNINJACOREAPI void BNFreePluginTypes(BNPluginType* r); 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 BNPluginStatus BNPluginGetPluginStatus(BNRepoPlugin* p); BINARYNINJACOREAPI BNPluginType* BNPluginGetPluginTypes(BNRepoPlugin* p, size_t* count); - BINARYNINJACOREAPI bool BNPluginEnable(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginEnable(BNRepoPlugin* p, bool force); BINARYNINJACOREAPI bool BNPluginDisable(BNRepoPlugin* p); BINARYNINJACOREAPI bool BNPluginInstall(BNRepoPlugin* p); BINARYNINJACOREAPI bool BNPluginUninstall(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginUpdate(BNRepoPlugin* p); + BINARYNINJACOREAPI char* BNPluginGetInstallInstructions(BNRepoPlugin* p, const char* platform); + BINARYNINJACOREAPI char** BNPluginGetPlatforms(BNRepoPlugin* p, size_t* count); + BINARYNINJACOREAPI void BNFreePluginPlatforms(char** platforms, size_t count); + BINARYNINJACOREAPI const char* BNPluginGetRepository(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsBeingDeleted(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsBeingUpdated(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsRunning(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsUpdatePending(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsDisablePending(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsDeletePending(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsUpdateAvailable(BNRepoPlugin* p); + + BINARYNINJACOREAPI char* BNPluginGetProjectData(BNRepoPlugin* p); + BINARYNINJACOREAPI uint64_t BNPluginGetLastUpdate(BNRepoPlugin* p); 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); @@ -3762,23 +3785,18 @@ extern "C" BINARYNINJACOREAPI void BNFreeRepositoryManagerRepositoriesList(BNRepository** r); BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, const char* url, - const char* repoPath, - const char* localReference, - const char* remoteReference); - 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); + const char* repoPath); BINARYNINJACOREAPI BNRepository* BNRepositoryGetRepositoryByPath(BNRepositoryManager* r, const char* repoPath); BINARYNINJACOREAPI BNRepositoryManager* BNGetRepositoryManager(); BINARYNINJACOREAPI BNRepository* BNRepositoryManagerGetDefaultRepository(BNRepositoryManager* r); BINARYNINJACOREAPI void BNRegisterForPluginLoading( const char* pluginApiName, - bool (*cb)(const char* repoPath, const char* pluginPath, void* ctx), + bool (*cb)(const char* repoPath, const char* pluginPath, bool force, void* ctx), // BNLoadPluginCallback void* ctx); - BINARYNINJACOREAPI bool BNLoadPluginForApi(const char* pluginApiName, const char* repoPath, const char* pluginPath); + BINARYNINJACOREAPI bool BNLoadPluginForApi(const char* pluginApiName, const char* repoPath, const char* pluginPath, bool force); + BINARYNINJACOREAPI char** BNGetRegisteredPluginLoaders(size_t* count); + BINARYNINJACOREAPI void BNFreeRegisteredPluginLoadersList(char** pluginLoaders, size_t count); // LLVM Services APIs BINARYNINJACOREAPI void BNLlvmServicesInit(void); @@ -3796,6 +3814,7 @@ extern "C" BINARYNINJACOREAPI bool BNIsPathDirectory(const char* path); BINARYNINJACOREAPI bool BNIsPathRegularFile(const char* path); BINARYNINJACOREAPI bool BNFileSize(const char* path, uint64_t* size); + BINARYNINJACOREAPI bool BNRenameFile(const char* source, const char* dest); // Settings APIs BINARYNINJACOREAPI bool BNSettingsRegisterGroup(const char* registry, const char* group, const char* title); diff --git a/pluginmanager.cpp b/pluginmanager.cpp index be0d0d9d..9572d362 100644 --- a/pluginmanager.cpp +++ b/pluginmanager.cpp @@ -25,24 +25,27 @@ 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 +PluginStatus RepoPlugin::GetPluginStatus() const { - return BNPluginGetPluginUpdateStatus(m_object); + return BNPluginGetPluginStatus(m_object); } -string RepoPlugin::GetApi() const +vector<string> RepoPlugin::GetApis() const { - RETURN_STRING(BNPluginGetApi(m_object)); + vector<string> result; + size_t count = 0; + char** apis = BNPluginGetApis(m_object, &count); + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.push_back(apis[i]); + + BNFreeStringList(apis, count); + return result; } string RepoPlugin::GetAuthor() const @@ -70,9 +73,9 @@ string RepoPlugin::GetLongdescription() const RETURN_STRING(BNPluginGetLongdescription(m_object)); } -string RepoPlugin::GetMinimimVersions() const +uint64_t RepoPlugin::GetMinimimVersion() const { - RETURN_STRING(BNPluginGetMinimimVersions(m_object)); + return BNPluginGetMinimimVersion(m_object); } string RepoPlugin::GetName() const @@ -93,16 +96,142 @@ vector<PluginType> RepoPlugin::GetPluginTypes() const return pluginTypes; } -string RepoPlugin::GetUrl() const + +string RepoPlugin::GetProjectUrl() const { - RETURN_STRING(BNPluginGetUrl(m_object)); + RETURN_STRING(BNPluginGetProjectUrl(m_object)); } + +string RepoPlugin::GetPackageUrl() const +{ + RETURN_STRING(BNPluginGetPackageUrl(m_object)); +} + + +string RepoPlugin::GetAuthorUrl() const +{ + RETURN_STRING(BNPluginGetAuthorUrl(m_object)); +} + + string RepoPlugin::GetVersion() const { RETURN_STRING(BNPluginGetVersion(m_object)); } + +string RepoPlugin::GetCommit() const +{ + RETURN_STRING(BNPluginGetCommit(m_object)); +} + + +string RepoPlugin::GetRepository() const +{ + RETURN_STRING(BNPluginGetRepository(m_object)); +} + + +vector<string> RepoPlugin::GetInstallPlatforms() const +{ + vector<string> result; + size_t count = 0; + char** platforms = BNPluginGetPlatforms(m_object, &count); + for (size_t i = 0; i < count; i++) + result.push_back(platforms[i]); + BNFreeStringList(platforms, count); + return result; +} + + +std::string RepoPlugin::GetInstallInstructions(const std::string& platform) const +{ + RETURN_STRING(BNPluginGetInstallInstructions(m_object, platform.c_str())); +} + + +bool RepoPlugin::IsBeingDeleted() const +{ + return BNPluginIsBeingDeleted(m_object); +} + +bool RepoPlugin::IsBeingUpdated() const +{ + return BNPluginIsBeingUpdated(m_object); +} + +bool RepoPlugin::IsRunning() const +{ + return BNPluginIsRunning(m_object); +} + + +bool RepoPlugin::IsUpdatePending() const +{ + return BNPluginIsUpdatePending(m_object); +} + + +bool RepoPlugin::IsDisablePending() const +{ + return BNPluginIsDisablePending(m_object); +} + + +bool RepoPlugin::IsDeletePending() const +{ + return BNPluginIsDeletePending(m_object); +} + + +bool RepoPlugin::IsUpdateAvailable() const +{ + return BNPluginIsUpdateAvailable(m_object); +} + + +uint64_t RepoPlugin::GetLastUpdate() +{ + return BNPluginGetLastUpdate(m_object); +} + +string RepoPlugin::GetProjectData() +{ + RETURN_STRING(BNPluginGetProjectData(m_object)); +} + + +bool RepoPlugin::Uninstall() +{ + return BNPluginUninstall(m_object); +} + + +bool RepoPlugin::Install() +{ + return BNPluginInstall(m_object); +} + + +bool RepoPlugin::Enable(bool force) +{ + return BNPluginEnable(m_object, force); +} + + +bool RepoPlugin::Update() +{ + return BNPluginUpdate(m_object); +} + + +bool RepoPlugin::Disable() +{ + return BNPluginDisable(m_object); +} + + Repository::Repository(BNRepository* r) { m_object = r; @@ -112,36 +241,26 @@ 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); + plugins.reserve(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) { @@ -185,15 +304,9 @@ vector<Ref<Repository>> RepositoryManager::GetRepositories() } bool RepositoryManager::AddRepository(const std::string& url, - const std::string& repoPath, // Relative path within the repositories directory - const std::string& localReference, - const std::string& remoteReference) + const std::string& repoPath) // Relative path within the repositories directory { - return BNRepositoryManagerAddRepository(m_object, - url.c_str(), - repoPath.c_str(), - localReference.c_str(), - remoteReference.c_str()); + return BNRepositoryManagerAddRepository(m_object, url.c_str(), repoPath.c_str()); } Ref<Repository> RepositoryManager::GetRepositoryByPath(const std::string& repoPath) diff --git a/python/__init__.py b/python/__init__.py index bdc6bdd7..f572bdef 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -24,7 +24,7 @@ import atexit import sys import ctypes from time import gmtime - +import os # 2-3 compatibility PY2 = sys.version_info[0] == 2 @@ -92,37 +92,7 @@ def pyNativeStr(arg): # Binary Ninja components import binaryninja._binaryninjacore as core -# __all__ = [ -# "enums", -# "databuffer", -# "filemetadata", -# "fileaccessor", -# "binaryview", -# "transform", -# "architecture", -# "basicblock", -# "function", -# "log", -# "lowlevelil", -# "mediumlevelil", -# "types", -# "functionrecognizer", -# "update", -# "plugin", -# "callingconvention", -# "platform", -# "demangle", -# "mainthread", -# "interaction", -# "lineardisassembly", -# "undoaction", -# "highlight", -# "scriptingprovider", -# "pluginmanager", -# "setting", -# "metadata", -# "flowgraph", -# ] + from binaryninja.enums import * from binaryninja.databuffer import * from binaryninja.filemetadata import * @@ -179,34 +149,42 @@ def get_install_directory(): return core.BNGetInstallDirectory() -_plugin_api_name = "python2" +_plugin_api_name = "python{}".format(sys.version_info.major) class PluginManagerLoadPluginCallback(object): - """Callback for BNLoadPluginForApi("python2", ...), dynamically loads python plugins.""" + """Callback for BNLoadPluginForApi("python{version}", ...), dynamically loads python plugins.""" def __init__(self): self.cb = ctypes.CFUNCTYPE( ctypes.c_bool, ctypes.c_char_p, ctypes.c_char_p, + ctypes.c_bool, ctypes.c_void_p)(self._load_plugin) - def _load_plugin(self, repo_path, plugin_path, ctx): + def _load_plugin(self, repo_path, plugin_path, force, ctx): try: + repo_path = repo_path.decode("utf-8") + plugin_path = plugin_path.decode("utf-8") repo = RepositoryManager()[repo_path] plugin = repo[plugin_path] - if plugin.api != _plugin_api_name: + if not force and _plugin_api_name not in plugin.api: raise ValueError("Plugin API name is not " + _plugin_api_name) + if not force and core.core_platform not in plugin.install_platforms: + raise ValueError("Current platform {} ins't in list of valid platforms for this plugin {}".format( + core.core_platform, plugin.install_platforms)) if not plugin.installed: plugin.installed = True + plugin_full_path = os.path.join(repo.full_path, plugin.path) if repo.full_path not in sys.path: sys.path.append(repo.full_path) + if plugin_full_path not in sys.path: + sys.path.append(plugin_full_path) - __import__(plugin.path) - log_info("Successfully loaded plugin: {}/{}: ".format(repo_path, plugin_path)) + __import__(plugin_path) return True except KeyError: log_error("Failed to find python plugin: {}/{}".format(repo_path, plugin_path)) @@ -284,12 +262,12 @@ def core_version(): def core_build_id(): """ - ``core_build_id`` returns a string containing the current build id + ``core_build_id`` returns a integer containing the current build id :return: current build id - :rtype: str, or None on failure + :rtype: int """ - core.BNGetBuildId() + return core.BNGetBuildId() def core_serial(): """ diff --git a/python/binaryview.py b/python/binaryview.py index 4ffe197e..4f146adc 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -645,7 +645,8 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): :rtype: BinaryView or None """ sqlite = b"SQLite format 3" - if filename.endswith(".bndb"): + isDatabase = filename.endswith(".bndb") + if isDatabase: f = open(filename, 'rb') if f is None or f.read(len(sqlite)) != sqlite: return None @@ -658,18 +659,21 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): return None for available in view.available_view_types: if available.name != "Raw": - if filename.endswith(".bndb"): + if isDatabase: bv = view.get_view_of_type(available.name) else: bv = cls[available.name].open(filename) + break + else: + if isDatabase: + bv = view.get_view_of_type("Raw") + else: + bv = cls["Raw"].open(filename) - if bv is None: - raise Exception("Unknown Architecture/Architecture Not Found (check plugins folder)") + if bv is not None and update_analysis: + bv.update_analysis_and_wait() + return bv - if update_analysis: - bv.update_analysis_and_wait() - return bv - return None def is_valid_for_data(self, data): return core.BNIsBinaryViewTypeValidForData(self.handle, data.handle) diff --git a/python/downloadprovider.py b/python/downloadprovider.py index 8d3718b9..27f007ff 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -79,9 +79,6 @@ class DownloadInstance(object): def perform_request(self, ctxt, url): raise NotImplementedError - def perform_request(self, url, callbacks): - return core.BNPerformDownloadRequest(self.handle, url, callbacks) - class _DownloadProviderMetaclass(type): @property @@ -165,11 +162,9 @@ if (sys.platform != "win32") and (sys.version_info >= (2, 7, 9)): def __init__(self, provider): super(PythonDownloadInstance, self).__init__(provider) - @abc.abstractmethod def perform_destroy_instance(self): pass - @abc.abstractmethod def perform_request(self, url): try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') @@ -223,11 +218,9 @@ else: def __init__(self, provider): super(PythonDownloadInstance, self).__init__(provider) - @abc.abstractmethod def perform_destroy_instance(self): pass - @abc.abstractmethod def perform_request(self, url): try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') diff --git a/python/generator.cpp b/python/generator.cpp index dbb44253..8186647a 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -188,13 +188,14 @@ int main(int argc, char* argv[]) fprintf(out, "import platform\n"); fprintf(out, "core = None\n"); fprintf(out, "_base_path = None\n"); - fprintf(out, "if platform.system() == \"Darwin\":\n"); + fprintf(out, "core_platform = platform.system()\n"); + fprintf(out, "if core_platform == \"Darwin\":\n"); fprintf(out, "\t_base_path = os.path.join(os.path.dirname(__file__), \"..\", \"..\", \"..\", \"MacOS\")\n"); fprintf(out, "\tcore = ctypes.CDLL(os.path.join(_base_path, \"libbinaryninjacore.dylib\"))\n\n"); - fprintf(out, "elif platform.system() == \"Linux\":\n"); + fprintf(out, "elif core_platform == \"Linux\":\n"); fprintf(out, "\t_base_path = os.path.join(os.path.dirname(__file__), \"..\", \"..\")\n"); fprintf(out, "\tcore = ctypes.CDLL(os.path.join(_base_path, \"libbinaryninjacore.so.1\"))\n\n"); - fprintf(out, "elif platform.system() == \"Windows\":\n"); + fprintf(out, "elif core_platform == \"Windows\":\n"); fprintf(out, "\t_base_path = os.path.join(os.path.dirname(__file__), \"..\", \"..\")\n"); fprintf(out, "\tcore = ctypes.CDLL(os.path.join(_base_path, \"binaryninjacore.dll\"))\n"); fprintf(out, "else:\n"); diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 3f75d68b..73fe0db6 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -19,10 +19,13 @@ # IN THE SOFTWARE. import ctypes +import json +from datetime import datetime # Binary Ninja components +import binaryninja from binaryninja import _binaryninjacore as core - +from binaryninja.enums import PluginType, PluginStatus # 2-3 compatibility from binaryninja import range @@ -32,9 +35,7 @@ class RepoPlugin(object): ``RepoPlugin` is mostly read-only, however you can install/uninstall enable/disable plugins. RepoPlugins are created by parsing the plugins.json in a plugin repository. """ - from binaryninja.enums import PluginType, PluginUpdateStatus def __init__(self, handle): - raise Exception("RepoPlugin temporarily disabled!") self.handle = core.handle_of_type(handle, core.BNRepoPlugin) def __del__(self): @@ -68,14 +69,29 @@ class RepoPlugin(object): @enabled.setter def enabled(self, state): if state: - return core.BNPluginEnable(self.handle) + return core.BNPluginEnable(self.handle, False) else: return core.BNPluginDisable(self.handle) + def enable(self, force=False): + """ + Enable this plugin, optionally trying to force it. + Force loading a plugin with ignore platform and api constraints. + (e.g. The plugin author says the plugin will only work on Linux-python3 but you'd like to + attempt to load it on Macos-python2) + """ + return core.BNPluginEnable(self.handle, force) + @property def api(self): """string indicating the API used by the plugin""" - return core.BNPluginGetApi(self.handle) + result = [] + count = ctypes.c_ulonglong(0) + platforms = core.BNPluginGetApis(self.handle, count) + for i in range(count.value): + result.append(platforms[i]) + core.BNFreePluginPlatforms(platforms, count) + return result @property def description(self): @@ -100,7 +116,7 @@ class RepoPlugin(object): @property def minimum_version(self): """String minimum version the plugin was tested on""" - return core.BNPluginGetMinimimVersions(self.handle) + return core.BNPluginGetMinimimVersion(self.handle) @property def name(self): @@ -119,34 +135,109 @@ class RepoPlugin(object): return result @property - def url(self): + def project_url(self): """String URL of the plugin's git repository""" - return core.BNPluginGetUrl(self.handle) + return core.BNPluginGetProjectUrl(self.handle) + + @property + def package_url(self): + """String URL of the plugin's zip file""" + return core.BNPluginGetPackageUrl(self.handle) + + @property + def author_url(self): + """String URL of the plugin author's url""" + return core.BNPluginGetAuthorUrl(self.handle) + + @property + def author(self): + """String of the plugin author""" + return core.BNPluginGetAuthor(self.handle) @property def version(self): """String version of the plugin""" return core.BNPluginGetVersion(self.handle) + + def install_instructions(self, platform): + """ + Installation instructions for the given platform + + :param str platform: One of the valid platforms "Windows", "Linux", "Darwin" + :return: String of the installation instructions for the provided platform + :rtype: str + """ + return core.BNPluginGetInstallInstructions(self.handle, platform) + @property - def update_status(self): - """PluginUpdateStatus enumeration indicating if the plugin is up to date or not""" - return PluginUpdateStatus(core.BNPluginGetPluginUpdateStatus(self.handle)) + def install_platforms(self): + """List of platforms this plugin can execute on""" + result = [] + count = ctypes.c_ulonglong(0) + platforms = core.BNPluginGetPlatforms(self.handle, count) + for i in range(count.value): + result.append(platforms[i]) + core.BNFreePluginPlatforms(platforms, count) + return result + @property + def being_deleted(self): + """Boolean status indicating that the plugin is being deleted""" + return core.BNPluginIsBeingDeleted(self.handle) + + @property + def being_updated(self): + """Boolean status indicating that the plugin is being updated""" + return core.BNPluginIsBeingUpdated(self.handle) + + @property + def running(self): + """Boolean status indicating that the plugin is currently running""" + return core.BNPluginIsRunning(self.handle) + + @property + def update_pending(self): + """Boolean status indicating that the plugin has updates will be installed after the next restart""" + return core.BNPluginIsUpdatePending(self.handle) + + @property + def disable_pending(self): + """Boolean status indicating that the plugin will be disabled after the next restart""" + return core.BNPluginIsDisablePending(self.handle) + + @property + def delete_pending(self): + """Boolean status indicating that the plugin will be deleted after the next restart""" + return core.BNPluginIsDeletePending(self.handle) + + @property + def update_available(self): + """Boolean status indicating that the plugin has updates available""" + return core.BNPluginIsUpdateAvailable(self.handle) + + @property + def project_data(self): + """Gets a json object of the project data field""" + return json.loads(core.BNPluginGetProjectData(self.handle)) + + @property + def last_update(self): + """Returns a datetime object representing the plugins last update""" + return datetime.fromtimestamp(core.BNPluginGetLastUpdate(self.handle)) class Repository(object): """ ``Repository`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. """ def __init__(self, handle): - raise Exception("Repository temporarily disabled!") 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) + return "<{}>".format(self.path) def __getitem__(self, plugin_path): for plugin in self.plugins: @@ -170,32 +261,17 @@ class Repository(object): return core.BNRepositoryGetPluginsPath(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 RepoPlugin objects contained within this repository""" pluginlist = [] count = ctypes.c_ulonglong(0) result = core.BNRepositoryGetPlugins(self.handle, count) for i in range(count.value): - pluginlist.append(RepoPlugin(handle=result[i])) + pluginlist.append(RepoPlugin(core.BNNewPluginReference(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): """ @@ -203,7 +279,6 @@ class RepositoryManager(object): the plugins that are installed/uninstalled enabled/disabled """ def __init__(self, handle=None): - raise Exception("RepositoryManager temporarily disabled!") self.handle = core.BNGetRepositoryManager() def __getitem__(self, repo_path): @@ -223,7 +298,7 @@ class RepositoryManager(object): count = ctypes.c_ulonglong(0) repos = core.BNRepositoryManagerGetRepositories(self.handle, count) for i in range(count.value): - result.append(Repository(handle=repos[i])) + result.append(Repository(core.BNNewRepositoryReference(repos[i]))) core.BNFreeRepositoryManagerRepositoriesList(repos) return result @@ -239,160 +314,25 @@ class RepositoryManager(object): def default_repository(self): """Gets the default Repository""" binaryninja._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. + return Repository(core.BNNewRepositoryReference(core.BNRepositoryManagerGetDefaultRepository(self.handle))) - :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 RepoPlugin or str plugin: RepoPlugin 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 RepoPlugin or str plugin: RepoPlugin 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 RepoPlugin or str plugin: RepoPlugin 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 RepoPlugin or str plugin: RepoPlugin 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"): + def add_repository(self, url=None, repopath=None): """ ``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 url: URL to the plugins.json containing the records for this repository :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/community-plugins.git", - repopath="myrepo", - localreference="master", remotereference="origin") + >>> mgr.add_repository("https://raw.githubusercontent.com/Vector35/community-plugins/master/plugins.json", "community") True >>> """ - if not (isinstance(url, str) and isinstance(repopath, str) and - isinstance(localreference, str) and isinstance(remotereference, str)): + if not isinstance(url, str) or not isinstance(repopath, str): raise ValueError("Parameter is incorrect type") - return core.BNRepositoryManagerAddRepository(self.handle, url, repopath, localreference, remotereference) + return core.BNRepositoryManagerAddRepository(self.handle, url, repopath) diff --git a/ui/uitypes.h b/ui/uitypes.h index ed93d0c6..557063f3 100644 --- a/ui/uitypes.h +++ b/ui/uitypes.h @@ -58,3 +58,6 @@ typedef BinaryNinja::Ref<BinaryNinja::Symbol> SymbolRef; typedef BinaryNinja::Ref<BinaryNinja::TemporaryFile> TemporaryFileRef; typedef BinaryNinja::Ref<BinaryNinja::Transform> TransformRef; typedef BinaryNinja::Ref<BinaryNinja::Type> TypeRef; +typedef BinaryNinja::Ref<BinaryNinja::RepoPlugin> RepoPluginRef; +typedef BinaryNinja::Ref<BinaryNinja::Repository> RepositoryRef; +typedef BinaryNinja::Ref<BinaryNinja::RepositoryManager> RepositoryManagerRef; |
