From 7f97416e6ed160e2972c53758e67d000c43e2db5 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 22 Feb 2021 13:08:06 +0100 Subject: [PATCH] ui/ux: Improve data analyzer interface, make it run asynchronously --- include/views/view_information.hpp | 4 +- plugins/builtin/source/lang/en_US.cpp | 8 +- source/views/view_information.cpp | 180 ++++++++++++++------------ 3 files changed, 106 insertions(+), 86 deletions(-) diff --git a/include/views/view_information.hpp b/include/views/view_information.hpp index 91aca6cdc..2431bd78b 100644 --- a/include/views/view_information.hpp +++ b/include/views/view_information.hpp @@ -27,12 +27,14 @@ namespace hex { std::vector m_blockEntropy; std::array m_valueCounts = { 0 }; - bool m_shouldInvalidate = false; + bool m_analyzing = false; std::pair m_analyzedRegion = { 0, 0 }; std::string m_fileDescription; std::string m_mimeType; + + void analyze(); }; } \ No newline at end of file diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 16bfa5b41..7303b0677 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -196,10 +196,14 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.menu.edit.set_base", "Set base address" }, { "hex.view.information.name", "Data Information" }, - { "hex.view.information.analyze", "Analyze current page" }, - { "hex.view.information.region", "analyzed region" }, + { "hex.view.information.control", "Control" }, + { "hex.view.information.analyze", "Analyze page" }, + { "hex.view.information.analyzing", "Analyzing..." }, + { "hex.view.information.region", "Analyzed region" }, + { "hex.view.information.magic", "Magic information" }, { "hex.view.information.description", "Description:" }, { "hex.view.information.mime", "MIME Type:" }, + { "hex.view.information.info_analysis", "Information analysis" }, { "hex.view.information.distribution", "Byte distribution" }, { "hex.view.information.entropy", "Entropy" }, { "hex.view.information.block_size", "Block size" }, diff --git a/source/views/view_information.cpp b/source/views/view_information.cpp index d738ef016..795d74df3 100644 --- a/source/views/view_information.cpp +++ b/source/views/view_information.cpp @@ -7,10 +7,13 @@ #include #include #include +#include #include #include +#include + namespace hex { ViewInformation::ViewInformation() : View("hex.view.information.name"_lang) { @@ -44,96 +47,106 @@ namespace hex { return entropy / 8; } + void ViewInformation::analyze() { + this->m_analyzing = true; + + std::thread([this]{ + auto provider = SharedData::currentProvider; + + this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() }; + + { + this->m_blockSize = std::ceil(provider->getSize() / 2048.0F); + std::vector buffer(this->m_blockSize, 0x00); + std::memset(this->m_valueCounts.data(), 0x00, this->m_valueCounts.size() * sizeof(u32)); + this->m_blockEntropy.clear(); + + for (u64 i = 0; i < provider->getSize(); i += this->m_blockSize) { + std::array blockValueCounts = { 0 }; + provider->read(i, buffer.data(), std::min(u64(this->m_blockSize), provider->getSize() - i)); + + for (size_t j = 0; j < this->m_blockSize; j++) { + blockValueCounts[buffer[j]]++; + this->m_valueCounts[buffer[j]]++; + } + this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize)); + } + + this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize()); + this->m_highestBlockEntropy = *std::max_element(this->m_blockEntropy.begin(), this->m_blockEntropy.end()); + } + + { + std::vector buffer(provider->getSize(), 0x00); + provider->read(0x00, buffer.data(), buffer.size()); + + this->m_fileDescription.clear(); + this->m_mimeType.clear(); + + std::string magicFiles; + + std::error_code error; + for (const auto &entry : std::filesystem::directory_iterator("magic", error)) { + if (entry.is_regular_file() && entry.path().extension() == ".mgc") + magicFiles += entry.path().string() + MAGIC_PATH_SEPARATOR; + } + + if (!error) { + magicFiles.pop_back(); + + { + magic_t cookie = magic_open(MAGIC_NONE); + if (magic_load(cookie, magicFiles.c_str()) != -1) + this->m_fileDescription = magic_buffer(cookie, buffer.data(), buffer.size()); + else + this->m_fileDescription = ""; + + magic_close(cookie); + } + + { + magic_t cookie = magic_open(MAGIC_MIME); + if (magic_load(cookie, magicFiles.c_str()) != -1) + this->m_mimeType = magic_buffer(cookie, buffer.data(), buffer.size()); + else + this->m_mimeType = ""; + + magic_close(cookie); + } + + this->m_dataValid = true; + } + } + + this->m_analyzing = false; + }).detach(); + } + void ViewInformation::drawContent() { if (ImGui::Begin("hex.view.information.name"_lang, &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); auto provider = SharedData::currentProvider; - if (provider != nullptr && provider->isReadable()) { - if (this->m_shouldInvalidate) { + ImGui::TextUnformatted("hex.view.information.control"_lang); + ImGui::Separator(); - this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() }; + ImGui::Disabled([this] { + if (ImGui::Button("hex.view.information.analyze"_lang)) + this->analyze(); + }, this->m_analyzing); - { - this->m_blockSize = std::ceil(provider->getSize() / 2048.0F); - std::vector buffer(this->m_blockSize, 0x00); - std::memset(this->m_valueCounts.data(), 0x00, this->m_valueCounts.size() * sizeof(u32)); - this->m_blockEntropy.clear(); - - for (u64 i = 0; i < provider->getSize(); i += this->m_blockSize) { - std::array blockValueCounts = { 0 }; - provider->read(i, buffer.data(), std::min(u64(this->m_blockSize), provider->getSize() - i)); - - for (size_t j = 0; j < this->m_blockSize; j++) { - blockValueCounts[buffer[j]]++; - this->m_valueCounts[buffer[j]]++; - } - this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize)); - } - - this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize()); - this->m_highestBlockEntropy = *std::max_element(this->m_blockEntropy.begin(), this->m_blockEntropy.end()); - } - - { - std::vector buffer(provider->getSize(), 0x00); - provider->read(0x00, buffer.data(), buffer.size()); - - this->m_fileDescription.clear(); - this->m_mimeType.clear(); - - std::string magicFiles; - - std::error_code error; - for (const auto &entry : std::filesystem::directory_iterator("magic", error)) { - if (entry.is_regular_file() && entry.path().extension() == ".mgc") - magicFiles += entry.path().string() + MAGIC_PATH_SEPARATOR; - } - - if (!error) { - magicFiles.pop_back(); - - { - magic_t cookie = magic_open(MAGIC_NONE); - if (magic_load(cookie, magicFiles.c_str()) != -1) - this->m_fileDescription = magic_buffer(cookie, buffer.data(), buffer.size()); - else - this->m_fileDescription = ""; - - magic_close(cookie); - } - - - { - magic_t cookie = magic_open(MAGIC_MIME); - if (magic_load(cookie, magicFiles.c_str()) != -1) - this->m_mimeType = magic_buffer(cookie, buffer.data(), buffer.size()); - else - this->m_mimeType = ""; - - magic_close(cookie); - } - - } - - - this->m_shouldInvalidate = false; - this->m_dataValid = true; - } + if (this->m_analyzing) { + ImGui::SameLine(); + ImGui::TextSpinner("hex.view.information.analyzing"_lang); } - ImGui::NewLine(); - - if (ImGui::Button("hex.view.information.analyze"_lang)) - this->m_shouldInvalidate = true; - - ImGui::NewLine(); - ImGui::Separator(); - ImGui::NewLine(); - if (this->m_dataValid) { + ImGui::NewLine(); + ImGui::TextUnformatted("hex.view.information.region"_lang); + ImGui::Separator(); + for (auto &[name, value] : (SharedData::currentProvider)->getDataInformation()) { ImGui::LabelText(name.c_str(), "%s", value.c_str()); } @@ -141,8 +154,11 @@ namespace hex { ImGui::LabelText("hex.view.information.region"_lang, "0x%llx - 0x%llx", this->m_analyzedRegion.first, this->m_analyzedRegion.second); ImGui::NewLine(); - ImGui::Separator(); - ImGui::NewLine(); + + if (!this->m_fileDescription.empty() || !this->m_mimeType.empty()) { + ImGui::TextUnformatted("hex.view.information.magic"_lang); + ImGui::Separator(); + } if (!this->m_fileDescription.empty()) { ImGui::TextUnformatted("hex.view.information.description"_lang); @@ -156,14 +172,12 @@ namespace hex { ImGui::NewLine(); } + ImGui::TextUnformatted("hex.view.information.info_analysis"_lang); ImGui::Separator(); - ImGui::NewLine(); ImGui::Text("hex.view.information.distribution"_lang); ImGui::PlotHistogram("##nolabel", this->m_valueCounts.data(), 256, 0, nullptr, FLT_MAX, FLT_MAX,ImVec2(0, 100)); - ImGui::NewLine(); - ImGui::Separator(); ImGui::NewLine(); ImGui::Text("hex.view.information.entropy"_lang);