From 2ec606fab8754dad2135deec2e72e87d39382978 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 16 Sep 2016 19:09:01 -0400 Subject: Add APIs for user interaction from plugins --- interaction.cpp | 286 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 interaction.cpp (limited to 'interaction.cpp') diff --git a/interaction.cpp b/interaction.cpp new file mode 100644 index 00000000..f7763679 --- /dev/null +++ b/interaction.cpp @@ -0,0 +1,286 @@ +#include +#include +#include "binaryninjaapi.h" + +using namespace std; +using namespace BinaryNinja; + + +void InteractionHandler::ShowMarkdownReport(Ref view, const string& title, const string& contents, + const string& plainText) +{ + ShowHTMLReport(view, title, MarkdownToHTML(contents), plainText); +} + + +void InteractionHandler::ShowHTMLReport(Ref 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, 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 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; +} + + +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; + 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& 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; +} -- cgit v1.3.1