diff --git a/include/providers/file_provider.hpp b/include/providers/file_provider.hpp index d966182d8..67a471336 100644 --- a/include/providers/file_provider.hpp +++ b/include/providers/file_provider.hpp @@ -19,8 +19,14 @@ namespace hex::prv { void write(u64 offset, void *buffer, size_t size) override; size_t getSize() override; + std::vector> getDataInformation() override; + private: FILE *m_file; + std::string m_path; + + bool m_fileStatsValid = false; + struct stat m_fileStats = { 0 }; bool m_readable, m_writable; }; diff --git a/include/providers/provider.hpp b/include/providers/provider.hpp index a52a3a712..6f01e02b4 100644 --- a/include/providers/provider.hpp +++ b/include/providers/provider.hpp @@ -2,6 +2,9 @@ #include +#include +#include + namespace hex::prv { class Provider { @@ -16,6 +19,8 @@ namespace hex::prv { virtual void read(u64 offset, void *buffer, size_t size) = 0; virtual void write(u64 offset, void *buffer, size_t size) = 0; virtual size_t getSize() = 0; + + virtual std::vector> getDataInformation() = 0; }; } \ No newline at end of file diff --git a/include/utils.hpp b/include/utils.hpp index 7a4d6a66e..8f8c6d6b2 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -46,5 +46,33 @@ namespace hex { return static_cast(type) >> 4; } + inline std::string toByteString(u64 bytes) { + double value = bytes; + u8 unitIndex = 0; + + while (value > 1024) { + value /= 1024; + unitIndex++; + + if (unitIndex == 6) + break; + } + + std::string result = std::to_string(value); + + switch (unitIndex) { + case 0: result += " Bytes"; break; + case 1: result += " kB"; break; + case 2: result += " MB"; break; + case 3: result += " GB"; break; + case 4: result += " TB"; break; + case 5: result += " PB"; break; + case 6: result += " EB"; break; + default: result = "A lot!"; + } + + return result; + } + } \ No newline at end of file diff --git a/source/provider/file_provider.cpp b/source/provider/file_provider.cpp index 125e5691b..7d8a2cda3 100644 --- a/source/provider/file_provider.cpp +++ b/source/provider/file_provider.cpp @@ -2,9 +2,16 @@ #include +#include +#include + +#include "utils.hpp" + namespace hex::prv { - FileProvider::FileProvider(std::string_view path) { + FileProvider::FileProvider(std::string_view path) : Provider(), m_path(path) { + this->m_fileStatsValid = stat(path.data(), &this->m_fileStats) == 0; + this->m_file = fopen(path.data(), "r+b"); this->m_readable = true; @@ -14,6 +21,7 @@ namespace hex::prv { this->m_file = fopen(path.data(), "rb"); this->m_writable = false; } + } FileProvider::~FileProvider() { @@ -56,4 +64,19 @@ namespace hex::prv { return ftell(this->m_file); } + std::vector> FileProvider::getDataInformation() { + std::vector> result; + + result.emplace_back("File path", this->m_path); + result.emplace_back("Size", hex::toByteString(this->getSize())); + + if (this->m_fileStatsValid) { + result.emplace_back("Creation time", ctime(&this->m_fileStats.st_ctime)); + result.emplace_back("Last access time", ctime(&this->m_fileStats.st_atime)); + result.emplace_back("Last modification time", ctime(&this->m_fileStats.st_mtime)); + } + + return result; + } + } \ No newline at end of file diff --git a/source/views/view_information.cpp b/source/views/view_information.cpp index 2d6202c58..e1bf16c81 100644 --- a/source/views/view_information.cpp +++ b/source/views/view_information.cpp @@ -48,7 +48,7 @@ namespace hex { if (!this->m_windowOpen) return; - if (ImGui::Begin("File Information", &this->m_windowOpen)) { + if (ImGui::Begin("Data Information", &this->m_windowOpen)) { ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) { @@ -127,6 +127,29 @@ namespace hex { ImGui::NewLine(); + for (auto &[name, value] : this->m_dataProvider->getDataInformation()) { + ImGui::LabelText(name.c_str(), "%s", value.c_str()); + } + + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + + if (!this->m_fileDescription.empty()) { + ImGui::TextUnformatted("Description:"); + ImGui::TextWrapped("%s", this->m_fileDescription.c_str()); + ImGui::NewLine(); + } + + if (!this->m_mimeType.empty()) { + ImGui::TextUnformatted("MIME Type:"); + ImGui::TextWrapped("%s", this->m_mimeType.c_str()); + ImGui::NewLine(); + } + + ImGui::Separator(); + ImGui::NewLine(); + ImGui::Text("Byte Distribution"); ImGui::PlotHistogram("##nolabel", this->m_valueCounts.data(), 256, 0, nullptr, FLT_MAX, FLT_MAX, ImVec2(0, 100)); @@ -147,22 +170,6 @@ namespace hex { ImGui::NewLine(); ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "This data is most likely encrypted or compressed!"); } - - ImGui::NewLine(); - ImGui::Separator(); - ImGui::NewLine(); - - if (!this->m_fileDescription.empty()) { - ImGui::TextUnformatted("Description:"); - ImGui::TextWrapped("%s", this->m_fileDescription.c_str()); - ImGui::NewLine(); - } - - if (!this->m_mimeType.empty()) { - ImGui::TextUnformatted("MIME Type:"); - ImGui::TextWrapped("%s", this->m_mimeType.c_str()); - ImGui::NewLine(); - } } ImGui::EndChild(); @@ -172,7 +179,7 @@ namespace hex { void ViewInformation::createMenu() { if (ImGui::BeginMenu("View")) { - ImGui::MenuItem("Entropy View", "", &this->m_windowOpen); + ImGui::MenuItem("Data Information View", "", &this->m_windowOpen); ImGui::EndMenu(); } } diff --git a/source/views/view_strings.cpp b/source/views/view_strings.cpp index 627383452..0189323a0 100644 --- a/source/views/view_strings.cpp +++ b/source/views/view_strings.cpp @@ -81,7 +81,7 @@ namespace hex { if (sortSpecs->SpecsDirty) { std::sort(this->m_foundStrings.begin(), this->m_foundStrings.end(), - [this, &sortSpecs](FoundString &left, FoundString &right) -> bool { + [&sortSpecs](FoundString &left, FoundString &right) -> bool { if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("position")) { if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) return left.offset > right.offset;