summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.cpp18
-rw-r--r--binaryninjaapi.h60
-rw-r--r--binaryninjacore.h43
-rw-r--r--docs/about/open-source.md6
-rw-r--r--downloadprovider.cpp135
-rw-r--r--python/__init__.py1
-rw-r--r--python/downloadprovider.py210
-rw-r--r--python/pluginmanager.py3
8 files changed, 447 insertions, 29 deletions
diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp
index f5eede03..b774cf2b 100644
--- a/binaryninjaapi.cpp
+++ b/binaryninjaapi.cpp
@@ -344,21 +344,3 @@ string BinaryNinja::GetUniqueIdentifierString()
BNFreeString(str);
return result;
}
-
-
-string BinaryNinja::GetLinuxCADirectory()
-{
- char* str = BNGetLinuxCADirectory();
- string result = str;
- BNFreeString(str);
- return result;
-}
-
-
-string BinaryNinja::GetLinuxCABundlePath()
-{
- char* str = BNGetLinuxCABundlePath();
- string result = str;
- BNFreeString(str);
- return result;
-}
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 7a13118f..9c0b9bc4 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -3636,6 +3636,63 @@ namespace BinaryNinja
const std::string& autoTypeSource = "");
};
+ // DownloadProvider
+ class DownloadProvider;
+
+ class DownloadInstance: public CoreRefCountObject<BNDownloadInstance, BNNewDownloadInstanceReference, BNFreeDownloadInstance>
+ {
+ protected:
+ DownloadInstance(DownloadProvider* provider);
+ DownloadInstance(BNDownloadInstance* instance);
+
+ static void DestroyInstanceCallback(void* ctxt);
+ static int PerformRequestCallback(void* ctxt, const char* url);
+
+ virtual void DestroyInstance();
+
+ public:
+ virtual int PerformRequest(const std::string& url) = 0;
+
+ int PerformRequest(const std::string& url, BNDownloadInstanceOutputCallbacks* callbacks);
+
+ std::string GetError() const;
+ void SetError(const std::string& error);
+ };
+
+ class CoreDownloadInstance: public DownloadInstance
+ {
+ public:
+ CoreDownloadInstance(BNDownloadInstance* instance);
+
+ virtual int PerformRequest(const std::string& url) override;
+ };
+
+ class DownloadProvider: public StaticCoreRefCountObject<BNDownloadProvider>
+ {
+ std::string m_nameForRegister;
+
+ protected:
+ DownloadProvider(const std::string& name);
+ DownloadProvider(BNDownloadProvider* provider);
+
+ static BNDownloadInstance* CreateInstanceCallback(void* ctxt);
+
+ public:
+ virtual Ref<DownloadInstance> CreateNewInstance() = 0;
+
+ static std::vector<Ref<DownloadProvider>> GetList();
+ static Ref<DownloadProvider> GetByName(const std::string& name);
+ static void Register(DownloadProvider* provider);
+ };
+
+ class CoreDownloadProvider: public DownloadProvider
+ {
+ public:
+ CoreDownloadProvider(BNDownloadProvider* provider);
+ virtual Ref<DownloadInstance> CreateNewInstance() override;
+ };
+
+ // Scripting Provider
class ScriptingOutputListener
{
BNScriptingOutputListener m_callbacks;
@@ -3994,7 +4051,4 @@ namespace BinaryNinja
bool IsArray() const;
bool IsKeyValueStore() const;
};
-
- std::string GetLinuxCADirectory();
- std::string GetLinuxCABundlePath();
}
diff --git a/binaryninjacore.h b/binaryninjacore.h
index e4d3a919..e4fb9de2 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -120,6 +120,8 @@ extern "C"
struct BNArchitecture;
struct BNFunction;
struct BNBasicBlock;
+ struct BNDownloadProvider;
+ struct BNDownloadInstance;
struct BNFunctionGraph;
struct BNFunctionGraphBlock;
struct BNSymbol;
@@ -1483,6 +1485,27 @@ extern "C"
size_t count, total;
};
+ struct BNDownloadInstanceOutputCallbacks
+ {
+ uint64_t (*writeCallback)(uint8_t* data, uint64_t len, void* ctxt);
+ void* writeContext;
+ bool (*progressCallback)(void* ctxt, uint64_t progress, uint64_t total);
+ void* progressContext;
+ };
+
+ struct BNDownloadInstanceCallbacks
+ {
+ void* context;
+ void (*destroyInstance)(void* ctxt);
+ int (*performRequest)(void* ctxt, const char* url);
+ };
+
+ struct BNDownloadProviderCallbacks
+ {
+ void* context;
+ BNDownloadInstance* (*createInstance)(void* ctxt);
+ };
+
enum BNFindFlag
{
NoFindFlags = 0,
@@ -3195,6 +3218,24 @@ extern "C"
char*** outVarName,
size_t* outVarNameElements);
+ // Download providers
+ BINARYNINJACOREAPI BNDownloadProvider* BNRegisterDownloadProvider(const char* name, BNDownloadProviderCallbacks* callbacks);
+ BINARYNINJACOREAPI BNDownloadProvider** BNGetDownloadProviderList(size_t* count);
+ BINARYNINJACOREAPI void BNFreeDownloadProviderList(BNDownloadProvider** providers);
+ BINARYNINJACOREAPI BNDownloadProvider* BNGetDownloadProviderByName(const char* name);
+
+ BINARYNINJACOREAPI char* BNGetDownloadProviderName(BNDownloadProvider* provider);
+ BINARYNINJACOREAPI BNDownloadInstance* BNCreateDownloadProviderInstance(BNDownloadProvider* provider);
+
+ BINARYNINJACOREAPI BNDownloadInstance* BNInitDownloadInstance(BNDownloadProvider* provider, BNDownloadInstanceCallbacks* callbacks);
+ BINARYNINJACOREAPI BNDownloadInstance* BNNewDownloadInstanceReference(BNDownloadInstance* instance);
+ BINARYNINJACOREAPI void BNFreeDownloadInstance(BNDownloadInstance* instance);
+ BINARYNINJACOREAPI int BNPerformDownloadRequest(BNDownloadInstance* instance, const char* url, BNDownloadInstanceOutputCallbacks* callbacks);
+ BINARYNINJACOREAPI uint64_t BNWriteDataForDownloadInstance(BNDownloadInstance* instance, uint8_t* data, uint64_t len);
+ BINARYNINJACOREAPI bool BNNotifyProgressForDownloadInstance(BNDownloadInstance* instance, uint64_t progress, uint64_t total);
+ BINARYNINJACOREAPI char* BNGetErrorForDownloadInstance(BNDownloadInstance* instance);
+ BINARYNINJACOREAPI void BNSetErrorForDownloadInstance(BNDownloadInstance* instance, const char* error);
+
// Scripting providers
BINARYNINJACOREAPI BNScriptingProvider* BNRegisterScriptingProvider(const char* name,
BNScriptingProviderCallbacks* callbacks);
@@ -3460,8 +3501,6 @@ extern "C"
BINARYNINJACOREAPI BNMetadata* BNBinaryViewQueryMetadata(BNBinaryView* view, const char* key);
BINARYNINJACOREAPI void BNBinaryViewRemoveMetadata(BNBinaryView* view, const char* key);
- BINARYNINJACOREAPI char* BNGetLinuxCADirectory();
- BINARYNINJACOREAPI char* BNGetLinuxCABundlePath();
#ifdef __cplusplus
}
#endif
diff --git a/docs/about/open-source.md b/docs/about/open-source.md
index b0a35f37..be9725d0 100644
--- a/docs/about/open-source.md
+++ b/docs/about/open-source.md
@@ -22,13 +22,11 @@ The previous tools are used in the generation of our documentation, but are not
* Core
- [discount] ([discount license] - BSD)
- - [libcurl] ([libcurl license] - MIT/X derivative)
- [libgit2] ([libgit2 license] - GPLv2 with linking exception)
- [libmspack] ([libmspack license] - LGPL, v2)
- [llvm] ([llvm license] - BSD-style)
- [lzf] ([lzf license] - BSD)
- [jemalloc] ([jemalloc license] - BSD)
- - [openssl] ([openssl license] - openssl license)
- [sqlite] ([sqlite license] - public domain)
- [zlib] ([zlib license] - zlib license)
@@ -69,8 +67,6 @@ Please note that we offer no support for running Binary Ninja with modified Qt l
[discount]: http://www.pell.portland.or.us/~orc/Code/discount/
[doxygen license]: https://github.com/doxygen/doxygen/blob/master/LICENSE
[doxygen]: http://www.stack.nl/~dimitri/doxygen/
-[libcurl]: https://curl.haxx.se/
-[libcurl license]: https://curl.haxx.se/docs/copyright.html
[libgit2]: https://libgit2.github.com/
[libgit2 license]: https://github.com/libgit2/libgit2/blob/master/COPYING
[libmspack]: https://www.cabextract.org.uk/libmspack/
@@ -87,8 +83,6 @@ Please note that we offer no support for running Binary Ninja with modified Qt l
[mkdocs]: http://www.mkdocs.org/
[opensans license]: http://www.apache.org/licenses/LICENSE-2.0.html
[opensans]: https://www.google.com/fonts/specimen/Open+Sans
-[openssl license]: https://www.openssl.org/source/license.html
-[openssl]: https://www.openssl.org/
[qt license]: https://www.qt.io/qt-licensing-terms/
[qt]: https://www.qt.io/download/
[sourcecodepro license]: https://github.com/adobe-fonts/source-code-pro/blob/master/LICENSE.txt
diff --git a/downloadprovider.cpp b/downloadprovider.cpp
new file mode 100644
index 00000000..0e3483df
--- /dev/null
+++ b/downloadprovider.cpp
@@ -0,0 +1,135 @@
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+DownloadInstance::DownloadInstance(DownloadProvider* provider)
+{
+ BNDownloadInstanceCallbacks cb;
+ cb.context = this;
+ cb.destroyInstance = DestroyInstanceCallback;
+ cb.performRequest = PerformRequestCallback;
+ m_object = BNInitDownloadInstance(provider->GetObject(), &cb);
+}
+
+
+DownloadInstance::DownloadInstance(BNDownloadInstance* instance)
+{
+ m_object = instance;
+}
+
+
+void DownloadInstance::DestroyInstanceCallback(void* ctxt)
+{
+ DownloadInstance* instance = (DownloadInstance*)ctxt;
+ instance->DestroyInstance();
+}
+
+
+int DownloadInstance::PerformRequestCallback(void* ctxt, const char* url)
+{
+ DownloadInstance* instance = (DownloadInstance*)ctxt;
+ return instance->PerformRequest(url);
+}
+
+
+string DownloadInstance::GetError() const
+{
+ char* str = BNGetErrorForDownloadInstance(m_object);
+ string result = str;
+ BNFreeString(str);
+ return result;
+}
+
+
+void DownloadInstance::SetError(const string& error)
+{
+ BNSetErrorForDownloadInstance(m_object, error.c_str());
+}
+
+
+int DownloadInstance::PerformRequest(const string& url, BNDownloadInstanceOutputCallbacks* callbacks)
+{
+ return BNPerformDownloadRequest(m_object, url.c_str(), callbacks);
+}
+
+
+void DownloadInstance::DestroyInstance()
+{
+}
+
+
+CoreDownloadInstance::CoreDownloadInstance(BNDownloadInstance* instance): DownloadInstance(instance)
+{
+}
+
+
+int CoreDownloadInstance::PerformRequest(const std::string& url)
+{
+ (void)url;
+ return -1;
+}
+
+
+DownloadProvider::DownloadProvider(const string& name): m_nameForRegister(name)
+{
+}
+
+
+DownloadProvider::DownloadProvider(BNDownloadProvider* provider)
+{
+ m_object = provider;
+}
+
+
+BNDownloadInstance* DownloadProvider::CreateInstanceCallback(void* ctxt)
+{
+ DownloadProvider* provider = (DownloadProvider*)ctxt;
+ Ref<DownloadInstance> instance = provider->CreateNewInstance();
+ return instance ? BNNewDownloadInstanceReference(instance->GetObject()) : nullptr;
+}
+
+
+vector<Ref<DownloadProvider>> DownloadProvider::GetList()
+{
+ size_t count;
+ BNDownloadProvider** list = BNGetDownloadProviderList(&count);
+ vector<Ref<DownloadProvider>> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new CoreDownloadProvider(list[i]));
+ BNFreeDownloadProviderList(list);
+ return result;
+}
+
+
+Ref<DownloadProvider> DownloadProvider::GetByName(const string& name)
+{
+ BNDownloadProvider* result = BNGetDownloadProviderByName(name.c_str());
+ if (!result)
+ return nullptr;
+ return new CoreDownloadProvider(result);
+}
+
+
+void DownloadProvider::Register(DownloadProvider* provider)
+{
+ BNDownloadProviderCallbacks cb;
+ cb.context = provider;
+ cb.createInstance = CreateInstanceCallback;
+ provider->m_object = BNRegisterDownloadProvider(provider->m_nameForRegister.c_str(), &cb);
+}
+
+
+CoreDownloadProvider::CoreDownloadProvider(BNDownloadProvider* provider): DownloadProvider(provider)
+{
+}
+
+
+Ref<DownloadInstance> CoreDownloadProvider::CreateNewInstance()
+{
+ BNDownloadInstance* result = BNCreateDownloadProviderInstance(m_object);
+ if (!result)
+ return nullptr;
+ return new CoreDownloadInstance(result);
+}
diff --git a/python/__init__.py b/python/__init__.py
index 729e4f8a..fda5f297 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -50,6 +50,7 @@ from .lineardisassembly import *
from .undoaction import *
from .highlight import *
from .scriptingprovider import *
+from .downloadprovider import *
from .pluginmanager import *
from .setting import *
from .metadata import *
diff --git a/python/downloadprovider.py b/python/downloadprovider.py
new file mode 100644
index 00000000..4756fd90
--- /dev/null
+++ b/python/downloadprovider.py
@@ -0,0 +1,210 @@
+# Copyright (c) 2015-2018 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 abc
+import code
+import ctypes
+import sys
+import traceback
+
+try:
+ from urllib.parse import urlparse, urlencode
+ from urllib.request import urlopen, Request, build_opener, install_opener, ProxyHandler
+ from urllib.error import HTTPError, URLError
+except ImportError:
+ from urlparse import urlparse
+ from urllib import urlencode
+ from urllib2 import urlopen, Request, build_opener, install_opener, ProxyHandler, HTTPError, URLError
+
+# Binary Ninja Components
+import _binaryninjacore as core
+from binaryninja.setting import Setting
+import startup
+import log
+
+
+class DownloadInstance(object):
+ def __init__(self, provider, handle = None):
+ if handle is None:
+ self._cb = core.BNDownloadInstanceCallbacks()
+ self._cb.context = 0
+ self._cb.destroyInstance = self._cb.destroyInstance.__class__(self._destroy_instance)
+ self._cb.performRequest = self._cb.performRequest.__class__(self._perform_request)
+ self.handle = core.BNInitDownloadInstance(provider.handle, self._cb)
+ else:
+ self.handle = core.handle_of_type(handle, core.BNDownloadInstance)
+ self._outputCallbacks = None
+
+ def __del__(self):
+ core.BNFreeDownloadInstance(self.handle)
+
+ def _destroy_instance(self, ctxt):
+ try:
+ self.perform_destroy_instance()
+ except:
+ log.log_error(traceback.format_exc())
+
+ def _perform_request(self, ctxt, url):
+ try:
+ return self.perform_request(ctxt, url)
+ except:
+ log.log_error(traceback.format_exc())
+ return -1
+
+ @abc.abstractmethod
+ def perform_destroy_instance(self):
+ raise NotImplementedError
+
+ @abc.abstractmethod
+ 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
+ def list(self):
+ """List all DownloadProvider types (read-only)"""
+ startup._init_plugins()
+ count = ctypes.c_ulonglong()
+ types = core.BNGetDownloadProviderList(count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(DownloadProvider(types[i]))
+ core.BNFreeDownloadProviderList(types)
+ return result
+
+ def __iter__(self):
+ startup._init_plugins()
+ count = ctypes.c_ulonglong()
+ types = core.BNGetDownloadProviderList(count)
+ try:
+ for i in xrange(0, count.value):
+ yield DownloadProvider(types[i])
+ finally:
+ core.BNFreeDownloadProviderList(types)
+
+ def __getitem__(self, value):
+ startup._init_plugins()
+ provider = core.BNGetDownloadProviderByName(str(value))
+ if provider is None:
+ raise KeyError("'%s' is not a valid download provider" % str(value))
+ return DownloadProvider(provider)
+
+ def __setattr__(self, name, value):
+ try:
+ type.__setattr__(self, name, value)
+ except AttributeError:
+ raise AttributeError("attribute '%s' is read only" % name)
+
+
+class DownloadProvider(object):
+ __metaclass__ = _DownloadProviderMetaclass
+ name = None
+ instance_class = None
+ _registered_providers = []
+
+ def __init__(self, handle = None):
+ if handle is not None:
+ self.handle = core.handle_of_type(handle, core.BNDownloadProvider)
+ self.__dict__["name"] = core.BNGetDownloadProviderName(handle)
+
+ def register(self):
+ self._cb = core.BNDownloadProviderCallbacks()
+ self._cb.context = 0
+ self._cb.createInstance = self._cb.createInstance.__class__(self._create_instance)
+ self.handle = core.BNRegisterDownloadProvider(self.__class__.name, self._cb)
+ self.__class__._registered_providers.append(self)
+
+ def _create_instance(self, ctxt):
+ try:
+ result = self.__class__.instance_class(self)
+ if result is None:
+ return None
+ return ctypes.cast(core.BNNewDownloadInstanceReference(result.handle), ctypes.c_void_p).value
+ except:
+ log.log_error(traceback.format_exc())
+ return None
+
+ def create_instance(self):
+ result = core.BNCreateDownloadProviderInstance(self.handle)
+ if result is None:
+ return None
+ return DownloadInstance(self, handle = result)
+
+
+class PythonDownloadInstance(DownloadInstance):
+ def __init__(self, provider):
+ super(PythonDownloadInstance, self).__init__(provider)
+
+ @abc.abstractmethod
+ def perform_destroy_instance(self):
+ pass
+
+ @abc.abstractmethod
+ def perform_request(self, ctxt, url):
+ try:
+ proxy_setting = Setting('download-client').get_string('https-proxy')
+ if proxy_setting:
+ opener = build_opener(ProxyHandler({'https': proxy_setting}))
+ install_opener(opener)
+
+ r = urlopen(url)
+ total_size = int(r.headers.get('content-length', 0))
+ bytes_sent = 0
+ while True:
+ data = r.read(4096)
+ if not data:
+ break
+ raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data)
+ bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes))
+ if bytes_wrote != len(raw_bytes):
+ core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!")
+ return -1
+ bytes_sent = bytes_sent + bytes_wrote
+ continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size)
+ if continue_download is False:
+ core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!")
+ return -1
+
+ if not bytes_sent:
+ core.BNSetErrorForDownloadInstance(self.handle, "Received no data!")
+ return -1
+
+ except URLError as e:
+ core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__)
+ return -1
+ except:
+ core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!")
+ log.log_error(traceback.format_exc())
+ return -1
+
+ return 0
+
+
+class PythonDownloadProvider(DownloadProvider):
+ name = "DefaultDownloadProvider"
+ instance_class = PythonDownloadInstance
+
+
+PythonDownloadProvider().register()
diff --git a/python/pluginmanager.py b/python/pluginmanager.py
index 2f293577..0cc43aca 100644
--- a/python/pluginmanager.py
+++ b/python/pluginmanager.py
@@ -32,6 +32,7 @@ class RepoPlugin(object):
created by parsing the plugins.json in a plugin repository.
"""
def __init__(self, handle):
+ raise Exception("RepoPlugin temporarily disabled!")
self.handle = core.handle_of_type(handle, core.BNRepoPlugin)
def __del__(self):
@@ -136,6 +137,7 @@ 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):
@@ -199,6 +201,7 @@ class RepositoryManager(object):
the plugins that are installed/unstalled enabled/disabled
"""
def __init__(self, handle=None):
+ raise Exception("RepositoryManager temporarily disabled!")
self.handle = core.BNGetRepositoryManager()
def __getitem__(self, repo_path):