summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h42
-rw-r--r--binaryninjacore.h6
-rw-r--r--python/settings.py40
-rw-r--r--settings.cpp43
-rw-r--r--ui/settingsview.h4
5 files changed, 115 insertions, 20 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 99eb1344..485a01d6 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -14727,26 +14727,26 @@ namespace BinaryNinja {
\c RegisterGroup method allows for specifying a UI friendly title for use in the Binary Ninja UI. Defining a new setting requires a
unique setting key and a JSON string of property, value pairs. The following table describes the available properties and values.
- ================== ====================================== ================== ======== =======================================================================
- Property JSON Data Type Prerequisite Optional {Allowed Values} and Notes
- ================== ====================================== ================== ======== =======================================================================
- "title" string None No Concise Setting Title
- "type" string None No {"array", "boolean", "number", "password", "string"}
- "elementType" string "type" is "array" No {"string"}
- "enum" array : {string} "type" is "array" Yes Enumeration definitions
- "enumDescriptions" array : {string} "type" is "array" Yes Enumeration descriptions that match "enum" array
- "minValue" number "type" is "number" Yes Specify 0 to infer unsigned (default is signed)
- "maxValue" number "type" is "number" Yes Values less than or equal to INT_MAX result in a QSpinBox UI element
- "precision" number "type" is "number" Yes Specify precision for a QDoubleSpinBox
- "default" {array, boolean, number, string, null} None Yes Specify optimal default value
- "aliases" array : {string} None Yes Array of deprecated setting key(s)
- "description" string None No Detailed setting description
- "ignore" array : {string} None Yes {"SettingsUserScope", "SettingsProjectScope", "SettingsResourceScope"}
- "message" string None Yes An optional message with additional emphasis
- "readOnly" bool None Yes Only enforced by UI elements
- "optional" bool None Yes Indicates setting can be null
- "requiresRestart bool None Yes Enable restart notification in the UI upon change
- ================== ====================================== ================== ======== =======================================================================
+ ================== ====================================== ====================================== ======== =======================================================================
+ Property JSON Data Type Prerequisite Optional {Allowed Values} and Notes
+ ================== ====================================== ====================================== ======== =======================================================================
+ "title" string None No Concise Setting Title
+ "type" string None No {"array", "boolean", "number", "object", "password", "string"}
+ "elementType" string "type" is "array" or type is "object" No {"string"}
+ "enum" array : {string} "type" is "array" Yes Enumeration definitions
+ "enumDescriptions" array : {string} "type" is "array" Yes Enumeration descriptions that match "enum" array
+ "minValue" number "type" is "number" Yes Specify 0 to infer unsigned (default is signed)
+ "maxValue" number "type" is "number" Yes Values less than or equal to INT_MAX result in a QSpinBox UI element
+ "precision" number "type" is "number" Yes Specify precision for a QDoubleSpinBox
+ "default" {array, boolean, number, string, null} None Yes Specify optimal default value
+ "aliases" array : {string} None Yes Array of deprecated setting key(s)
+ "description" string None No Detailed setting description
+ "ignore" array : {string} None Yes {"SettingsUserScope", "SettingsProjectScope", "SettingsResourceScope"}
+ "message" string None Yes An optional message with additional emphasis
+ "readOnly" bool None Yes Only enforced by UI elements
+ "optional" bool None Yes Indicates setting can be null
+ "requiresRestart bool None Yes Enable restart notification in the UI upon change
+ ================== ====================================== ====================================== ======== =======================================================================
\note In order to facilitate deterministic analysis results, settings from the <em><tt>default</tt></em> schema that impact analysis are serialized
from Default, User, and Project scope into Resource scope during initial BinaryView analysis. This allows an analysis database to be opened
@@ -14924,6 +14924,8 @@ namespace BinaryNinja {
BNSettingsScope scope = SettingsAutoScope);
bool Set(const std::string& key, const std::vector<std::string>& value, Ref<BinaryView> view = nullptr,
BNSettingsScope scope = SettingsAutoScope);
+ bool Set(const std::string& key, const std::map<std::string, std::string>& value, Ref<BinaryView> view = nullptr,
+ BNSettingsScope scope = SettingsAutoScope);
bool SetJson(const std::string& key, const std::string& value, Ref<BinaryView> view = nullptr,
BNSettingsScope scope = SettingsAutoScope);
};
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 995f2f4f..30e34b81 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -3021,6 +3021,7 @@ extern "C"
BINARYNINJACOREAPI void BNFreeString(char* str);
BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size);
BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count);
+ BINARYNINJACOREAPI void BNFreeStringObject(char*** obj, size_t count);
BINARYNINJACOREAPI void BNShutdown(void);
BINARYNINJACOREAPI bool BNIsShutdownRequested(void);
@@ -6370,6 +6371,9 @@ extern "C"
BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope);
BINARYNINJACOREAPI const char** BNSettingsGetStringList(
BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope, size_t* inoutSize);
+ BINARYNINJACOREAPI const char*** BNSettingsGetStringObject(BNSettings* settings,
+ const char* key, BNBinaryView* view, BNSettingsScope* scope, size_t* entryCount);
+
BINARYNINJACOREAPI char* BNSettingsGetJson(
BNSettings* settings, const char* key, BNBinaryView* view, BNSettingsScope* scope);
@@ -6385,6 +6389,8 @@ extern "C"
BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, const char* value);
BINARYNINJACOREAPI bool BNSettingsSetStringList(BNSettings* settings, BNBinaryView* view, BNSettingsScope scope,
const char* key, const char** value, size_t size);
+ BINARYNINJACOREAPI bool BNSettingsSetStringObject(BNSettings* settings, BNBinaryView* view, BNSettingsScope scope,
+ const char* key, const char*** value, size_t size);
BINARYNINJACOREAPI bool BNSettingsSetJson(
BNSettings* settings, BNBinaryView* view, BNSettingsScope scope, const char* key, const char* value);
diff --git a/python/settings.py b/python/settings.py
index fee8a755..f7bee686 100644
--- a/python/settings.py
+++ b/python/settings.py
@@ -20,6 +20,8 @@
import ctypes
+from typing import Dict
+
# Binary Ninja components
from . import _binaryninjacore as core
from .enums import SettingsScope
@@ -333,6 +335,18 @@ class Settings:
core.BNFreeStringList(result, length)
return out_list
+ def get_string_object(self, key, view=None):
+ if view is not None:
+ view = view.handle
+ length = ctypes.c_ulonglong()
+ result = core.BNSettingsGetStringObject(self.handle, key, view, None, ctypes.byref(length))
+ assert result is not None, "core.BNSettingsGetStringObject returned None"
+ out_dict = {}
+ for i in range(length.value):
+ out_dict[result[i][0].decode('utf8')] = (result[i][1].decode('utf8'))
+ core.BNFreeStringObject(result, length)
+ return out_dict
+
def get_json(self, key, view=None):
if view is not None:
view = view.handle
@@ -379,6 +393,19 @@ class Settings:
core.BNFreeStringList(result, length)
return (out_list, SettingsScope(c_scope.value))
+ def get_string_object_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope):
+ if view is not None:
+ view = view.handle
+ c_scope = core.SettingsScopeEnum(scope)
+ length = ctypes.c_ulonglong()
+ result = core.BNSettingsGetStringObject(self.handle, key, view, ctypes.byref(c_scope), ctypes.byref(length))
+ assert result is not None, "core.BNSettingsGetStringObject returned None"
+ out_dict = {}
+ for i in range(length.value):
+ out_dict[result[i][0].decode('utf8')] = (result[i][1].decode('utf8'))
+ core.BNFreeStringObject(result, length)
+ return (out_dict, SettingsScope(c_scope.value))
+
def get_json_with_scope(self, key, view=None, scope=SettingsScope.SettingsAutoScope):
if view is not None:
view = view.handle
@@ -416,6 +443,19 @@ class Settings:
string_list[i] = value[i].encode('charmap')
return core.BNSettingsSetStringList(self.handle, view, scope, key, string_list, length)
+ def set_string_object(self, key, value: Dict[str, str], view=None, scope=SettingsScope.SettingsAutoScope):
+ if view is not None:
+ view = view.handle
+ length = ctypes.c_ulonglong()
+ length.value = len(value)
+ entry_val = (ctypes.c_char_p * 2)
+ string_obj = (ctypes.POINTER(ctypes.c_char_p) * len(value))()
+ for i,entry in enumerate(value.items()):
+ string_obj[i] = entry_val()
+ string_obj[i][0] = entry[0].encode('charmap')
+ string_obj[i][1] = entry[1].encode('charmap')
+ return core.BNSettingsSetStringObject(self.handle, view, scope, key, string_obj, length)
+
def set_json(self, key, value, view=None, scope=SettingsScope.SettingsAutoScope):
if view is not None:
view = view.handle
diff --git a/settings.cpp b/settings.cpp
index 59394c42..6066aa1e 100644
--- a/settings.cpp
+++ b/settings.cpp
@@ -259,6 +259,26 @@ vector<string> Settings::Get<vector<string>>(const string& key, Ref<BinaryView>
}
+template <>
+map<string, string> Settings::Get<map<string, string>>(const string& key, Ref<BinaryView> view, BNSettingsScope* scope)
+{
+ // [[key, val], ...]
+ size_t size = 0;
+ char*** outBuffer =
+ (char***)BNSettingsGetStringObject(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope, &size);
+
+ map<string, string> result;
+ for (size_t i = 0; i < size; i++)
+ {
+ char** entry = outBuffer[i];
+ result[entry[0]] = entry[1];
+ }
+
+ BNFreeStringObject(outBuffer, size);
+ return result;
+}
+
+
string Settings::GetJson(const string& key, Ref<BinaryView> view, BNSettingsScope* scope)
{
char* tmpStr = BNSettingsGetJson(m_object, key.c_str(), view ? view->GetObject() : nullptr, scope);
@@ -329,6 +349,29 @@ bool Settings::Set(const string& key, const vector<string>& value, Ref<BinaryVie
}
+bool Settings::Set(const string& key, const map<string, string>& value, Ref<BinaryView> view, BNSettingsScope scope)
+{
+ char*** buffer = new char**[value.size()];
+ if (!buffer)
+ return false;
+
+ size_t i = 0;
+ for (const auto& entry : value)
+ {
+ buffer[i] = new char*[2];
+ buffer[i][0] = BNAllocString(entry.first.c_str());
+ buffer[i][1] = BNAllocString(entry.second.c_str());
+ i++;
+ }
+
+ bool result = BNSettingsSetStringObject(
+ m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), (const char***)buffer, value.size());
+
+ BNFreeStringObject(buffer, value.size());
+ return result;
+}
+
+
bool Settings::SetJson(const string& key, const string& value, Ref<BinaryView> view, BNSettingsScope scope)
{
return BNSettingsSetJson(m_object, view ? view->GetObject() : nullptr, scope, key.c_str(), value.c_str());
diff --git a/ui/settingsview.h b/ui/settingsview.h
index df6e19cb..a810af9e 100644
--- a/ui/settingsview.h
+++ b/ui/settingsview.h
@@ -14,8 +14,10 @@
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QTableWidget>
#include <QtWidgets/QTreeView>
#include <map>
@@ -160,6 +162,7 @@ class BINARYNINJAUIAPI SettingsEditor : public QWidget
QSpinBox* m_spinBox = nullptr;
QComboBox* m_comboBox = nullptr;
QLineEdit* m_arrayText = nullptr;
+ QTableWidget* m_objectTable = nullptr;
std::set<QString> m_validComboSelections;
Json::StreamWriterBuilder m_builder;
@@ -198,6 +201,7 @@ class BINARYNINJAUIAPI SettingsEditor : public QWidget
void updateDoubleNumberSetting(double value);
void updateIntNumberSetting(int value);
void updateArraySetting();
+ void updateObjectSetting();
void addArrayStringSetting(const QString& text);
void resetSetting();
void resetAllSettings(BNSettingsScope scope);