summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h17
-rw-r--r--binaryninjacore.h8
-rw-r--r--interaction.cpp25
-rw-r--r--python/interaction.py41
-rw-r--r--ui/metadatachoicedialog.h20
5 files changed, 97 insertions, 14 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 7f7fca60..7a4efee4 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1517,7 +1517,18 @@ namespace BinaryNinja {
\return Whether a choice was successfully picked
*/
bool GetChoiceInput(
- size_t& idx, const std::string& prompt, const std::string& title, const std::vector<std::string>& choices);
+ size_t& idx, const std::string& prompt, const std::string& title, const std::vector<std::string>& choices);
+
+ /*! Prompts the user to select the one of the provided choices out of a large list, with the option to filter choices
+
+ \ingroup interaction
+ \param[out] idx Reference to the size_t the resulting index selected will be copied to
+ \param[in] title Title for the input popup / prompt for headless
+ \param[in] prompt Prompt for the input (shown on the 'Select' button in UI)
+ \param[in] choices List of string choices for the user to select from
+ \return Whether a choice was successfully picked
+ */
+ bool GetLargeChoiceInput(size_t& idx, const std::string& title, const std::string& prompt, const std::vector<std::string>& choices);
/*! Prompts the user for a file name to open
@@ -14527,7 +14538,9 @@ namespace BinaryNinja {
virtual bool GetAddressInput(uint64_t& result, const std::string& prompt, const std::string& title,
Ref<BinaryView> view, uint64_t currentAddr);
virtual bool GetChoiceInput(size_t& idx, const std::string& prompt, const std::string& title,
- const std::vector<std::string>& choices) = 0;
+ const std::vector<std::string>& choices) = 0;
+ virtual bool GetLargeChoiceInput(size_t& idx, const std::string& prompt, const std::string& title,
+ const std::vector<std::string>& choices) = 0;
virtual bool GetOpenFileNameInput(std::string& result, const std::string& prompt, const std::string& ext = "");
virtual bool GetSaveFileNameInput(std::string& result, const std::string& prompt, const std::string& ext = "",
const std::string& defaultName = "");
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 0461a16c..a92c7a09 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -2733,7 +2733,9 @@ extern "C"
bool (*getAddressInput)(void* ctxt, uint64_t* result, const char* prompt, const char* title, BNBinaryView* view,
uint64_t currentAddr);
bool (*getChoiceInput)(
- void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
+ void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
+ bool (*getLargeChoiceInput)(
+ void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
bool (*getOpenFileNameInput)(void* ctxt, char** result, const char* prompt, const char* ext);
bool (*getSaveFileNameInput)(
void* ctxt, char** result, const char* prompt, const char* ext, const char* defaultName);
@@ -6073,7 +6075,9 @@ extern "C"
BINARYNINJACOREAPI bool BNGetAddressInput(
uint64_t* result, const char* prompt, const char* title, BNBinaryView* view, uint64_t currentAddr);
BINARYNINJACOREAPI bool BNGetChoiceInput(
- size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
+ size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
+ BINARYNINJACOREAPI bool BNGetLargeChoiceInput(
+ size_t* result, const char* prompt, const char* title, const char** choices, size_t count);
BINARYNINJACOREAPI bool BNGetOpenFileNameInput(char** result, const char* prompt, const char* ext);
BINARYNINJACOREAPI bool BNGetSaveFileNameInput(
char** result, const char* prompt, const char* ext, const char* defaultName);
diff --git a/interaction.cpp b/interaction.cpp
index 7bc1d2fa..037edca6 100644
--- a/interaction.cpp
+++ b/interaction.cpp
@@ -255,7 +255,7 @@ static bool GetAddressInputCallback(
static bool GetChoiceInputCallback(
- void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count)
+ void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count)
{
InteractionHandler* handler = (InteractionHandler*)ctxt;
vector<string> choiceStrs;
@@ -265,6 +265,17 @@ static bool GetChoiceInputCallback(
}
+static bool GetLargeChoiceInputCallback(
+ void* ctxt, size_t* result, const char* prompt, const char* title, const char** choices, size_t count)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ vector<string> choiceStrs;
+ for (size_t i = 0; i < count; i++)
+ choiceStrs.push_back(choices[i]);
+ return handler->GetLargeChoiceInput(*result, prompt,title, choiceStrs);
+}
+
+
static bool GetOpenFileNameInputCallback(void* ctxt, char** result, const char* prompt, const char* ext)
{
InteractionHandler* handler = (InteractionHandler*)ctxt;
@@ -445,6 +456,7 @@ void BinaryNinja::RegisterInteractionHandler(InteractionHandler* handler)
cb.getIntegerInput = GetIntegerInputCallback;
cb.getAddressInput = GetAddressInputCallback;
cb.getChoiceInput = GetChoiceInputCallback;
+ cb.getLargeChoiceInput = GetLargeChoiceInputCallback;
cb.getOpenFileNameInput = GetOpenFileNameInputCallback;
cb.getSaveFileNameInput = GetSaveFileNameInputCallback;
cb.getDirectoryNameInput = GetDirectoryNameInputCallback;
@@ -533,6 +545,17 @@ bool BinaryNinja::GetChoiceInput(size_t& idx, const string& prompt, const string
}
+bool BinaryNinja::GetLargeChoiceInput(size_t& idx, const string& prompt, const string& title, const vector<string>& choices)
+{
+ const char** choiceStrs = new const char*[choices.size()];
+ for (size_t i = 0; i < choices.size(); i++)
+ choiceStrs[i] = choices[i].c_str();
+ bool ok = BNGetLargeChoiceInput(&idx, prompt.c_str(), title.c_str(), choiceStrs, choices.size());
+ delete[] choiceStrs;
+ return ok;
+}
+
+
bool BinaryNinja::GetOpenFileNameInput(string& result, const string& prompt, const string& ext)
{
char* value = nullptr;
diff --git a/python/interaction.py b/python/interaction.py
index 123a095f..56d9a6fb 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -492,6 +492,7 @@ class InteractionHandler:
self._cb.getIntegerInput = self._cb.getIntegerInput.__class__(self._get_int_input)
self._cb.getAddressInput = self._cb.getAddressInput.__class__(self._get_address_input)
self._cb.getChoiceInput = self._cb.getChoiceInput.__class__(self._get_choice_input)
+ self._cb.getLargeChoiceInput = self._cb.getLargeChoiceInput.__class__(self._get_large_choice_input)
self._cb.getOpenFileNameInput = self._cb.getOpenFileNameInput.__class__(self._get_open_filename_input)
self._cb.getSaveFileNameInput = self._cb.getSaveFileNameInput.__class__(self._get_save_filename_input)
self._cb.getDirectoryNameInput = self._cb.getDirectoryNameInput.__class__(self._get_directory_name_input)
@@ -597,6 +598,19 @@ class InteractionHandler:
except:
log_error(traceback.format_exc())
+ def _get_large_choice_input(self, ctxt, result, prompt, title, choice_buf, count):
+ try:
+ choices = []
+ for i in range(0, count):
+ choices.append(choice_buf[i])
+ value = self.get_large_choice_input(prompt, title, choices)
+ if value is None:
+ return False
+ result[0] = value
+ return True
+ except:
+ log_error(traceback.format_exc())
+
def _get_open_filename_input(self, ctxt, result, prompt, ext):
try:
value = self.get_open_filename_input(prompt, ext)
@@ -760,6 +774,9 @@ class InteractionHandler:
def get_choice_input(self, prompt, title, choices):
return NotImplemented
+ def get_large_choice_input(self, prompt, title, choices):
+ return NotImplemented
+
def get_open_filename_input(self, prompt, ext):
return get_text_line_input(prompt, "Open File")
@@ -1215,6 +1232,30 @@ def get_choice_input(prompt, title, choices):
return value.value
+def get_large_choice_input(prompt, title, choices):
+ """
+ ``get_large_choice_input`` prompts the user to select the one of the provided choices from a large pool
+
+ .. note:: This API function differently on the command-line vs the UI. In the UI a pop-up is used. On the command-line \
+ a text prompt is used. The UI uses a filterable list of entries
+
+ :param str prompt: Text for the button when executed in the UI. Prompt shown for selection headless.
+ :param str title: Title of the window when executed in the UI.
+ :param choices: A list of strings for the user to choose from.
+ :type choices: list(str)
+ :rtype: integer array index of the selected option
+ :Example:
+ >>> get_large_choice_input("Select Function", "Select a Function", [f.symbol.short_name for f in bv.functions])
+ """
+ choice_buf = (ctypes.c_char_p * len(choices))()
+ for i in range(0, len(choices)):
+ choice_buf[i] = str(choices[i]).encode('charmap')
+ value = ctypes.c_ulonglong()
+ if not core.BNGetLargeChoiceInput(value, prompt, title, choice_buf, len(choices)):
+ return None
+ return value.value
+
+
def get_open_filename_input(prompt: str, ext: str = "") -> Optional[str]:
"""
``get_open_filename_input`` prompts the user for a file name to open
diff --git a/ui/metadatachoicedialog.h b/ui/metadatachoicedialog.h
index ed25f3e1..b34dccdc 100644
--- a/ui/metadatachoicedialog.h
+++ b/ui/metadatachoicedialog.h
@@ -43,7 +43,7 @@ public:
};
// Model that is blind and queries info from its delegate.
-class ManagedTableModel : public QAbstractTableModel
+class BINARYNINJAUIAPI ManagedTableModel : public QAbstractTableModel
{
ManagedTableDelegate* m_delegate;
@@ -228,8 +228,6 @@ class BINARYNINJAUIAPI MetadataChoiceDialog : public QDialog, public ManagedTabl
protected:
std::vector<EntryItem> m_entries;
-
-
QHBoxLayout* m_midRowLayout;
// ManagedTableDelegate
@@ -297,11 +295,12 @@ protected:
QPushButton* m_choose;
bool ExtraFilterEnabled() { return m_extraFilter.exists && m_extraFilter.enabled; };
-
+public:
void AddWidthRequiredByItem(void* item, size_t widthRequired);
void RemoveWidthRequiredByItem(QWidget* item);
void AddHeightRequiredByItem(void* item, size_t widthRequired);
void RemoveHeightRequiredByItem(QWidget* item);
+protected:
void UpdateMinimumSpace();
std::optional<EntryItem> m_chosenEntry;
@@ -328,10 +327,11 @@ public:
\param parent Parent Widget
\param title Title of the dialog
+ \param prompt Text of the button to select a choice
\param entries List of entries
\param metadata Map of indices to the metadata for those entries.
*/
- MetadataChoiceDialog(QWidget* parent, const QString& title, const QStringList& entries,
+ MetadataChoiceDialog(QWidget* parent, const QString& title, const QString& prompt, const QStringList& entries,
std::unordered_map<size_t, QString> metadata);
/*! Create a choice selection dialog with a Title, list of entries, and pre-built set of metadata for those entries.
@@ -343,10 +343,11 @@ public:
\param parent Parent Widget
\param title Title of the dialog
+ \param prompt Text of the button to select a choice
\param entries List of entries
\param metadata Map of indices to the metadata (as InstructionTextTokens) for those entries.
*/
- MetadataChoiceDialog(QWidget* parent, const QString& title, const QStringList& entries,
+ MetadataChoiceDialog(QWidget* parent, const QString& title, const QString& prompt, const QStringList& entries,
std::unordered_map<size_t, std::vector<BinaryNinja::DisassemblyTextLine>> metadata);
/*! Create a choice selection dialog with a Title and list of entries.
@@ -355,12 +356,13 @@ public:
\param parent Parent Widget
\param title Title of the dialog
+ \param prompt Text of the button to select a choice
\param entries List of entries
*/
- MetadataChoiceDialog(QWidget* parent, const QString& title, const QStringList& entries);
+ MetadataChoiceDialog(QWidget* parent, const QString& title, const QString& prompt, const QStringList& entries);
- MetadataChoiceDialog(QWidget* parent, const QString& title) :
- MetadataChoiceDialog(parent, title, {}) {}
+ MetadataChoiceDialog(QWidget* parent, const QString& title, const QString& prompt = "Select") :
+ MetadataChoiceDialog(parent, title, prompt, {}) {}
/*! Set the callback the dialog will execute to retrieve metadata for a given item.