summaryrefslogtreecommitdiff
path: root/interaction.cpp
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2016-10-10 18:24:38 -0400
committerRusty Wagner <rusty@vector35.com>2016-10-10 18:24:38 -0400
commit98d187d9d86506ea915731266b8faaaa2dc0c9d6 (patch)
treefa1ee82d342c12ed5d42e7caf9397312edf7cf63 /interaction.cpp
parent4598adb7ae961e69fb6ed3e594c0244c49eef511 (diff)
parent55ac7a184b7956c0c2e2ca41d512e7c4a81267d9 (diff)
Merge commit '55ac7a184b7956c0c2e2ca41d512e7c4a81267d9'
Diffstat (limited to 'interaction.cpp')
-rw-r--r--interaction.cpp557
1 files changed, 557 insertions, 0 deletions
diff --git a/interaction.cpp b/interaction.cpp
new file mode 100644
index 00000000..fb4eb6d4
--- /dev/null
+++ b/interaction.cpp
@@ -0,0 +1,557 @@
+#include <stdlib.h>
+#include <string.h>
+#include "binaryninjaapi.h"
+
+using namespace std;
+using namespace BinaryNinja;
+
+
+FormInputField FormInputField::Label(const string& text)
+{
+ FormInputField result;
+ result.type = LabelFormField;
+ result.prompt = text;
+ return result;
+}
+
+
+FormInputField FormInputField::Separator()
+{
+ FormInputField result;
+ result.type = SeparatorFormField;
+ return result;
+}
+
+
+FormInputField FormInputField::TextLine(const string& prompt)
+{
+ FormInputField result;
+ result.type = TextLineFormField;
+ result.prompt = prompt;
+ return result;
+}
+
+
+FormInputField FormInputField::MultilineText(const string& prompt)
+{
+ FormInputField result;
+ result.type = MultilineTextFormField;
+ result.prompt = prompt;
+ return result;
+}
+
+
+FormInputField FormInputField::Integer(const string& prompt)
+{
+ FormInputField result;
+ result.type = IntegerFormField;
+ result.prompt = prompt;
+ return result;
+}
+
+
+FormInputField FormInputField::Address(const std::string& prompt, BinaryView* view, uint64_t currentAddress)
+{
+ FormInputField result;
+ result.type = AddressFormField;
+ result.prompt = prompt;
+ result.view = view;
+ result.currentAddress = currentAddress;
+ return result;
+}
+
+
+FormInputField FormInputField::Choice(const string& prompt, const vector<string>& choices)
+{
+ FormInputField result;
+ result.type = ChoiceFormField;
+ result.prompt = prompt;
+ result.choices = choices;
+ return result;
+}
+
+
+FormInputField FormInputField::OpenFileName(const string& prompt, const string& ext)
+{
+ FormInputField result;
+ result.type = OpenFileNameFormField;
+ result.prompt = prompt;
+ result.ext = ext;
+ return result;
+}
+
+
+FormInputField FormInputField::SaveFileName(const string& prompt, const string& ext, const string& defaultName)
+{
+ FormInputField result;
+ result.type = SaveFileNameFormField;
+ result.prompt = prompt;
+ result.ext = ext;
+ result.defaultName = defaultName;
+ return result;
+}
+
+
+FormInputField FormInputField::DirectoryName(const string& prompt, const string& defaultName)
+{
+ FormInputField result;
+ result.type = DirectoryNameFormField;
+ result.prompt = prompt;
+ result.defaultName = defaultName;
+ return result;
+}
+
+
+void InteractionHandler::ShowMarkdownReport(Ref<BinaryView> view, const string& title, const string& contents,
+ const string& plainText)
+{
+ ShowHTMLReport(view, title, MarkdownToHTML(contents), plainText);
+}
+
+
+void InteractionHandler::ShowHTMLReport(Ref<BinaryView> view, const string& title, const string&,
+ const string& plainText)
+{
+ if (plainText.size() != 0)
+ ShowPlainTextReport(view, title, plainText);
+}
+
+
+bool InteractionHandler::GetIntegerInput(int64_t& result, const string& prompt, const string& title)
+{
+ string input;
+
+ while (true)
+ {
+ string input;
+ if (!GetTextLineInput(input, prompt, title))
+ return false;
+ if (input.size() == 0)
+ return false;
+
+ errno = 0;
+ result = strtoll(input.c_str(), nullptr, 0);
+ if (errno != 0)
+ {
+ errno = 0;
+ result = strtoull(input.c_str(), nullptr, 0);
+ if (errno != 0)
+ continue;
+ }
+
+ return true;
+ }
+}
+
+
+bool InteractionHandler::GetAddressInput(uint64_t& result, const string& prompt, const string& title,
+ Ref<BinaryView>, uint64_t)
+{
+ int64_t value;
+ if (!GetIntegerInput(value, prompt, title))
+ return false;
+ result = (uint64_t)value;
+ return true;
+}
+
+
+bool InteractionHandler::GetOpenFileNameInput(string& result, const string& prompt, const string&)
+{
+ return GetTextLineInput(result, prompt, "Open File");
+}
+
+
+bool InteractionHandler::GetSaveFileNameInput(string& result, const string& prompt, const string&, const string&)
+{
+ return GetTextLineInput(result, prompt, "Save File");
+}
+
+
+bool InteractionHandler::GetDirectoryNameInput(string& result, const string& prompt, const string&)
+{
+ return GetTextLineInput(result, prompt, "Select Directory");
+}
+
+
+static void ShowPlainTextReportCallback(void* ctxt, BNBinaryView* view, const char* title, const char* contents)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ handler->ShowPlainTextReport(view ? new BinaryView(BNNewViewReference(view)) : nullptr, title, contents);
+}
+
+
+static void ShowMarkdownReportCallback(void* ctxt, BNBinaryView* view, const char* title, const char* contents,
+ const char* plaintext)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ handler->ShowMarkdownReport(view ? new BinaryView(BNNewViewReference(view)) : nullptr, title, contents, plaintext);
+}
+
+
+static void ShowHTMLReportCallback(void* ctxt, BNBinaryView* view, const char* title, const char* contents,
+ const char* plaintext)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ handler->ShowHTMLReport(view ? new BinaryView(BNNewViewReference(view)) : nullptr, title, contents, plaintext);
+}
+
+
+static bool GetTextLineInputCallback(void* ctxt, char** result, const char* prompt, const char* title)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ string value;
+ if (!handler->GetTextLineInput(value, prompt, title))
+ return false;
+ *result = BNAllocString(value.c_str());
+ return true;
+}
+
+
+static bool GetIntegerInputCallback(void* ctxt, int64_t* result, const char* prompt, const char* title)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ return handler->GetIntegerInput(*result, prompt, title);
+}
+
+
+static bool GetAddressInputCallback(void* ctxt, uint64_t* result, const char* prompt, const char* title,
+ BNBinaryView* view, uint64_t currentAddr)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ return handler->GetAddressInput(*result, prompt, title, view ? new BinaryView(BNNewViewReference(view)) : nullptr,
+ currentAddr);
+}
+
+
+static bool GetChoiceInputCallback(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->GetChoiceInput(*result, prompt, title, choiceStrs);
+}
+
+
+static bool GetOpenFileNameInputCallback(void* ctxt, char** result, const char* prompt, const char* ext)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ string value;
+ if (!handler->GetOpenFileNameInput(value, prompt, ext))
+ return false;
+ *result = BNAllocString(value.c_str());
+ return true;
+}
+
+
+static bool GetSaveFileNameInputCallback(void* ctxt, char** result, const char* prompt, const char* ext,
+ const char* defaultName)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ string value;
+ if (!handler->GetSaveFileNameInput(value, prompt, ext, defaultName))
+ return false;
+ *result = BNAllocString(value.c_str());
+ return true;
+}
+
+
+static bool GetDirectoryNameInputCallback(void* ctxt, char** result, const char* prompt, const char* defaultName)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ string value;
+ if (!handler->GetDirectoryNameInput(value, prompt, defaultName))
+ return false;
+ *result = BNAllocString(value.c_str());
+ return true;
+}
+
+
+static bool GetFormInputCallback(void* ctxt, BNFormInputField* fieldBuf, size_t count, const char* title)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+
+ // Convert list of fields from core structure to API structure
+ vector<FormInputField> fields;
+ for (size_t i = 0; i < count; i++)
+ {
+ vector<string> choices;
+ switch (fieldBuf[i].type)
+ {
+ case SeparatorFormField:
+ fields.push_back(FormInputField::Separator());
+ break;
+ case TextLineFormField:
+ fields.push_back(FormInputField::TextLine(fieldBuf[i].prompt));
+ break;
+ case MultilineTextFormField:
+ fields.push_back(FormInputField::MultilineText(fieldBuf[i].prompt));
+ break;
+ case IntegerFormField:
+ fields.push_back(FormInputField::Integer(fieldBuf[i].prompt));
+ break;
+ case AddressFormField:
+ fields.push_back(FormInputField::Address(fieldBuf[i].prompt, fieldBuf[i].view ?
+ new BinaryView(BNNewViewReference(fieldBuf[i].view)) : nullptr, fieldBuf[i].currentAddress));
+ break;
+ case ChoiceFormField:
+ for (size_t j = 0; j < fieldBuf[i].count; j++)
+ choices.push_back(fieldBuf[i].choices[j]);
+ fields.push_back(FormInputField::Choice(fieldBuf[i].prompt, choices));
+ break;
+ case OpenFileNameFormField:
+ fields.push_back(FormInputField::OpenFileName(fieldBuf[i].prompt, fieldBuf[i].ext));
+ break;
+ case SaveFileNameFormField:
+ fields.push_back(FormInputField::SaveFileName(fieldBuf[i].prompt, fieldBuf[i].ext, fieldBuf[i].defaultName));
+ break;
+ case DirectoryNameFormField:
+ fields.push_back(FormInputField::DirectoryName(fieldBuf[i].prompt, fieldBuf[i].defaultName));
+ break;
+ default:
+ fields.push_back(FormInputField::Label(fieldBuf[i].prompt));
+ break;
+ }
+ }
+
+ if (!handler->GetFormInput(fields, title))
+ return false;
+
+ // Place results into core structure
+ for (size_t i = 0; i < count; i++)
+ {
+ switch (fieldBuf[i].type)
+ {
+ case TextLineFormField:
+ case MultilineTextFormField:
+ case OpenFileNameFormField:
+ case SaveFileNameFormField:
+ case DirectoryNameFormField:
+ fieldBuf[i].stringResult = BNAllocString(fields[i].stringResult.c_str());
+ break;
+ case IntegerFormField:
+ fieldBuf[i].intResult = fields[i].intResult;
+ break;
+ case AddressFormField:
+ fieldBuf[i].addressResult = fields[i].addressResult;
+ break;
+ case ChoiceFormField:
+ fieldBuf[i].indexResult = fields[i].indexResult;
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+
+static BNMessageBoxButtonResult ShowMessageBoxCallback(void* ctxt, const char* title, const char* text,
+ BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ return handler->ShowMessageBox(title, text, buttons, icon);
+}
+
+
+void BinaryNinja::RegisterInteractionHandler(InteractionHandler* handler)
+{
+ BNInteractionHandlerCallbacks cb;
+ cb.context = handler;
+ cb.showPlainTextReport = ShowPlainTextReportCallback;
+ cb.showMarkdownReport = ShowMarkdownReportCallback;
+ cb.showHTMLReport = ShowHTMLReportCallback;
+ cb.getTextLineInput = GetTextLineInputCallback;
+ cb.getIntegerInput = GetIntegerInputCallback;
+ cb.getAddressInput = GetAddressInputCallback;
+ cb.getChoiceInput = GetChoiceInputCallback;
+ cb.getOpenFileNameInput = GetOpenFileNameInputCallback;
+ cb.getSaveFileNameInput = GetSaveFileNameInputCallback;
+ cb.getDirectoryNameInput = GetDirectoryNameInputCallback;
+ cb.getFormInput = GetFormInputCallback;
+ cb.showMessageBox = ShowMessageBoxCallback;
+ BNRegisterInteractionHandler(&cb);
+}
+
+
+string BinaryNinja::MarkdownToHTML(const string& contents)
+{
+ char* str = BNMarkdownToHTML(contents.c_str());
+ string result = str;
+ BNFreeString(str);
+ return result;
+}
+
+
+void BinaryNinja::ShowPlainTextReport(const string& title, const string& contents)
+{
+ BNShowPlainTextReport(nullptr, title.c_str(), contents.c_str());
+}
+
+
+void BinaryNinja::ShowMarkdownReport(const string& title, const string& contents, const string& plainText)
+{
+ BNShowMarkdownReport(nullptr, title.c_str(), contents.c_str(), plainText.c_str());
+}
+
+
+void BinaryNinja::ShowHTMLReport(const string& title, const string& contents, const string& plainText)
+{
+ BNShowHTMLReport(nullptr, title.c_str(), contents.c_str(), plainText.c_str());
+}
+
+
+bool BinaryNinja::GetTextLineInput(string& result, const string& prompt, const string& title)
+{
+ char* value = nullptr;
+ if (!BNGetTextLineInput(&value, prompt.c_str(), title.c_str()))
+ return false;
+ result = value;
+ BNFreeString(value);
+ return true;
+}
+
+
+bool BinaryNinja::GetIntegerInput(int64_t& result, const string& prompt, const string& title)
+{
+ return BNGetIntegerInput(&result, prompt.c_str(), title.c_str());
+}
+
+
+bool BinaryNinja::GetAddressInput(uint64_t& result, const string& prompt, const string& title)
+{
+ return BNGetAddressInput(&result, prompt.c_str(), title.c_str(), nullptr, 0);
+}
+
+
+bool BinaryNinja::GetChoiceInput(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 = BNGetChoiceInput(&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;
+ if (!BNGetOpenFileNameInput(&value, prompt.c_str(), ext.c_str()))
+ return false;
+ result = value;
+ BNFreeString(value);
+ return true;
+}
+
+
+bool BinaryNinja::GetSaveFileNameInput(string& result, const string& prompt, const string& ext,
+ const string& defaultName)
+{
+ char* value = nullptr;
+ if (!BNGetSaveFileNameInput(&value, prompt.c_str(), ext.c_str(), defaultName.c_str()))
+ return false;
+ result = value;
+ BNFreeString(value);
+ return true;
+}
+
+
+bool BinaryNinja::GetDirectoryNameInput(string& result, const string& prompt, const string& defaultName)
+{
+ char* value = nullptr;
+ if (!BNGetDirectoryNameInput(&value, prompt.c_str(), defaultName.c_str()))
+ return false;
+ result = value;
+ BNFreeString(value);
+ return true;
+}
+
+
+bool BinaryNinja::GetFormInput(vector<FormInputField>& fields, const string& title)
+{
+ // Construct field list in core format
+ BNFormInputField* fieldBuf = new BNFormInputField[fields.size()];
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ fieldBuf[i].type = fields[i].type;
+ fieldBuf[i].prompt = fields[i].prompt.c_str();
+ switch (fields[i].type)
+ {
+ case AddressFormField:
+ fieldBuf[i].view = fields[i].view ? fields[i].view->GetObject() : nullptr;
+ fieldBuf[i].currentAddress = fields[i].currentAddress;
+ break;
+ case ChoiceFormField:
+ fieldBuf[i].choices = new const char*[fields[i].choices.size()];
+ fieldBuf[i].count = fields[i].choices.size();
+ for (size_t j = 0; j < fields[i].choices.size(); j++)
+ fieldBuf[i].choices[j] = fields[i].choices[j].c_str();
+ break;
+ case OpenFileNameFormField:
+ fieldBuf[i].ext = fields[i].ext.c_str();
+ break;
+ case SaveFileNameFormField:
+ fieldBuf[i].ext = fields[i].ext.c_str();
+ fieldBuf[i].defaultName = fields[i].defaultName.c_str();
+ break;
+ case DirectoryNameFormField:
+ fieldBuf[i].defaultName = fields[i].defaultName.c_str();
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool ok = BNGetFormInput(fieldBuf, fields.size(), title.c_str());
+
+ // Free any memory used by field descriptions
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ if (fields[i].type == ChoiceFormField)
+ delete[] fieldBuf[i].choices;
+ }
+
+ // If user cancelled, there are no results
+ if (!ok)
+ return false;
+
+ // Copy results to API structures
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ switch (fields[i].type)
+ {
+ case TextLineFormField:
+ case MultilineTextFormField:
+ case OpenFileNameFormField:
+ case SaveFileNameFormField:
+ case DirectoryNameFormField:
+ fields[i].stringResult = fieldBuf[i].stringResult;
+ break;
+ case IntegerFormField:
+ fields[i].intResult = fieldBuf[i].intResult;
+ break;
+ case AddressFormField:
+ fields[i].addressResult = fieldBuf[i].addressResult;
+ break;
+ case ChoiceFormField:
+ fields[i].indexResult = fieldBuf[i].indexResult;
+ break;
+ default:
+ break;
+ }
+ }
+
+ BNFreeFormInputResults(fieldBuf, fields.size());
+ return true;
+}
+
+
+BNMessageBoxButtonResult BinaryNinja::ShowMessageBox(const string& title, const string& text,
+ BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon)
+{
+ return BNShowMessageBox(title.c_str(), text.c_str(), buttons, icon);
+}