diff options
| -rw-r--r-- | binaryninjaapi.h | 42 | ||||
| -rw-r--r-- | binaryninjacore.h | 6 | ||||
| -rw-r--r-- | python/settings.py | 40 | ||||
| -rw-r--r-- | settings.cpp | 43 | ||||
| -rw-r--r-- | ui/settingsview.h | 4 |
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); |
