impr: Refactor and modularize data information view
This commit is contained in:
parent
a2ffac9424
commit
56e7c15064
@ -24,6 +24,7 @@ namespace hex {
|
||||
|
||||
class View;
|
||||
class Shortcut;
|
||||
class Task;
|
||||
|
||||
namespace dp {
|
||||
class Node;
|
||||
@ -1259,6 +1260,7 @@ namespace hex {
|
||||
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName);
|
||||
}
|
||||
|
||||
/* Reports Registry. Allows adding new sections to exported reports */
|
||||
namespace Reports {
|
||||
|
||||
namespace impl {
|
||||
@ -1276,6 +1278,73 @@ namespace hex {
|
||||
void addReportProvider(impl::Callback callback);
|
||||
|
||||
}
|
||||
|
||||
namespace DataInformation {
|
||||
|
||||
class InformationSection {
|
||||
public:
|
||||
InformationSection(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription = "", bool hasSettings = false)
|
||||
: m_unlocalizedName(unlocalizedName), m_unlocalizedDescription(unlocalizedDescription),
|
||||
m_hasSettings(hasSettings) { }
|
||||
virtual ~InformationSection() = default;
|
||||
|
||||
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const { return m_unlocalizedName; }
|
||||
[[nodiscard]] const UnlocalizedString& getUnlocalizedDescription() const { return m_unlocalizedDescription; }
|
||||
|
||||
virtual void process(Task &task, prv::Provider *provider, Region region) = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void drawSettings() { }
|
||||
virtual void drawContent() = 0;
|
||||
|
||||
[[nodiscard]] bool isValid() const { return m_valid; }
|
||||
void markValid(bool valid = true) { m_valid = valid; }
|
||||
|
||||
[[nodiscard]] bool isEnabled() const { return m_enabled; }
|
||||
void setEnabled(bool enabled) { m_enabled = enabled; }
|
||||
|
||||
[[nodiscard]] bool isAnalyzing() const { return m_analyzing; }
|
||||
void setAnalyzing(bool analyzing) { m_analyzing = analyzing; }
|
||||
|
||||
virtual void load(const nlohmann::json &data) {
|
||||
m_enabled = data.value<bool>("enabled", true);
|
||||
}
|
||||
[[nodiscard]] virtual nlohmann::json store() {
|
||||
nlohmann::json data;
|
||||
data["enabled"] = m_enabled.load();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool hasSettings() const { return m_hasSettings; }
|
||||
|
||||
private:
|
||||
UnlocalizedString m_unlocalizedName, m_unlocalizedDescription;
|
||||
bool m_hasSettings;
|
||||
|
||||
std::atomic<bool> m_analyzing = false;
|
||||
std::atomic<bool> m_valid = false;
|
||||
std::atomic<bool> m_enabled = true;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
using CreateCallback = std::function<std::unique_ptr<InformationSection>()>;
|
||||
|
||||
const std::vector<CreateCallback>& getInformationSectionConstructors();
|
||||
void addInformationSectionCreator(const CreateCallback &callback);
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void addInformationSection(auto && ...args) {
|
||||
impl::addInformationSectionCreator([args...] {
|
||||
return std::make_unique<T>(std::forward<decltype(args)>(args)...);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ struct GLFWwindow;
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
class AutoResetBase;
|
||||
}
|
||||
|
||||
namespace prv {
|
||||
class Provider;
|
||||
@ -409,7 +411,7 @@ namespace hex {
|
||||
|
||||
bool isWindowResizable();
|
||||
|
||||
void addAutoResetObject(AutoResetBase *object);
|
||||
void addAutoResetObject(hex::impl::AutoResetBase *object);
|
||||
void cleanup();
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ namespace hex {
|
||||
* @brief Updates the current process value of the task
|
||||
* @param value Current value
|
||||
*/
|
||||
void update(u64 value = 0);
|
||||
void update(u64 value);
|
||||
void update() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the maximum value of the task
|
||||
|
@ -5,14 +5,18 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class AutoResetBase {
|
||||
public:
|
||||
virtual ~AutoResetBase() = default;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class AutoReset : AutoResetBase {
|
||||
class AutoReset : public impl::AutoResetBase {
|
||||
public:
|
||||
using Type = T;
|
||||
|
||||
|
@ -17,13 +17,13 @@ namespace hex::magic {
|
||||
|
||||
bool compile();
|
||||
std::string getDescription(const std::vector<u8> &data, bool firstEntryOnly = false);
|
||||
std::string getDescription(prv::Provider *provider, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getDescription(prv::Provider *provider, u64 address = 0x00, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getMIMEType(const std::vector<u8> &data, bool firstEntryOnly = false);
|
||||
std::string getMIMEType(prv::Provider *provider, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getMIMEType(prv::Provider *provider, u64 address = 0x00, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getExtensions(const std::vector<u8> &data, bool firstEntryOnly = false);
|
||||
std::string getExtensions(prv::Provider *provider, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getExtensions(prv::Provider *provider, u64 address = 0x00, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getAppleCreatorType(const std::vector<u8> &data, bool firstEntryOnly = false);
|
||||
std::string getAppleCreatorType(prv::Provider *provider, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
std::string getAppleCreatorType(prv::Provider *provider, u64 address = 0x00, size_t size = 100_KiB, bool firstEntryOnly = false);
|
||||
|
||||
bool isValidMIMEType(const std::string &mimeType);
|
||||
|
||||
|
@ -1255,4 +1255,21 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::DataInformation {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static AutoReset<std::vector<CreateCallback>> s_informationSectionConstructors;
|
||||
const std::vector<CreateCallback>& getInformationSectionConstructors() {
|
||||
return *s_informationSectionConstructors;
|
||||
}
|
||||
|
||||
void addInformationSectionCreator(const CreateCallback &callback) {
|
||||
s_informationSectionConstructors->emplace_back(callback);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -471,8 +471,8 @@ namespace hex {
|
||||
return s_windowResizable;
|
||||
}
|
||||
|
||||
static std::vector<AutoResetBase*> s_autoResetObjects;
|
||||
void addAutoResetObject(AutoResetBase *object) {
|
||||
static std::vector<hex::impl::AutoResetBase*> s_autoResetObjects;
|
||||
void addAutoResetObject(hex::impl::AutoResetBase *object) {
|
||||
s_autoResetObjects.emplace_back(object);
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,12 @@ namespace hex {
|
||||
throw TaskInterruptor();
|
||||
}
|
||||
|
||||
void Task::update() const {
|
||||
if (m_shouldInterrupt.load(std::memory_order_relaxed)) [[unlikely]]
|
||||
throw TaskInterruptor();
|
||||
}
|
||||
|
||||
|
||||
void Task::setMaxValue(u64 value) {
|
||||
m_maxValue = value;
|
||||
}
|
||||
|
@ -113,9 +113,9 @@ namespace hex::magic {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getDescription(prv::Provider *provider, size_t size, bool firstEntryOnly) {
|
||||
std::string getDescription(prv::Provider *provider, u64 address, size_t size, bool firstEntryOnly) {
|
||||
std::vector<u8> buffer(std::min<u64>(provider->getSize(), size), 0x00);
|
||||
provider->read(provider->getBaseAddress(), buffer.data(), buffer.size());
|
||||
provider->read(provider->getBaseAddress() + address, buffer.data(), buffer.size());
|
||||
|
||||
return getDescription(buffer, firstEntryOnly);
|
||||
}
|
||||
@ -138,16 +138,16 @@ namespace hex::magic {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getMIMEType(prv::Provider *provider, size_t size, bool firstEntryOnly) {
|
||||
std::string getMIMEType(prv::Provider *provider, u64 address, size_t size, bool firstEntryOnly) {
|
||||
std::vector<u8> buffer(std::min<u64>(provider->getSize(), size), 0x00);
|
||||
provider->read(provider->getBaseAddress(), buffer.data(), buffer.size());
|
||||
provider->read(provider->getBaseAddress() + address, buffer.data(), buffer.size());
|
||||
|
||||
return getMIMEType(buffer, firstEntryOnly);
|
||||
}
|
||||
|
||||
std::string getExtensions(prv::Provider *provider, size_t size, bool firstEntryOnly) {
|
||||
std::string getExtensions(prv::Provider *provider, u64 address, size_t size, bool firstEntryOnly) {
|
||||
std::vector<u8> buffer(std::min<u64>(provider->getSize(), size), 0x00);
|
||||
provider->read(provider->getBaseAddress(), buffer.data(), buffer.size());
|
||||
provider->read(provider->getBaseAddress() + address, buffer.data(), buffer.size());
|
||||
|
||||
return getExtensions(buffer, firstEntryOnly);
|
||||
}
|
||||
@ -170,9 +170,9 @@ namespace hex::magic {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getAppleCreatorType(prv::Provider *provider, size_t size, bool firstEntryOnly) {
|
||||
std::string getAppleCreatorType(prv::Provider *provider, u64 address, size_t size, bool firstEntryOnly) {
|
||||
std::vector<u8> buffer(std::min<u64>(provider->getSize(), size), 0x00);
|
||||
provider->read(provider->getBaseAddress(), buffer.data(), buffer.size());
|
||||
provider->read(provider->getBaseAddress() + address, buffer.data(), buffer.size());
|
||||
|
||||
return getAppleCreatorType(buffer, firstEntryOnly);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ add_imhex_plugin(
|
||||
source/content/out_of_box_experience.cpp
|
||||
source/content/minimap_visualizers.cpp
|
||||
source/content/window_decoration.cpp
|
||||
source/content/data_information_sections.cpp
|
||||
|
||||
source/content/data_processor_nodes/basic_nodes.cpp
|
||||
source/content/data_processor_nodes/control_nodes.cpp
|
||||
|
@ -302,7 +302,7 @@ namespace hex {
|
||||
void draw(ImVec2 size, ImPlotFlags flags, bool updateHandle = false) {
|
||||
|
||||
if (!m_processing && ImPlot::BeginPlot("##ChunkBasedAnalysis", size, flags)) {
|
||||
ImPlot::SetupAxes("hex.ui.common.address"_lang, "hex.builtin.view.information.entropy"_lang,
|
||||
ImPlot::SetupAxes("hex.ui.common.address"_lang, "hex.builtin.information_section.info_analysis.entropy"_lang,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch);
|
||||
ImPlot::SetupAxisFormat(ImAxis_X1, impl::IntegerAxisFormatter, (void*)("0x%04llX"));
|
||||
@ -682,7 +682,7 @@ namespace hex {
|
||||
u64 m_endAddress = 0;
|
||||
|
||||
// Hold the result of the byte distribution analysis
|
||||
std::array<ImU64, 256> m_valueCounts;
|
||||
std::array<ImU64, 256> m_valueCounts = { };
|
||||
std::atomic<bool> m_processing = false;
|
||||
};
|
||||
|
||||
|
@ -1,64 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
|
||||
#include "content/helpers/diagrams.hpp"
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <ui/widgets.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewInformation : public View::Window {
|
||||
public:
|
||||
explicit ViewInformation();
|
||||
~ViewInformation() override;
|
||||
~ViewInformation() override = default;
|
||||
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
struct AnalysisData {
|
||||
AnalysisData() = default;
|
||||
AnalysisData(const AnalysisData&) = default;
|
||||
|
||||
TaskHolder analyzerTask;
|
||||
|
||||
bool dataValid = false;
|
||||
u32 blockSize = 0;
|
||||
double averageEntropy = -1.0;
|
||||
|
||||
double highestBlockEntropy = -1.0;
|
||||
u64 highestBlockEntropyAddress = 0x00;
|
||||
double lowestBlockEntropy = -1.0;
|
||||
u64 lowestBlockEntropyAddress = 0x00;
|
||||
|
||||
double plainTextCharacterPercentage = -1.0;
|
||||
|
||||
Region analysisRegion = { 0, 0 };
|
||||
Region analyzedRegion = { 0, 0 };
|
||||
prv::Provider *analyzedProvider = nullptr;
|
||||
|
||||
std::string dataDescription;
|
||||
std::string dataMimeType;
|
||||
std::string dataAppleCreatorType;
|
||||
std::string dataExtensions;
|
||||
|
||||
std::shared_ptr<DiagramDigram> digram;
|
||||
std::shared_ptr<DiagramLayeredDistribution> layeredDistribution;
|
||||
std::shared_ptr<DiagramByteDistribution> byteDistribution;
|
||||
std::shared_ptr<DiagramByteTypesDistribution> byteTypesDistribution;
|
||||
std::shared_ptr<DiagramChunkBasedEntropyAnalysis> chunkBasedEntropy;
|
||||
|
||||
u32 inputChunkSize = 0;
|
||||
ui::RegionType selectionType = ui::RegionType::EntireData;
|
||||
};
|
||||
|
||||
PerProvider<AnalysisData> m_analysis;
|
||||
|
||||
|
||||
void analyze();
|
||||
|
||||
struct AnalysisData {
|
||||
bool valid = false;
|
||||
|
||||
TaskHolder task;
|
||||
prv::Provider *analyzedProvider = nullptr;
|
||||
Region analysisRegion = { 0, 0 };
|
||||
|
||||
ui::RegionType selectionType = ui::RegionType::EntireData;
|
||||
|
||||
std::list<std::unique_ptr<ContentRegistry::DataInformation::InformationSection>> informationSections;
|
||||
};
|
||||
|
||||
PerProvider<AnalysisData> m_analysisData;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -837,32 +837,32 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "Erstelle eine neue Regel um sie zu bearbeiten.",
|
||||
"hex.builtin.view.information.analyze": "Seite analysieren",
|
||||
"hex.builtin.view.information.analyzing": "Analysiere...",
|
||||
"hex.builtin.view.information.apple_type": "Apple Creator / Type Code",
|
||||
"hex.builtin.view.information.block_size": "Blockgrösse",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} Blöcke mit {1} Bytes",
|
||||
"hex.builtin.view.information.byte_types": "Byte Typen",
|
||||
"hex.builtin.information_section.magic.apple_type": "Apple Creator / Type Code",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "Blockgrösse",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} Blöcke mit {1} Bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "Byte Typen",
|
||||
"hex.builtin.view.information.control": "Einstellungen",
|
||||
"hex.builtin.view.information.description": "Beschreibung",
|
||||
"hex.builtin.view.information.digram": "Diagramm",
|
||||
"hex.builtin.view.information.distribution": "Byte Verteilung",
|
||||
"hex.builtin.view.information.encrypted": "Diese Daten sind vermutlich verschlüsselt oder komprimiert!",
|
||||
"hex.builtin.view.information.entropy": "Entropie",
|
||||
"hex.builtin.view.information.extension": "Dateiendung",
|
||||
"hex.builtin.view.information.file_entropy": "Gesammtentropie",
|
||||
"hex.builtin.view.information.highest_entropy": "Höchste Blockentropie",
|
||||
"hex.builtin.view.information.info_analysis": "Informationsanalyse",
|
||||
"hex.builtin.view.information.layered_distribution": "Schichtverteilung",
|
||||
"hex.builtin.view.information.lowest_entropy": "Tiefste Blockentropie",
|
||||
"hex.builtin.view.information.magic": "Magic Informationen",
|
||||
"hex.builtin.information_section.magic.description": "Beschreibung",
|
||||
"hex.builtin.information_section.info_analysis.digram": "Diagramm",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "Byte Verteilung",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "Diese Daten sind vermutlich verschlüsselt oder komprimiert!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "Entropie",
|
||||
"hex.builtin.information_section.magic.extension": "Dateiendung",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "Gesammtentropie",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Höchste Blockentropie",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "Informationsanalyse",
|
||||
"hex.builtin.information_section.info_analysis": "Schichtverteilung",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "Tiefste Blockentropie",
|
||||
"hex.builtin.information_section.magic": "Magic Informationen",
|
||||
"hex.builtin.view.information.magic_db_added": "Magic Datenbank hinzugefügt!",
|
||||
"hex.builtin.view.information.mime": "MIME Typ",
|
||||
"hex.builtin.information_section.magic.mime": "MIME Typ",
|
||||
"hex.builtin.view.information.name": "Dateninformationen",
|
||||
"hex.builtin.view.information.octet_stream_text": "Unbekannt",
|
||||
"hex.builtin.view.information.octet_stream_warning": "application/octet-stream ist ein generischer MIME Typ für Binärdaten. Dies bedeutet, dass der Dateityp nicht zuverlässig erkannt werden konnte.",
|
||||
"hex.builtin.view.information.plain_text": "Diese Daten sind vermutlich einfacher Text.",
|
||||
"hex.builtin.view.information.plain_text_percentage": "Klartext Prozentanteil",
|
||||
"hex.builtin.view.information.provider_information": "Provider Informationen",
|
||||
"hex.builtin.view.information.region": "Analysierte Region",
|
||||
"hex.builtin.view.information.not_analyzed": "Noch nicht Analysiert",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "Unbekannt",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "application/octet-stream ist ein generischer MIME Typ für Binärdaten. Dies bedeutet, dass der Dateityp nicht zuverlässig erkannt werden konnte.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "Diese Daten sind vermutlich einfacher Text.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "Klartext Prozentanteil",
|
||||
"hex.builtin.information_section.provider_information": "Provider Informationen",
|
||||
"hex.builtin.view.logs.component": "Komponent",
|
||||
"hex.builtin.view.logs.log_level": "Log Level",
|
||||
"hex.builtin.view.logs.message": "Nachricht",
|
||||
|
@ -827,32 +827,32 @@
|
||||
"hex.builtin.view.highlight_rules.menu.edit.rules": "Modify highlight rules...",
|
||||
"hex.builtin.view.information.analyze": "Analyze page",
|
||||
"hex.builtin.view.information.analyzing": "Analyzing...",
|
||||
"hex.builtin.view.information.apple_type": "Apple Creator / Type Code",
|
||||
"hex.builtin.view.information.block_size": "Block size",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.view.information.byte_types": "Byte types",
|
||||
"hex.builtin.information_section.magic.apple_type": "Apple Creator / Type Code",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "Block size",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "Byte types",
|
||||
"hex.builtin.view.information.control": "Control",
|
||||
"hex.builtin.view.information.description": "Description",
|
||||
"hex.builtin.view.information.digram": "Digram",
|
||||
"hex.builtin.view.information.distribution": "Byte distribution",
|
||||
"hex.builtin.view.information.encrypted": "This data is most likely encrypted or compressed!",
|
||||
"hex.builtin.view.information.entropy": "Entropy",
|
||||
"hex.builtin.view.information.extension": "File Extension",
|
||||
"hex.builtin.view.information.file_entropy": "Overall entropy",
|
||||
"hex.builtin.view.information.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.view.information.lowest_entropy": "Lowest block entropy",
|
||||
"hex.builtin.view.information.info_analysis": "Information analysis",
|
||||
"hex.builtin.view.information.layered_distribution": "Layered distribution",
|
||||
"hex.builtin.view.information.magic": "Magic information",
|
||||
"hex.builtin.information_section.magic.description": "Description",
|
||||
"hex.builtin.information_section.info_analysis.digram": "Digram",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "Byte distribution",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "This data is most likely encrypted or compressed!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "Entropy",
|
||||
"hex.builtin.information_section.magic.extension": "File Extension",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "Overall entropy",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "Lowest block entropy",
|
||||
"hex.builtin.information_section.info_analysis": "Information analysis",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "Layered distribution",
|
||||
"hex.builtin.information_section.magic": "Magic information",
|
||||
"hex.builtin.view.information.magic_db_added": "Magic database added!",
|
||||
"hex.builtin.view.information.mime": "MIME Type",
|
||||
"hex.builtin.information_section.magic.mime": "MIME Type",
|
||||
"hex.builtin.view.information.name": "Data Information",
|
||||
"hex.builtin.view.information.octet_stream_text": "Unknown",
|
||||
"hex.builtin.view.information.octet_stream_warning": "application/octet-stream denotes an unknown data type.\n\nThis means that this data has no MIME type associated with it because it's not in a known format.",
|
||||
"hex.builtin.view.information.region": "Analyzed region",
|
||||
"hex.builtin.view.information.plain_text": "This data is most likely plain text.",
|
||||
"hex.builtin.view.information.plain_text_percentage": "Plain text percentage",
|
||||
"hex.builtin.view.information.provider_information": "Provider Information",
|
||||
"hex.builtin.view.information.not_analyzed": "Not yet analyzed",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "Unknown",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "application/octet-stream denotes an unknown data type.\n\nThis means that this data has no MIME type associated with it because it's not in a known format.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "This data is most likely plain text.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "Plain text percentage",
|
||||
"hex.builtin.information_section.provider_information": "Provider Information",
|
||||
"hex.builtin.view.logs.component": "Component",
|
||||
"hex.builtin.view.logs.log_level": "Log Level",
|
||||
"hex.builtin.view.logs.message": "Message",
|
||||
|
@ -833,32 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "Analizar página",
|
||||
"hex.builtin.view.information.analyzing": "Analizando...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "Tamaño de bloque",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} bloques de {1} bytes",
|
||||
"hex.builtin.view.information.byte_types": "Tipos de byte",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "Tamaño de bloque",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} bloques de {1} bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "Tipos de byte",
|
||||
"hex.builtin.view.information.control": "Ajustes",
|
||||
"hex.builtin.view.information.description": "Descripción",
|
||||
"hex.builtin.view.information.digram": "Digrama",
|
||||
"hex.builtin.view.information.distribution": "Distribución de bytes",
|
||||
"hex.builtin.view.information.encrypted": "¡Estos datos están probablemente encriptados o comprimidos!",
|
||||
"hex.builtin.view.information.entropy": "Entropía",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "Entropía total",
|
||||
"hex.builtin.view.information.highest_entropy": "Entropía del mayor bloque",
|
||||
"hex.builtin.view.information.info_analysis": "Análisis de información",
|
||||
"hex.builtin.view.information.layered_distribution": "Distribución en capas",
|
||||
"hex.builtin.view.information.lowest_entropy": "Entropía del menor bloque",
|
||||
"hex.builtin.view.information.magic": "Información del 'magic'",
|
||||
"hex.builtin.information_section.magic.description": "Descripción",
|
||||
"hex.builtin.information_section.info_analysis.digram": "Digrama",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "Distribución de bytes",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "¡Estos datos están probablemente encriptados o comprimidos!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "Entropía",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "Entropía total",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Entropía del mayor bloque",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "Entropía del menor bloque",
|
||||
"hex.builtin.information_section.info_analysis": "Análisis de información",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "Distribución en capas",
|
||||
"hex.builtin.information_section.magic": "Información del 'magic'",
|
||||
"hex.builtin.view.information.magic_db_added": "¡Añadida base de datos de 'magic's!",
|
||||
"hex.builtin.view.information.mime": "Tipo MIME",
|
||||
"hex.builtin.information_section.magic.mime": "Tipo MIME",
|
||||
"hex.builtin.view.information.name": "Información de Datos:",
|
||||
"hex.builtin.view.information.octet_stream_text": "",
|
||||
"hex.builtin.view.information.octet_stream_warning": "",
|
||||
"hex.builtin.view.information.plain_text": "Estos datos probablemente no están encriptados o comprimidos.",
|
||||
"hex.builtin.view.information.plain_text_percentage": "Porcentaje de 'plain text'",
|
||||
"hex.builtin.view.information.provider_information": "Información de Proveedor",
|
||||
"hex.builtin.view.information.region": "Región analizada",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "Estos datos probablemente no están encriptados o comprimidos.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "Porcentaje de 'plain text'",
|
||||
"hex.builtin.information_section.provider_information": "Información de Proveedor",
|
||||
"hex.builtin.view.logs.component": "",
|
||||
"hex.builtin.view.logs.log_level": "",
|
||||
"hex.builtin.view.logs.message": "",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "Analizza Pagina",
|
||||
"hex.builtin.view.information.analyzing": "Sto analizzando...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "Dimensione del Blocco",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} blocchi di {1} bytes",
|
||||
"hex.builtin.view.information.byte_types": "",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "Dimensione del Blocco",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} blocchi di {1} bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "",
|
||||
"hex.builtin.view.information.control": "Controllo",
|
||||
"hex.builtin.view.information.description": "Descrizione",
|
||||
"hex.builtin.view.information.digram": "",
|
||||
"hex.builtin.view.information.distribution": "Distribuzione dei Byte",
|
||||
"hex.builtin.view.information.encrypted": "Questi dati sono probabilmente codificati o compressi!",
|
||||
"hex.builtin.view.information.entropy": "Entropia",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "",
|
||||
"hex.builtin.view.information.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.view.information.info_analysis": "Informazioni dell'analisi",
|
||||
"hex.builtin.view.information.layered_distribution": "",
|
||||
"hex.builtin.view.information.lowest_entropy": "",
|
||||
"hex.builtin.view.information.magic": "Informazione Magica",
|
||||
"hex.builtin.information_section.magic.description": "Descrizione",
|
||||
"hex.builtin.information_section.info_analysis.digram": "",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "Distribuzione dei Byte",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "Questi dati sono probabilmente codificati o compressi!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "Entropia",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.information_section.info_analysis": "Informazioni dell'analisi",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "",
|
||||
"hex.builtin.information_section.magic": "Informazione Magica",
|
||||
"hex.builtin.view.information.magic_db_added": "Database magico aggiunto!",
|
||||
"hex.builtin.view.information.mime": "Tipo di MIME",
|
||||
"hex.builtin.information_section.magic.mime": "Tipo di MIME",
|
||||
"hex.builtin.view.information.name": "Informazione sui Dati",
|
||||
"hex.builtin.view.information.octet_stream_text": "",
|
||||
"hex.builtin.view.information.octet_stream_warning": "",
|
||||
"hex.builtin.view.information.plain_text": "",
|
||||
"hex.builtin.view.information.plain_text_percentage": "",
|
||||
"hex.builtin.view.information.provider_information": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "",
|
||||
"hex.builtin.information_section.provider_information": "",
|
||||
"hex.builtin.view.information.region": "Regione Analizzata",
|
||||
"hex.builtin.view.logs.component": "",
|
||||
"hex.builtin.view.logs.log_level": "",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "表示中のページを解析する",
|
||||
"hex.builtin.view.information.analyzing": "解析中…",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "ブロックサイズ",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} ブロック/ {1} バイト",
|
||||
"hex.builtin.view.information.byte_types": "",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "ブロックサイズ",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} ブロック/ {1} バイト",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "",
|
||||
"hex.builtin.view.information.control": "コントロール",
|
||||
"hex.builtin.view.information.description": "詳細",
|
||||
"hex.builtin.view.information.digram": "",
|
||||
"hex.builtin.view.information.distribution": "バイト分布",
|
||||
"hex.builtin.view.information.encrypted": "暗号化や圧縮を経たデータと推測されます。",
|
||||
"hex.builtin.view.information.entropy": "エントロピー",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "",
|
||||
"hex.builtin.view.information.highest_entropy": "最大エントロピーブロック",
|
||||
"hex.builtin.view.information.info_analysis": "情報の分析",
|
||||
"hex.builtin.view.information.layered_distribution": "",
|
||||
"hex.builtin.view.information.lowest_entropy": "",
|
||||
"hex.builtin.view.information.magic": "Magic情報",
|
||||
"hex.builtin.information_section.magic.description": "詳細",
|
||||
"hex.builtin.information_section.info_analysis.digram": "",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "バイト分布",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "暗号化や圧縮を経たデータと推測されます。",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "エントロピー",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "最大エントロピーブロック",
|
||||
"hex.builtin.information_section.info_analysis": "情報の分析",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "",
|
||||
"hex.builtin.information_section.magic": "Magic情報",
|
||||
"hex.builtin.view.information.magic_db_added": "Magicデータベースが追加されました。",
|
||||
"hex.builtin.view.information.mime": "MIMEタイプ",
|
||||
"hex.builtin.information_section.magic.mime": "MIMEタイプ",
|
||||
"hex.builtin.view.information.name": "データ解析",
|
||||
"hex.builtin.view.information.octet_stream_text": "",
|
||||
"hex.builtin.view.information.octet_stream_warning": "",
|
||||
"hex.builtin.view.information.plain_text": "",
|
||||
"hex.builtin.view.information.plain_text_percentage": "",
|
||||
"hex.builtin.view.information.provider_information": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "",
|
||||
"hex.builtin.information_section.provider_information": "",
|
||||
"hex.builtin.view.information.region": "解析する領域",
|
||||
"hex.builtin.view.logs.component": "",
|
||||
"hex.builtin.view.logs.log_level": "",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "규칙을 만들어 편집하세요",
|
||||
"hex.builtin.view.information.analyze": "페이지 분석",
|
||||
"hex.builtin.view.information.analyzing": "분석 중...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "블록 크기",
|
||||
"hex.builtin.view.information.block_size.desc": "{1}바이트 중 {0}블록",
|
||||
"hex.builtin.view.information.byte_types": "바이트 유형",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "블록 크기",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{1}바이트 중 {0}블록",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "바이트 유형",
|
||||
"hex.builtin.view.information.control": "제어",
|
||||
"hex.builtin.view.information.description": "설명",
|
||||
"hex.builtin.view.information.digram": "다이어그램",
|
||||
"hex.builtin.view.information.distribution": "바이트 분포",
|
||||
"hex.builtin.view.information.encrypted": "이 데이터는 암호화 또는 압축되어 있을 가능성이 높습니다!",
|
||||
"hex.builtin.view.information.entropy": "엔트로피",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "전체 엔트로피",
|
||||
"hex.builtin.view.information.highest_entropy": "최고 블록 엔트로피",
|
||||
"hex.builtin.view.information.info_analysis": "정보 분석",
|
||||
"hex.builtin.view.information.layered_distribution": "계층화 분포",
|
||||
"hex.builtin.view.information.lowest_entropy": "최저 블록 엔트로피",
|
||||
"hex.builtin.view.information.magic": "Magic 정보",
|
||||
"hex.builtin.information_section.magic.description": "설명",
|
||||
"hex.builtin.information_section.info_analysis.digram": "다이어그램",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "바이트 분포",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "이 데이터는 암호화 또는 압축되어 있을 가능성이 높습니다!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "엔트로피",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "전체 엔트로피",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "최고 블록 엔트로피",
|
||||
"hex.builtin.information_section.info_analysis": "정보 분석",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "계층화 분포",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "최저 블록 엔트로피",
|
||||
"hex.builtin.information_section.magic": "Magic 정보",
|
||||
"hex.builtin.view.information.magic_db_added": "Magic 데이터베이스 추가됨!",
|
||||
"hex.builtin.view.information.mime": "MIME 유형",
|
||||
"hex.builtin.information_section.magic.mime": "MIME 유형",
|
||||
"hex.builtin.view.information.name": "데이터 정보",
|
||||
"hex.builtin.view.information.octet_stream_text": "알 수 없음",
|
||||
"hex.builtin.view.information.octet_stream_warning": "application/octet-stream은 알 수 없는 데이터 유형을 나타냅니다.\n\n즉, 이 데이터는 알려진 형식이 아니기 때문에 연결된 MIME 유형이 없습니다.",
|
||||
"hex.builtin.view.information.plain_text": "이 데이터는 일반 텍스트일 가능성이 높습니다.",
|
||||
"hex.builtin.view.information.plain_text_percentage": "일반 텍스트 비율",
|
||||
"hex.builtin.view.information.provider_information": "공급자 정보",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "알 수 없음",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "application/octet-stream은 알 수 없는 데이터 유형을 나타냅니다.\n\n즉, 이 데이터는 알려진 형식이 아니기 때문에 연결된 MIME 유형이 없습니다.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "이 데이터는 일반 텍스트일 가능성이 높습니다.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "일반 텍스트 비율",
|
||||
"hex.builtin.information_section.provider_information": "공급자 정보",
|
||||
"hex.builtin.view.information.region": "분석한 영역",
|
||||
"hex.builtin.view.logs.component": "컴포넌트",
|
||||
"hex.builtin.view.logs.log_level": "로그 수준",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "Analisar Pagina",
|
||||
"hex.builtin.view.information.analyzing": "Analizando...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "Block size",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.view.information.byte_types": "",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "Block size",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "",
|
||||
"hex.builtin.view.information.control": "Controle",
|
||||
"hex.builtin.view.information.description": "Descrição",
|
||||
"hex.builtin.view.information.digram": "",
|
||||
"hex.builtin.view.information.distribution": "Byte distribution",
|
||||
"hex.builtin.view.information.encrypted": "Esses dados provavelmente estão criptografados ou compactados!",
|
||||
"hex.builtin.view.information.entropy": "Entropy",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "",
|
||||
"hex.builtin.view.information.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.view.information.info_analysis": "Análise de Informações",
|
||||
"hex.builtin.view.information.layered_distribution": "",
|
||||
"hex.builtin.view.information.lowest_entropy": "",
|
||||
"hex.builtin.view.information.magic": "Informação Mágica",
|
||||
"hex.builtin.information_section.magic.description": "Descrição",
|
||||
"hex.builtin.information_section.info_analysis.digram": "",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "Byte distribution",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "Esses dados provavelmente estão criptografados ou compactados!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "Entropy",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.information_section.info_analysis": "Análise de Informações",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "",
|
||||
"hex.builtin.information_section.magic": "Informação Mágica",
|
||||
"hex.builtin.view.information.magic_db_added": "Magic database added!",
|
||||
"hex.builtin.view.information.mime": "MIME Type",
|
||||
"hex.builtin.information_section.magic.mime": "MIME Type",
|
||||
"hex.builtin.view.information.name": "Data Information",
|
||||
"hex.builtin.view.information.octet_stream_text": "",
|
||||
"hex.builtin.view.information.octet_stream_warning": "",
|
||||
"hex.builtin.view.information.plain_text": "",
|
||||
"hex.builtin.view.information.plain_text_percentage": "",
|
||||
"hex.builtin.view.information.provider_information": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "",
|
||||
"hex.builtin.information_section.provider_information": "",
|
||||
"hex.builtin.view.information.region": "Região analizada",
|
||||
"hex.builtin.view.logs.component": "",
|
||||
"hex.builtin.view.logs.log_level": "",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "分析",
|
||||
"hex.builtin.view.information.analyzing": "分析中...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "块大小",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} 块 × {1} 字节",
|
||||
"hex.builtin.view.information.byte_types": "字节类型",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "块大小",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} 块 × {1} 字节",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "字节类型",
|
||||
"hex.builtin.view.information.control": "控制",
|
||||
"hex.builtin.view.information.description": "描述",
|
||||
"hex.builtin.view.information.digram": "图",
|
||||
"hex.builtin.view.information.distribution": "字节分布",
|
||||
"hex.builtin.view.information.encrypted": "此数据似乎经过了加密或压缩!",
|
||||
"hex.builtin.view.information.entropy": "熵",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "整体熵",
|
||||
"hex.builtin.view.information.highest_entropy": "最高区块熵",
|
||||
"hex.builtin.view.information.info_analysis": "信息分析",
|
||||
"hex.builtin.view.information.layered_distribution": "分层分布",
|
||||
"hex.builtin.view.information.lowest_entropy": "最低区块熵",
|
||||
"hex.builtin.view.information.magic": "LibMagic 信息",
|
||||
"hex.builtin.information_section.magic.description": "描述",
|
||||
"hex.builtin.information_section.info_analysis.digram": "图",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "字节分布",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "此数据似乎经过了加密或压缩!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "熵",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "整体熵",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "最高区块熵",
|
||||
"hex.builtin.information_section.info_analysis": "信息分析",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "分层分布",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "最低区块熵",
|
||||
"hex.builtin.information_section.magic": "LibMagic 信息",
|
||||
"hex.builtin.view.information.magic_db_added": "LibMagic 数据库已添加!",
|
||||
"hex.builtin.view.information.mime": "MIME 类型",
|
||||
"hex.builtin.information_section.magic.mime": "MIME 类型",
|
||||
"hex.builtin.view.information.name": "数据信息",
|
||||
"hex.builtin.view.information.octet_stream_text": "未知",
|
||||
"hex.builtin.view.information.octet_stream_warning": "application/octet-stream 表示未知的数据类型。\n\n这意味着该数据没有与之关联的 MIME 类型,因为它不是已知的格式。",
|
||||
"hex.builtin.view.information.plain_text": "此数据很可能是纯文本。",
|
||||
"hex.builtin.view.information.plain_text_percentage": "纯文本百分比",
|
||||
"hex.builtin.view.information.provider_information": "提供者信息",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "未知",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "application/octet-stream 表示未知的数据类型。\n\n这意味着该数据没有与之关联的 MIME 类型,因为它不是已知的格式。",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "此数据很可能是纯文本。",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "纯文本百分比",
|
||||
"hex.builtin.information_section.provider_information": "提供者信息",
|
||||
"hex.builtin.view.information.region": "已分析区域",
|
||||
"hex.builtin.view.logs.component": "组件",
|
||||
"hex.builtin.view.logs.log_level": "日志等级",
|
||||
|
@ -833,31 +833,31 @@
|
||||
"hex.builtin.view.highlight_rules.no_rule": "",
|
||||
"hex.builtin.view.information.analyze": "分析頁面",
|
||||
"hex.builtin.view.information.analyzing": "正在分析...",
|
||||
"hex.builtin.view.information.apple_type": "",
|
||||
"hex.builtin.view.information.block_size": "區塊大小",
|
||||
"hex.builtin.view.information.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.view.information.byte_types": "",
|
||||
"hex.builtin.information_section.magic.apple_type": "",
|
||||
"hex.builtin.information_section.info_analysis.block_size": "區塊大小",
|
||||
"hex.builtin.information_section.info_analysis.block_size.desc": "{0} blocks of {1} bytes",
|
||||
"hex.builtin.information_section.info_analysis.byte_types": "",
|
||||
"hex.builtin.view.information.control": "控制",
|
||||
"hex.builtin.view.information.description": "說明",
|
||||
"hex.builtin.view.information.digram": "",
|
||||
"hex.builtin.view.information.distribution": "位元組分佈",
|
||||
"hex.builtin.view.information.encrypted": "此資料很有可能經過加密或壓縮!",
|
||||
"hex.builtin.view.information.entropy": "熵",
|
||||
"hex.builtin.view.information.extension": "",
|
||||
"hex.builtin.view.information.file_entropy": "",
|
||||
"hex.builtin.view.information.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.view.information.info_analysis": "資訊分析",
|
||||
"hex.builtin.view.information.layered_distribution": "",
|
||||
"hex.builtin.view.information.lowest_entropy": "",
|
||||
"hex.builtin.view.information.magic": "Magic information",
|
||||
"hex.builtin.information_section.magic.description": "說明",
|
||||
"hex.builtin.information_section.info_analysis.digram": "",
|
||||
"hex.builtin.information_section.info_analysis.distribution": "位元組分佈",
|
||||
"hex.builtin.information_section.info_analysis.encrypted": "此資料很有可能經過加密或壓縮!",
|
||||
"hex.builtin.information_section.info_analysis.entropy": "熵",
|
||||
"hex.builtin.information_section.magic.extension": "",
|
||||
"hex.builtin.information_section.info_analysis.file_entropy": "",
|
||||
"hex.builtin.information_section.info_analysis.highest_entropy": "Highest block entropy",
|
||||
"hex.builtin.information_section.info_analysis": "資訊分析",
|
||||
"hex.builtin.information_section.info_analysis.layered_distribution": "",
|
||||
"hex.builtin.information_section.info_analysis.lowest_entropy": "",
|
||||
"hex.builtin.information_section.magic": "Magic information",
|
||||
"hex.builtin.view.information.magic_db_added": "Magic database added!",
|
||||
"hex.builtin.view.information.mime": "MIME 類型",
|
||||
"hex.builtin.information_section.magic.mime": "MIME 類型",
|
||||
"hex.builtin.view.information.name": "資料資訊",
|
||||
"hex.builtin.view.information.octet_stream_text": "未知",
|
||||
"hex.builtin.view.information.octet_stream_warning": "application/octet-stream denotes an unknown data type.\n\nThis means that this data has no MIME type associated with it because it's not in a known format.",
|
||||
"hex.builtin.view.information.plain_text": "此資料很有可能是純文字。",
|
||||
"hex.builtin.view.information.plain_text_percentage": "純文字比例",
|
||||
"hex.builtin.view.information.provider_information": "提供者資訊",
|
||||
"hex.builtin.information_section.magic.octet_stream_text": "未知",
|
||||
"hex.builtin.information_section.magic.octet_stream_warning": "application/octet-stream denotes an unknown data type.\n\nThis means that this data has no MIME type associated with it because it's not in a known format.",
|
||||
"hex.builtin.information_section.info_analysis.plain_text": "此資料很有可能是純文字。",
|
||||
"hex.builtin.information_section.info_analysis.plain_text_percentage": "純文字比例",
|
||||
"hex.builtin.information_section.provider_information": "提供者資訊",
|
||||
"hex.builtin.view.information.region": "Analyzed region",
|
||||
"hex.builtin.view.logs.component": "Component",
|
||||
"hex.builtin.view.logs.log_level": "記錄等級",
|
||||
|
369
plugins/builtin/source/content/data_information_sections.cpp
Normal file
369
plugins/builtin/source/content/data_information_sections.cpp
Normal file
@ -0,0 +1,369 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <content/helpers/diagrams.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class InformationProvider : public ContentRegistry::DataInformation::InformationSection {
|
||||
public:
|
||||
InformationProvider() : InformationSection("hex.builtin.information_section.provider_information") { }
|
||||
~InformationProvider() override = default;
|
||||
|
||||
void process(Task &task, prv::Provider *provider, Region region) override {
|
||||
hex::unused(task);
|
||||
|
||||
m_provider = provider;
|
||||
m_region = region;
|
||||
}
|
||||
|
||||
void reset() override {
|
||||
m_provider = nullptr;
|
||||
m_region = Region::Invalid();
|
||||
}
|
||||
|
||||
void drawContent() override {
|
||||
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoKeepColumnsVisible)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
for (auto &[name, value] : m_provider->getDataDescription()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", name);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedWrapped("{}", value);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.ui.common.region"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", m_region.getStartAddress(), m_region.getEndAddress());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
prv::Provider *m_provider = nullptr;
|
||||
Region m_region = Region::Invalid();
|
||||
};
|
||||
|
||||
class InformationMagic : public ContentRegistry::DataInformation::InformationSection {
|
||||
public:
|
||||
InformationMagic() : InformationSection("hex.builtin.information_section.magic") { }
|
||||
~InformationMagic() override = default;
|
||||
|
||||
void process(Task &task, prv::Provider *provider, Region region) override {
|
||||
magic::compile();
|
||||
|
||||
task.update();
|
||||
|
||||
m_dataDescription = magic::getDescription(provider, region.getStartAddress());
|
||||
m_dataMimeType = magic::getMIMEType(provider, region.getStartAddress());
|
||||
m_dataAppleCreatorType = magic::getAppleCreatorType(provider, region.getStartAddress());
|
||||
m_dataExtensions = magic::getExtensions(provider, region.getStartAddress());
|
||||
}
|
||||
|
||||
void drawContent() override {
|
||||
if (!(m_dataDescription.empty() && m_dataMimeType.empty())) {
|
||||
if (ImGui::BeginTable("magic", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (!m_dataDescription.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.magic.description"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (m_dataDescription == "data") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.information_section.magic.octet_stream_text"_lang, m_dataDescription);
|
||||
} else {
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_dataDescription);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_dataMimeType.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.magic.mime"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (m_dataMimeType.contains("application/octet-stream")) {
|
||||
ImGuiExt::TextFormatted("{}", m_dataMimeType);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGuiExt::HelpHover("hex.builtin.information_section.magic.octet_stream_warning"_lang);
|
||||
ImGui::PopStyleVar();
|
||||
} else {
|
||||
ImGuiExt::TextFormatted("{}", m_dataMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_dataAppleCreatorType.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.magic.apple_type"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", m_dataAppleCreatorType);
|
||||
}
|
||||
|
||||
if (!m_dataExtensions.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.magic.extension"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", m_dataExtensions);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
}
|
||||
}
|
||||
|
||||
void reset() override {
|
||||
m_dataDescription.clear();
|
||||
m_dataMimeType.clear();
|
||||
m_dataAppleCreatorType.clear();
|
||||
m_dataExtensions.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_dataDescription;
|
||||
std::string m_dataMimeType;
|
||||
std::string m_dataAppleCreatorType;
|
||||
std::string m_dataExtensions;
|
||||
};
|
||||
|
||||
class InformationByteAnalysis : public ContentRegistry::DataInformation::InformationSection {
|
||||
public:
|
||||
InformationByteAnalysis() : InformationSection("hex.builtin.information_section.info_analysis", "", true) { }
|
||||
~InformationByteAnalysis() override = default;
|
||||
|
||||
void process(Task &task, prv::Provider *provider, Region region) override {
|
||||
if (m_inputChunkSize == 0)
|
||||
m_inputChunkSize = 256;
|
||||
|
||||
m_blockSize = std::max<u32>(std::ceil(region.getSize() / 2048.0F), 256);
|
||||
|
||||
m_byteDistribution.reset();
|
||||
m_digram.reset(region.getSize());
|
||||
m_layeredDistribution.reset(region.getSize());
|
||||
m_byteTypesDistribution.reset(region.getStartAddress(), region.getEndAddress(), provider->getBaseAddress(), provider->getActualSize());
|
||||
m_chunkBasedEntropy.reset(m_inputChunkSize, region.getStartAddress(), region.getEndAddress(),
|
||||
provider->getBaseAddress(), provider->getActualSize());
|
||||
|
||||
// Create a handle to the file
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
reader.seek(region.getStartAddress());
|
||||
reader.setEndAddress(region.getEndAddress());
|
||||
|
||||
// Loop over each byte of the selection and update each analysis
|
||||
// one byte at a time to process the file only once
|
||||
for (u8 byte : reader) {
|
||||
m_byteDistribution.update(byte);
|
||||
m_byteTypesDistribution.update(byte);
|
||||
m_chunkBasedEntropy.update(byte);
|
||||
m_layeredDistribution.update(byte);
|
||||
m_digram.update(byte);
|
||||
task.update();
|
||||
}
|
||||
|
||||
m_averageEntropy = m_chunkBasedEntropy.calculateEntropy(m_byteDistribution.get(), region.getSize());
|
||||
m_highestBlockEntropy = m_chunkBasedEntropy.getHighestEntropyBlockValue();
|
||||
m_highestBlockEntropyAddress = m_chunkBasedEntropy.getHighestEntropyBlockAddress();
|
||||
m_lowestBlockEntropy = m_chunkBasedEntropy.getLowestEntropyBlockValue();
|
||||
m_lowestBlockEntropyAddress = m_chunkBasedEntropy.getLowestEntropyBlockAddress();
|
||||
m_plainTextCharacterPercentage = m_byteTypesDistribution.getPlainTextCharacterPercentage();
|
||||
}
|
||||
|
||||
void reset() override {
|
||||
m_averageEntropy = -1.0;
|
||||
m_highestBlockEntropy = -1.0;
|
||||
m_plainTextCharacterPercentage = -1.0;
|
||||
}
|
||||
|
||||
void drawSettings() override {
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.information_section.info_analysis.block_size"_lang, &m_inputChunkSize);
|
||||
}
|
||||
|
||||
void drawContent() override {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
ImPlot::PushStyleColor(ImPlotCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
|
||||
// Display byte distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.info_analysis.distribution"_lang);
|
||||
m_byteDistribution.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect
|
||||
);
|
||||
|
||||
// Display byte types distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.info_analysis.byte_types"_lang);
|
||||
m_byteTypesDistribution.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
);
|
||||
|
||||
// Display chunk-based entropy analysis
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.info_analysis.entropy"_lang);
|
||||
m_chunkBasedEntropy.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
);
|
||||
|
||||
ImPlot::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
// Entropy information
|
||||
if (ImGui::BeginTable("entropy_info", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.information_section.info_analysis.block_size"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("hex.builtin.information_section.info_analysis.block_size.desc"_lang, m_chunkBasedEntropy.getSize(), m_chunkBasedEntropy.getChunkSize());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.information_section.info_analysis.file_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
if (m_averageEntropy < 0) {
|
||||
ImGui::TextUnformatted("???");
|
||||
} else {
|
||||
auto entropy = std::abs(m_averageEntropy);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F - (0.3F * entropy), 0.6F, 0.8F, 1.0F).Value);
|
||||
ImGui::ProgressBar(entropy, ImVec2(200_scaled, ImGui::GetTextLineHeight()), hex::format("{:.5f}", entropy).c_str());
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.information_section.info_analysis.highest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", m_highestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", m_highestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(m_highestBlockEntropyAddress, m_inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.information_section.info_analysis.lowest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", m_lowestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", m_lowestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(m_lowestBlockEntropyAddress, m_inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.information_section.info_analysis.plain_text_percentage"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (m_plainTextCharacterPercentage < 0) {
|
||||
ImGui::TextUnformatted("???");
|
||||
} else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (m_plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value);
|
||||
ImGui::ProgressBar(m_plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight()));
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
// General information
|
||||
if (ImGui::BeginTable("info", 1, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (m_averageEntropy > 0.83 && m_highestBlockEntropy > 0.9) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.information_section.info_analysis.encrypted"_lang);
|
||||
}
|
||||
|
||||
if (m_plainTextCharacterPercentage > 95) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.information_section.info_analysis.plain_text"_lang);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
auto availableWidth = ImGui::GetContentRegionAvail().x;
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.info_analysis.digram"_lang);
|
||||
m_digram.draw({ availableWidth, availableWidth });
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.information_section.info_analysis.layered_distribution"_lang);
|
||||
m_layeredDistribution.draw({ availableWidth, availableWidth });
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &data) override {
|
||||
InformationSection::load(data);
|
||||
|
||||
m_inputChunkSize = data.value("block_size", 0);
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
auto result = InformationSection::store();
|
||||
result["block_size"] = m_inputChunkSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_inputChunkSize = 0;
|
||||
|
||||
u32 m_blockSize = 0;
|
||||
double m_averageEntropy = -1.0;
|
||||
|
||||
double m_highestBlockEntropy = -1.0;
|
||||
u64 m_highestBlockEntropyAddress = 0x00;
|
||||
double m_lowestBlockEntropy = -1.0;
|
||||
u64 m_lowestBlockEntropyAddress = 0x00;
|
||||
double m_plainTextCharacterPercentage = -1.0;
|
||||
|
||||
DiagramDigram m_digram;
|
||||
DiagramLayeredDistribution m_layeredDistribution;
|
||||
DiagramByteDistribution m_byteDistribution;
|
||||
DiagramByteTypesDistribution m_byteTypesDistribution;
|
||||
DiagramChunkBasedEntropyAnalysis m_chunkBasedEntropy;
|
||||
};
|
||||
|
||||
void registerDataInformationSections() {
|
||||
ContentRegistry::DataInformation::addInformationSection<InformationProvider>();
|
||||
ContentRegistry::DataInformation::addInformationSection<InformationMagic>();
|
||||
ContentRegistry::DataInformation::addInformationSection<InformationByteAnalysis>();
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <toasts/toast_notification.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
@ -18,6 +19,17 @@ namespace hex::plugin::builtin {
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) {
|
||||
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
|
||||
ui::ToastInfo::open("hex.builtin.view.information.magic_db_added"_lang);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,9 @@
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/providers/buffered_reader.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/magic.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
|
||||
#include <implot.h>
|
||||
|
||||
#include <toasts/toast_notification.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
@ -21,153 +14,53 @@ namespace hex::plugin::builtin {
|
||||
using namespace hex::literals;
|
||||
|
||||
ViewInformation::ViewInformation() : View::Window("hex.builtin.view.information.name", ICON_VS_GRAPH_LINE) {
|
||||
EventDataChanged::subscribe(this, [this](prv::Provider *provider) {
|
||||
auto &analysis = m_analysis.get(provider);
|
||||
m_analysisData.setOnCreateCallback([](prv::Provider *provider, AnalysisData &data) {
|
||||
data.analyzedProvider = provider;
|
||||
|
||||
analysis.dataValid = false;
|
||||
analysis.plainTextCharacterPercentage = -1.0;
|
||||
analysis.averageEntropy = -1.0;
|
||||
analysis.highestBlockEntropy = -1.0;
|
||||
analysis.blockSize = 0;
|
||||
analysis.dataMimeType.clear();
|
||||
analysis.dataDescription.clear();
|
||||
analysis.dataAppleCreatorType.clear();
|
||||
analysis.dataExtensions.clear();
|
||||
analysis.analyzedRegion = { 0, 0 };
|
||||
});
|
||||
|
||||
EventRegionSelected::subscribe(this, [this](ImHexApi::HexEditor::ProviderRegion region) {
|
||||
auto &analysis = m_analysis.get(region.getProvider());
|
||||
|
||||
// Set the position of the diagram relative to the place where
|
||||
// the user clicked inside the hex editor view
|
||||
if (analysis.blockSize != 0) {
|
||||
analysis.byteTypesDistribution->setHandlePosition(region.getStartAddress());
|
||||
analysis.chunkBasedEntropy->setHandlePosition(region.getStartAddress());
|
||||
for (const auto &informationSectionConstructor : ContentRegistry::DataInformation::impl::getInformationSectionConstructors()) {
|
||||
data.informationSections.push_back(informationSectionConstructor());
|
||||
}
|
||||
});
|
||||
|
||||
ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) {
|
||||
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
|
||||
ui::ToastInfo::open("hex.builtin.view.information.magic_db_added"_lang);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
});
|
||||
|
||||
m_analysis.setOnCreateCallback([](prv::Provider *provider, AnalysisData &analysis) {
|
||||
analysis.dataValid = false;
|
||||
analysis.blockSize = 0;
|
||||
analysis.averageEntropy = -1.0;
|
||||
|
||||
analysis.lowestBlockEntropy = -1.0;
|
||||
analysis.highestBlockEntropy = -1.0;
|
||||
analysis.lowestBlockEntropyAddress = 0x00;
|
||||
analysis.highestBlockEntropyAddress = 0x00;
|
||||
|
||||
analysis.plainTextCharacterPercentage = -1.0;
|
||||
|
||||
analysis.analysisRegion = { 0, 0 };
|
||||
analysis.analyzedRegion = { 0, 0 };
|
||||
analysis.analyzedProvider = provider;
|
||||
|
||||
analysis.inputChunkSize = 0;
|
||||
analysis.selectionType = ui::RegionType::EntireData;
|
||||
|
||||
analysis.digram = std::make_shared<DiagramDigram>();
|
||||
analysis.layeredDistribution = std::make_shared<DiagramLayeredDistribution>();
|
||||
analysis.byteDistribution = std::make_shared<DiagramByteDistribution>();
|
||||
analysis.byteTypesDistribution = std::make_shared<DiagramByteTypesDistribution>();
|
||||
analysis.chunkBasedEntropy = std::make_shared<DiagramChunkBasedEntropyAnalysis>();
|
||||
});
|
||||
}
|
||||
|
||||
ViewInformation::~ViewInformation() {
|
||||
EventDataChanged::unsubscribe(this);
|
||||
EventRegionSelected::unsubscribe(this);
|
||||
EventProviderOpened::unsubscribe(this);
|
||||
}
|
||||
|
||||
void ViewInformation::analyze() {
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.misc", "hex.builtin.achievement.misc.analyze_file.name");
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
auto &analysis = m_analysisData.get(provider);
|
||||
|
||||
m_analysis.get(provider).analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this, provider](auto &task) {
|
||||
auto &analysis = m_analysis.get(provider);
|
||||
const auto ®ion = analysis.analysisRegion;
|
||||
|
||||
analysis.analyzedProvider = provider;
|
||||
|
||||
if ((region.getStartAddress() >= region.getEndAddress()) || (region.getEndAddress() > provider->getActualSize())) {
|
||||
analysis.analyzedRegion = { provider->getBaseAddress(), provider->getActualSize() };
|
||||
// Reset all sections
|
||||
for (const auto §ion : analysis.informationSections) {
|
||||
section->reset();
|
||||
section->markValid(false);
|
||||
}
|
||||
|
||||
if (analysis.inputChunkSize == 0) {
|
||||
analysis.inputChunkSize = 256;
|
||||
// Run analyzers for each section
|
||||
analysis.task = TaskManager::createTask("hex.builtin.view.information.analyzing"_lang, analysis.informationSections.size(), [provider, &analysis](Task &task) {
|
||||
u32 progress = 0;
|
||||
for (const auto §ion : analysis.informationSections) {
|
||||
// Only process the section if it is enabled
|
||||
if (section->isEnabled()) {
|
||||
// Set the section as analyzing so a spinner can be drawn
|
||||
section->setAnalyzing(true);
|
||||
ON_SCOPE_EXIT { section->setAnalyzing(false); };
|
||||
|
||||
try {
|
||||
// Process the section
|
||||
section->process(task, provider, analysis.analysisRegion);
|
||||
|
||||
// Mark the section as valid
|
||||
section->markValid();
|
||||
} catch (const std::exception &e) {
|
||||
// Show a toast with the error if the section failed to process
|
||||
ui::ToastError::open(hex::format("hex.builtin.view.information.error_processing_section"_lang, Lang(section->getUnlocalizedName()), e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
task.setMaxValue(analysis.analyzedRegion.getSize());
|
||||
|
||||
{
|
||||
magic::compile();
|
||||
|
||||
analysis.dataDescription = magic::getDescription(provider);
|
||||
analysis.dataMimeType = magic::getMIMEType(provider);
|
||||
analysis.dataAppleCreatorType = magic::getAppleCreatorType(provider);
|
||||
analysis.dataExtensions = magic::getExtensions(provider);
|
||||
// Update the task progress
|
||||
progress += 1;
|
||||
task.update(progress);
|
||||
}
|
||||
|
||||
{
|
||||
analysis.blockSize = std::max<u32>(std::ceil(provider->getActualSize() / 2048.0F), 256);
|
||||
|
||||
analysis.averageEntropy = -1.0;
|
||||
analysis.highestBlockEntropy = -1.0;
|
||||
analysis.plainTextCharacterPercentage = -1.0;
|
||||
|
||||
// Setup / start each analysis
|
||||
|
||||
analysis.byteDistribution->reset();
|
||||
analysis.digram->reset(region.getSize());
|
||||
analysis.layeredDistribution->reset(region.getSize());
|
||||
analysis.byteTypesDistribution->reset(region.getStartAddress(), region.getEndAddress(), provider->getBaseAddress(), provider->getActualSize());
|
||||
analysis.chunkBasedEntropy->reset(analysis.inputChunkSize, region.getStartAddress(), region.getEndAddress(),
|
||||
provider->getBaseAddress(), provider->getActualSize());
|
||||
|
||||
// Create a handle to the file
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
reader.seek(region.getStartAddress());
|
||||
reader.setEndAddress(region.getEndAddress());
|
||||
|
||||
analysis.analyzedRegion = region;
|
||||
|
||||
u64 count = 0;
|
||||
|
||||
// Loop over each byte of the selection and update each analysis
|
||||
// one byte at a time to process the file only once
|
||||
for (u8 byte : reader) {
|
||||
analysis.byteDistribution->update(byte);
|
||||
analysis.byteTypesDistribution->update(byte);
|
||||
analysis.chunkBasedEntropy->update(byte);
|
||||
analysis.layeredDistribution->update(byte);
|
||||
analysis.digram->update(byte);
|
||||
++count;
|
||||
task.update(count);
|
||||
}
|
||||
|
||||
analysis.averageEntropy = analysis.chunkBasedEntropy->calculateEntropy(analysis.byteDistribution->get(), analysis.analyzedRegion.getSize());
|
||||
analysis.highestBlockEntropy = analysis.chunkBasedEntropy->getHighestEntropyBlockValue();
|
||||
analysis.highestBlockEntropyAddress = analysis.chunkBasedEntropy->getHighestEntropyBlockAddress();
|
||||
analysis.lowestBlockEntropy = analysis.chunkBasedEntropy->getLowestEntropyBlockValue();
|
||||
analysis.lowestBlockEntropyAddress = analysis.chunkBasedEntropy->getLowestEntropyBlockAddress();
|
||||
analysis.plainTextCharacterPercentage = analysis.byteTypesDistribution->getPlainTextCharacterPercentage();
|
||||
}
|
||||
|
||||
analysis.dataValid = true;
|
||||
});
|
||||
}
|
||||
|
||||
@ -176,25 +69,52 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
auto &analysis = m_analysis.get(provider);
|
||||
auto &analysis = m_analysisData.get(provider);
|
||||
|
||||
ImGui::BeginDisabled(analysis.analyzerTask.isRunning());
|
||||
// Draw settings window
|
||||
ImGui::BeginDisabled(analysis.task.isRunning());
|
||||
ImGuiExt::BeginSubWindow("hex.ui.common.settings"_lang);
|
||||
{
|
||||
if (ImGui::BeginTable("SettingsTable", 2, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedSame, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
ImGui::TableSetupColumn("Left", ImGuiTableColumnFlags_WidthStretch, 0.5F);
|
||||
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F);
|
||||
// Create a table so we can draw global settings on the left and section specific settings on the right
|
||||
if (ImGui::BeginTable("SettingsTable", 2, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
ImGui::TableSetupColumn("Left", ImGuiTableColumnFlags_WidthStretch, 0.3F);
|
||||
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.7F);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
// Draw global settings
|
||||
ImGui::TableNextColumn();
|
||||
ui::regionSelectionPicker(&analysis.analysisRegion, provider, &analysis.selectionType, false);
|
||||
|
||||
// Draw analyzed section names
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.information.block_size"_lang, &analysis.inputChunkSize);
|
||||
if (ImGui::BeginTable("AnalyzedSections", 1, ImGuiTableFlags_BordersInnerH, ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||
for (const auto §ion : analysis.informationSections | std::views::reverse) {
|
||||
if (section->isEnabled() && (section->isValid() || section->isAnalyzing())) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::BeginDisabled();
|
||||
{
|
||||
ImGui::TextUnformatted(Lang(section->getUnlocalizedName()));
|
||||
|
||||
if (section->isAnalyzing()) {
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextSpinner("");
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::NewLine();
|
||||
|
||||
// Draw the analyze button
|
||||
ImGui::SetCursorPosX(50_scaled);
|
||||
if (ImGuiExt::DimmedButton("hex.builtin.view.information.analyze"_lang, ImVec2(ImGui::GetContentRegionAvail().x - 50_scaled, 0)))
|
||||
this->analyze();
|
||||
@ -202,238 +122,89 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::EndSubWindow();
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (analysis.analyzerTask.isRunning()) {
|
||||
// Draw the analyzing spinner
|
||||
if (analysis.task.isRunning()) {
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
} else {
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
if (!analysis.analyzerTask.isRunning() && analysis.dataValid && analysis.analyzedProvider != nullptr) {
|
||||
|
||||
// Provider information
|
||||
ImGuiExt::Header("hex.builtin.view.information.provider_information"_lang, true);
|
||||
|
||||
if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoKeepColumnsVisible)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
for (auto &[name, value] : analysis.analyzedProvider->getDataDescription()) {
|
||||
if (analysis.analyzedProvider != nullptr) {
|
||||
for (const auto §ion : analysis.informationSections) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", name);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedWrapped("{}", value);
|
||||
}
|
||||
ImGui::PushID(section.get());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.region"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", analysis.analyzedRegion.getStartAddress(), analysis.analyzedRegion.getEndAddress());
|
||||
bool enabled = section->isEnabled();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
// Magic information
|
||||
if (!(analysis.dataDescription.empty() && analysis.dataMimeType.empty())) {
|
||||
ImGuiExt::Header("hex.builtin.view.information.magic"_lang);
|
||||
|
||||
if (ImGui::BeginTable("magic", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (!analysis.dataDescription.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.description"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (analysis.dataDescription == "data") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, analysis.dataDescription);
|
||||
} else {
|
||||
ImGuiExt::TextFormattedWrapped("{}", analysis.dataDescription);
|
||||
}
|
||||
}
|
||||
|
||||
if (!analysis.dataMimeType.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.mime"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (analysis.dataMimeType.contains("application/octet-stream")) {
|
||||
ImGuiExt::TextFormatted("{}", analysis.dataMimeType);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGuiExt::HelpHover("hex.builtin.view.information.octet_stream_warning"_lang);
|
||||
ImGui::PopStyleVar();
|
||||
} else {
|
||||
ImGuiExt::TextFormatted("{}", analysis.dataMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!analysis.dataAppleCreatorType.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.apple_type"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", analysis.dataAppleCreatorType);
|
||||
}
|
||||
|
||||
if (!analysis.dataExtensions.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.extension"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", analysis.dataExtensions);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
// Information analysis
|
||||
if (analysis.analyzedRegion.getSize() > 0) {
|
||||
|
||||
ImGuiExt::Header("hex.builtin.view.information.info_analysis"_lang);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
ImPlot::PushStyleColor(ImPlotCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
|
||||
// Display byte distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang);
|
||||
analysis.byteDistribution->draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect
|
||||
);
|
||||
|
||||
// Display byte types distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.byte_types"_lang);
|
||||
analysis.byteTypesDistribution->draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
);
|
||||
|
||||
// Display chunk-based entropy analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
||||
analysis.chunkBasedEntropy->draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
);
|
||||
|
||||
ImPlot::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
// Entropy information
|
||||
if (ImGui::BeginTable("entropy_info", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("type");
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.block_size"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.information.block_size.desc"_lang, analysis.chunkBasedEntropy->getSize(), analysis.chunkBasedEntropy->getChunkSize());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.file_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
if (analysis.averageEntropy < 0) {
|
||||
ImGui::TextUnformatted("???");
|
||||
} else {
|
||||
auto entropy = std::abs(analysis.averageEntropy);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F - (0.3F * entropy), 0.6F, 0.8F, 1.0F).Value);
|
||||
ImGui::ProgressBar(entropy, ImVec2(200_scaled, ImGui::GetTextLineHeight()), hex::format("{:.5f}", entropy).c_str());
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.highest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", analysis.highestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", analysis.highestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(analysis.highestBlockEntropyAddress, analysis.inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.lowest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", analysis.lowestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", analysis.lowestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(analysis.lowestBlockEntropyAddress, analysis.inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.plain_text_percentage"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
if (analysis.plainTextCharacterPercentage < 0) {
|
||||
ImGui::TextUnformatted("???");
|
||||
} else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (analysis.plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value);
|
||||
ImGui::ProgressBar(analysis.plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight()));
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
// General information
|
||||
if (ImGui::BeginTable("info", 1, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (analysis.averageEntropy > 0.83 && analysis.highestBlockEntropy > 0.9) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.encrypted"_lang);
|
||||
}
|
||||
|
||||
if (analysis.plainTextCharacterPercentage > 95) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.plain_text"_lang);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
|
||||
if (ImGui::BeginChild(Lang(section->getUnlocalizedName()), ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY, ImGuiWindowFlags_MenuBar)) {
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
|
||||
// Draw the enable checkbox of the section
|
||||
// This is specifically split out so the checkbox does not get disabled when the section is disabled
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.digram"_lang);
|
||||
analysis.digram->draw(scaled(ImVec2(300, 300)));
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().FramePadding.y);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
{
|
||||
if (ImGui::Checkbox("##enabled", &enabled)) {
|
||||
section->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
// Draw the rest of the section header
|
||||
ImGui::BeginDisabled(!enabled);
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.layered_distribution"_lang);
|
||||
analysis.layeredDistribution->draw(scaled(ImVec2(300, 300)));
|
||||
ImGui::TextUnformatted(Lang(section->getUnlocalizedName()));
|
||||
ImGui::SameLine();
|
||||
if (auto description = section->getUnlocalizedDescription(); !description.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::HelpHover(Lang(description));
|
||||
}
|
||||
|
||||
// Draw settings gear on the right
|
||||
if (section->hasSettings()) {
|
||||
ImGui::SameLine(0, ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize(ICON_VS_SETTINGS_GEAR).x);
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_SETTINGS_GEAR, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
ImGui::OpenPopup("SectionSettings");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("SectionSettings")) {
|
||||
ImGuiExt::Header("hex.ui.common.settings"_lang, true);
|
||||
section->drawSettings();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
// Draw the section content
|
||||
ImGui::BeginDisabled(!enabled);
|
||||
{
|
||||
if (section->isValid())
|
||||
section->drawContent();
|
||||
else if (section->isAnalyzing())
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
else
|
||||
ImGuiExt::TextFormattedCenteredHorizontal("hex.builtin.view.information.not_analyzed"_lang);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::NewLine();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ namespace hex::plugin::builtin {
|
||||
void registerAchievements();
|
||||
void registerReportGenerators();
|
||||
void registerTutorials();
|
||||
void registerDataInformationSections();
|
||||
void loadWorkspaces();
|
||||
|
||||
void addWindowDecoration();
|
||||
@ -112,6 +113,7 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
||||
registerAchievements();
|
||||
registerReportGenerators();
|
||||
registerTutorials();
|
||||
registerDataInformationSections();
|
||||
loadWorkspaces();
|
||||
addWindowDecoration();
|
||||
createWelcomeScreen();
|
||||
|
Loading…
Reference in New Issue
Block a user