mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 15:57:03 -05:00
feat: Allow custom hashes to be saved to projects
This commit is contained in:
@@ -436,11 +436,12 @@ namespace hex {
|
||||
public:
|
||||
using Callback = std::function<std::vector<u8>(const Region&, prv::Provider *)>;
|
||||
|
||||
Function(const Hash *type, std::string name, Callback callback)
|
||||
Function(Hash *type, std::string name, Callback callback)
|
||||
: m_type(type), m_name(std::move(name)), m_callback(std::move(callback)) {
|
||||
|
||||
}
|
||||
|
||||
[[nodiscard]] Hash *getType() { return this->m_type; }
|
||||
[[nodiscard]] const Hash *getType() const { return this->m_type; }
|
||||
[[nodiscard]] const std::string &getName() const { return this->m_name; }
|
||||
|
||||
@@ -457,7 +458,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
private:
|
||||
const Hash *m_type;
|
||||
Hash *m_type;
|
||||
std::string m_name;
|
||||
Callback m_callback;
|
||||
|
||||
@@ -467,12 +468,15 @@ namespace hex {
|
||||
virtual void draw() { }
|
||||
[[nodiscard]] virtual Function create(std::string name) = 0;
|
||||
|
||||
[[nodiscard]] virtual nlohmann::json store() const = 0;
|
||||
virtual void load(const nlohmann::json &json) = 0;
|
||||
|
||||
[[nodiscard]] const std::string &getUnlocalizedName() const {
|
||||
return this->m_unlocalizedName;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] Function create(const std::string &name, const Function::Callback &callback) const {
|
||||
[[nodiscard]] Function create(const std::string &name, const Function::Callback &callback) {
|
||||
return { this, name, callback };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <pl/pattern_language.hpp>
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <hex/data_processor/node.hpp>
|
||||
#include <hex/data_processor/link.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ProviderExtraData {
|
||||
@@ -73,6 +75,10 @@ namespace hex::plugin::builtin {
|
||||
std::optional<u64> selectionStart, selectionEnd;
|
||||
float scrollPosition = 0.0F;
|
||||
} editor;
|
||||
|
||||
struct Hashes {
|
||||
std::vector<ContentRegistry::Hashes::Hash::Function> hashFunctions;
|
||||
} hashes;
|
||||
};
|
||||
|
||||
static Data& getCurrent() {
|
||||
|
||||
@@ -17,11 +17,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawContent() override;
|
||||
|
||||
private:
|
||||
static bool importHashes(prv::Provider *provider, const nlohmann::json &json);
|
||||
static bool exportHashes(prv::Provider *provider, nlohmann::json &json);
|
||||
|
||||
private:
|
||||
ContentRegistry::Hashes::Hash *m_selectedHash = nullptr;
|
||||
std::string m_newHashName;
|
||||
|
||||
std::vector<ContentRegistry::Hashes::Hash::Function> m_hashFunctions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class HashMD5 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -17,6 +19,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
class HashSHA1 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -30,6 +35,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
class HashSHA224 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -43,6 +51,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
class HashSHA256 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -56,6 +67,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
class HashSHA384 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -69,6 +83,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
class HashSHA512 : public ContentRegistry::Hashes::Hash {
|
||||
@@ -82,6 +99,9 @@ namespace hex::plugin::builtin {
|
||||
return { array.begin(), array.end() };
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override { return { }; }
|
||||
void load(const nlohmann::json &) override {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -113,6 +133,28 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json store() const override {
|
||||
nlohmann::json result;
|
||||
|
||||
result["polynomial"] = this->m_polynomial;
|
||||
result["initialValue"] = this->m_initialValue;
|
||||
result["xorOut"] = this->m_xorOut;
|
||||
result["reflectIn"] = this->m_reflectIn;
|
||||
result["reflectOut"] = this->m_reflectOut;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &json) override {
|
||||
try {
|
||||
this->m_polynomial = json["polynomial"];
|
||||
this->m_initialValue = json["initialValue"];
|
||||
this->m_xorOut = json["xorOut"];
|
||||
this->m_reflectIn = json["reflectIn"];
|
||||
this->m_reflectOut = json["reflectOut"];
|
||||
} catch (std::exception&) { }
|
||||
}
|
||||
|
||||
private:
|
||||
CRCFunction m_crcFunction;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "content/views/view_hashes.hpp"
|
||||
#include "content/helpers/provider_extra_data.hpp"
|
||||
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <vector>
|
||||
@@ -7,18 +9,19 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewHashes::ViewHashes() : View("hex.builtin.view.hashes.name") {
|
||||
EventManager::subscribe<EventRegionSelected>(this, [this](const auto &) {
|
||||
for (auto &function : this->m_hashFunctions)
|
||||
EventManager::subscribe<EventRegionSelected>(this, [](const auto &providerRegion) {
|
||||
for (auto &function : ProviderExtraData::get(providerRegion.getProvider()).hashes.hashFunctions)
|
||||
function.reset();
|
||||
});
|
||||
|
||||
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
|
||||
ImHexApi::HexEditor::addTooltipProvider([](u64 address, const u8 *data, size_t size) {
|
||||
hex::unused(data);
|
||||
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
if (ImGui::GetIO().KeyShift) {
|
||||
if (!this->m_hashFunctions.empty() && selection.has_value() && selection->overlaps(Region { address, size })) {
|
||||
auto &hashFunctions = ProviderExtraData::get(selection->getProvider()).hashes.hashFunctions;
|
||||
if (!hashFunctions.empty() && selection.has_value() && selection->overlaps(Region { address, size })) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||
@@ -31,7 +34,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Indent();
|
||||
if (ImGui::BeginTable("##hashes_tooltip", 3, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
for (auto &function : this->m_hashFunctions) {
|
||||
for (auto &function : hashFunctions) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextFormatted("{}", function.getName());
|
||||
@@ -55,6 +58,29 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ProjectFile::registerPerProviderHandler({
|
||||
.basePath = "hashes.json",
|
||||
.required = false,
|
||||
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||
auto fileContent = tar.read(basePath);
|
||||
if (fileContent.empty())
|
||||
return true;
|
||||
|
||||
auto data = nlohmann::json::parse(fileContent.begin(), fileContent.end());
|
||||
ProviderExtraData::get(provider).hashes.hashFunctions.clear();
|
||||
|
||||
return ViewHashes::importHashes(provider, data);
|
||||
},
|
||||
.store = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||
nlohmann::json data;
|
||||
|
||||
bool result = ViewHashes::exportHashes(provider, data);
|
||||
tar.write(basePath, data.dump(4));
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ViewHashes::~ViewHashes() {
|
||||
@@ -70,6 +96,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.hashes.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto &hashFunctions = ProviderExtraData::get(ImHexApi::Provider::get()).hashes.hashFunctions;
|
||||
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, this->m_selectedHash != nullptr ? LangEntry(this->m_selectedHash->getUnlocalizedName()) : "")) {
|
||||
|
||||
for (const auto hash : hashes) {
|
||||
@@ -106,7 +134,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::BeginDisabled(this->m_newHashName.empty() || this->m_selectedHash == nullptr);
|
||||
if (ImGui::IconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (this->m_selectedHash != nullptr)
|
||||
this->m_hashFunctions.push_back(this->m_selectedHash->create(this->m_newHashName));
|
||||
hashFunctions.push_back(this->m_selectedHash->create(this->m_newHashName));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -121,8 +149,8 @@ namespace hex::plugin::builtin {
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
std::optional<u32> indexToRemove;
|
||||
for (u32 i = 0; i < this->m_hashFunctions.size(); i++) {
|
||||
auto &function = this->m_hashFunctions[i];
|
||||
for (u32 i = 0; i < hashFunctions.size(); i++) {
|
||||
auto &function = hashFunctions[i];
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
@@ -167,7 +195,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (indexToRemove.has_value()) {
|
||||
this->m_hashFunctions.erase(this->m_hashFunctions.begin() + indexToRemove.value());
|
||||
hashFunctions.erase(hashFunctions.begin() + indexToRemove.value());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
@@ -179,4 +207,45 @@ namespace hex::plugin::builtin {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool ViewHashes::importHashes(prv::Provider *provider, const nlohmann::json &json) {
|
||||
if (!json.contains("hashes"))
|
||||
return false;
|
||||
|
||||
const auto &hashes = ContentRegistry::Hashes::impl::getHashes();
|
||||
|
||||
auto &hashFunctions = ProviderExtraData::get(provider).hashes.hashFunctions;
|
||||
for (const auto &hash : json["hashes"]) {
|
||||
if (!hash.contains("name") || !hash.contains("type"))
|
||||
continue;
|
||||
|
||||
for (const auto &newHash : hashes) {
|
||||
if (newHash->getUnlocalizedName() == hash["type"]) {
|
||||
|
||||
auto newFunction = newHash->create(hash["name"]);
|
||||
newFunction.getType()->load(hash["settings"]);
|
||||
|
||||
hashFunctions.push_back(std::move(newFunction));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewHashes::exportHashes(prv::Provider *provider, nlohmann::json &json) {
|
||||
json["hashes"] = nlohmann::json::array();
|
||||
size_t index = 0;
|
||||
for (const auto &hashFunction : ProviderExtraData::get(provider).hashes.hashFunctions) {
|
||||
json["hashes"][index] = {
|
||||
{ "name", hashFunction.getName() },
|
||||
{ "type", hashFunction.getType()->getUnlocalizedName() },
|
||||
{ "settings", hashFunction.getType()->store() }
|
||||
};
|
||||
index++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user