1
0
mirror of synced 2024-11-28 01:20:51 +01:00

tools: Added file shredder, splitter and combiner

This commit is contained in:
WerWolv 2021-09-22 17:56:06 +02:00
parent 5601aab043
commit e57481b87c
13 changed files with 600 additions and 31 deletions

View File

@ -17,11 +17,6 @@ set(PLUGINS
# example
)
# List extra magic databases to compile here
set(MAGICDBS
magic_dbs/nintendo_magic
)
findLibraries()
detectOS()
@ -45,10 +40,10 @@ add_subdirectory(plugins/libimhex)
# Add include directories
include_directories(include ${MBEDTLS_INCLUDE_DIRS} ${CAPSTONE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS} ${Python_INCLUDE_DIRS})
if (USE_SYSTEM_LLVM)
include_directories(include ${LLVM_INCLUDE_DIRS})
include_directories(${LLVM_INCLUDE_DIRS})
endif()
if (USE_SYSTEM_YARA)
include_directories(include ${YARA_INCLUDE_DIRS})
include_directories(${YARA_INCLUDE_DIRS})
endif()
enable_testing()

View File

@ -5,9 +5,13 @@
#include <hex/helpers/shared_data.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/file.hpp>
#include <hex/helpers/literals.hpp>
#include <regex>
#include <algorithm>
#include <chrono>
#include <random>
#include <regex>
#include <llvm/Demangle/Demangle.h>
#include "math_evaluator.hpp"
@ -24,6 +28,7 @@ namespace hex::plugin::builtin {
using namespace std::literals::string_literals;
using namespace std::literals::chrono_literals;
using namespace hex::literals;
int updateStringSizeCallback(ImGuiInputTextCallbackData *data) {
auto &mathInput = *static_cast<std::string*>(data->UserData);
@ -666,6 +671,371 @@ namespace hex::plugin::builtin {
}
}
void drawFileToolShredder() {
static bool shredding = false;
static auto selectedFile = []{ std::string s; s.reserve(0x1000); return s; }();
static bool fastMode = false;
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.warning"_lang);
ImGui::NewLine();
if (ImGui::BeginChild("settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 4 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
ImGui::BeginDisabled(shredding);
{
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.input"_lang);
ImGui::SameLine();
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &selectedFile);
ImGui::SameLine();
if (ImGui::Button("...")) {
hex::openFileBrowser("hex.builtin.tools.file_tools.shredder.picker"_lang, DialogMode::Open, {}, [](const std::string &path) {
selectedFile = path;
});
}
ImGui::Checkbox("hex.builtin.tools.file_tools.shredder.fast"_lang, &fastMode);
}
ImGui::EndDisabled();
}
ImGui::EndChild();
if (shredding)
ImGui::TextSpinner("hex.builtin.tools.file_tools.shredder.shredding"_lang);
else {
ImGui::BeginDisabled(selectedFile.empty());
{
if (ImGui::Button("hex.builtin.tools.file_tools.shredder.shred"_lang)) {
shredding = true;
std::thread([]{
ON_SCOPE_EXIT { shredding = false; selectedFile.clear(); };
File file(selectedFile, File::Mode::Write);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.shredder.error.open"_lang);
return;
}
std::vector<std::array<u8, 3>> overwritePattern;
if (fastMode) {
/* Should be sufficient for modern disks */
overwritePattern.push_back({ 0x00, 0x00, 0x00 });
overwritePattern.push_back({ 0xFF, 0xFF, 0xFF });
}
else {
/* Gutmann's method. Secure for magnetic storage */
std::random_device rd;
std::uniform_int_distribution<u8> dist(0x00, 0xFF);
/* Fill fixed patterns */
overwritePattern = {
{}, {}, {}, {},
{ 0x55, 0x55, 0x55 }, { 0xAA, 0xAA, 0xAA }, { 0x92, 0x49, 0x24 }, { 0x49, 0x24, 0x92 },
{ 0x24, 0x92, 0x49 }, { 0x00, 0x00, 0x00 }, { 0x11, 0x11, 0x11 }, { 0x22, 0x22, 0x22 },
{ 0x33, 0x33, 0x44 }, { 0x55, 0x55, 0x55 }, { 0x66, 0x66, 0x66 }, { 0x77, 0x77, 0x77 },
{ 0x88, 0x88, 0x88 }, { 0x99, 0x99, 0x99 }, { 0xAA, 0xAA, 0xAA }, { 0xBB, 0xBB, 0xBB },
{ 0xCC, 0xCC, 0xCC }, { 0xDD, 0xDD, 0xDD }, { 0xEE, 0xEE, 0xEE }, { 0xFF, 0xFF, 0xFF },
{ 0x92, 0x49, 0x24 }, { 0x49, 0x24, 0x92 }, { 0x24, 0x92, 0x49 }, { 0x6D, 0xB6, 0xDB },
{ 0xB6, 0xDB, 0x6D }, { 0xBD, 0x6D, 0xB6 },
{}, {}, {}, {}
};
/* Fill random patterns */
for (u8 i = 0; i < 4; i++)
overwritePattern[i] = { dist(rd), dist(rd), dist(rd) };
for (u8 i = 0; i < 4; i++)
overwritePattern[overwritePattern.size() - 1 - i] = { dist(rd), dist(rd), dist(rd) };
}
size_t fileSize = file.getSize();
for (const auto &pattern : overwritePattern) {
for (u64 offset = 0; offset < fileSize; offset += 3) {
file.write(pattern.data(), std::min(pattern.size(), fileSize - offset));
}
file.flush();
}
file.remove();
View::showMessagePopup("hex.builtin.tools.file_tools.shredder.success"_lang);
}).detach();
}
}
ImGui::EndDisabled();
}
}
void drawFileToolSplitter() {
std::array sizeText = {
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.zip100"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.zip200"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.cdrom650"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.cdrom700"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.fat32"_lang,
(const char*)"hex.builtin.tools.file_tools.splitter.sizes.custom"_lang
};
std::array<u64, sizeText.size()> sizes = {
1200_KiB,
1400_KiB,
100_MiB,
200_MiB,
650_MiB,
700_MiB,
4_GiB,
1
};
static bool splitting = false;
static auto selectedFile = []{ std::string s; s.reserve(0x1000); return s; }();
static auto baseOutputPath = []{ std::string s; s.reserve(0x1000); return s; }();
static u64 splitSize = sizes[0];
static int selectedItem = 0;
if (ImGui::BeginChild("split_settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 7 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
ImGui::BeginDisabled(splitting);
{
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.input"_lang);
ImGui::SameLine();
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &selectedFile);
ImGui::SameLine();
if (ImGui::Button("...##input")) {
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.input"_lang, DialogMode::Open, {}, [](const std::string &path) {
selectedFile = path;
});
}
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.output"_lang);
ImGui::SameLine();
ImGui::InputText("##base_path", baseOutputPath.data(), baseOutputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &baseOutputPath);
ImGui::SameLine();
if (ImGui::Button("...##output")) {
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.output"_lang, DialogMode::Save, {}, [](const std::string &path) {
baseOutputPath = path;
});
}
ImGui::Separator();
if (ImGui::Combo("###part_size", &selectedItem, sizeText.data(), sizeText.size())) {
splitSize = sizes[selectedItem];
}
}
ImGui::EndDisabled();
ImGui::BeginDisabled(splitting || selectedItem != sizes.size() - 1);
{
ImGui::InputScalar("###custom_size", ImGuiDataType_U64, &splitSize);
ImGui::SameLine();
ImGui::TextUnformatted("Bytes");
}
ImGui::EndDisabled();
}
ImGui::EndChild();
ImGui::BeginDisabled(selectedFile.empty() || baseOutputPath.empty() || splitSize == 0);
{
if (splitting)
ImGui::TextSpinner("hex.builtin.tools.file_tools.splitter.splitting"_lang);
else {
if (ImGui::Button("hex.builtin.tools.file_tools.splitter.split"_lang)) {
splitting = true;
std::thread([]{
ON_SCOPE_EXIT { splitting = false; selectedFile.clear(); baseOutputPath.clear(); };
File file(selectedFile, File::Mode::Read);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.error.open"_lang);
return;
}
if (file.getSize() < splitSize) {
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.error.size"_lang);
return;
}
u32 index = 1;
for (u64 offset = 0; offset < file.getSize(); offset += splitSize) {
File partFile(baseOutputPath + hex::format(".{:05}", index), File::Mode::Create);
if (!partFile.isValid()) {
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.splitter.error.create"_lang, index));
return;
}
constexpr auto BufferSize = 0xFF'FFFF;
for (u64 partOffset = 0; partOffset < splitSize; partOffset += BufferSize) {
partFile.write(file.readBytes(std::min<u64>(BufferSize, splitSize - partOffset)));
partFile.flush();
}
index++;
}
View::showMessagePopup("hex.builtin.tools.file_tools.splitter.success"_lang);
}).detach();
}
}
}
ImGui::EndDisabled();
}
void drawFileToolCombiner() {
static bool combining = false;
static std::vector<std::string> files;
static auto outputPath = []{ std::string s; s.reserve(0x1000); return s; }();
static s32 selectedIndex;
if (ImGui::BeginTable("files_table", 2, ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("file list", ImGuiTableColumnFlags_NoHeaderLabel, 10);
ImGui::TableSetupColumn("buttons", ImGuiTableColumnFlags_NoHeaderLabel, 1);
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::BeginListBox("##files", { -FLT_MIN, 10 * ImGui::GetTextLineHeightWithSpacing() })) {
s32 index = 0;
for (auto &file : files) {
if (ImGui::Selectable(std::filesystem::path(file).filename().string().c_str(), index == selectedIndex))
selectedIndex = index;
index++;
}
ImGui::EndListBox();
}
ImGui::TableNextColumn();
ImGui::BeginDisabled(selectedIndex <= 0) ;
{
if (ImGui::ArrowButton("move_up", ImGuiDir_Up)) {
std::iter_swap(files.begin() + selectedIndex, files.begin() + selectedIndex - 1);
selectedIndex--;
}
}
ImGui::EndDisabled();
ImGui::BeginDisabled(files.empty() || selectedIndex >= files.size() - 1) ;
{
if (ImGui::ArrowButton("move_down", ImGuiDir_Down)) {
std::iter_swap(files.begin() + selectedIndex, files.begin() + selectedIndex + 1);
selectedIndex++;
}
}
ImGui::EndDisabled();
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::BeginDisabled(combining);
{
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.add"_lang)) {
hex::openFileBrowser("hex.builtin.tools.file_tools.combiner.add.picker"_lang, DialogMode::Open, {}, [](const std::string &path) {
files.push_back(path);
});
}
ImGui::SameLine();
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.delete"_lang)) {
files.erase(files.begin() + selectedIndex);
selectedIndex--;
}
ImGui::SameLine();
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.clear"_lang)) {
files.clear();
}
}
ImGui::EndDisabled();
ImGui::EndTable();
}
ImGui::BeginDisabled(combining);
{
ImGui::TextUnformatted("hex.builtin.tools.file_tools.combiner.output"_lang);
ImGui::SameLine();
ImGui::InputText("##output_path", outputPath.data(), outputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &outputPath);
ImGui::SameLine();
if (ImGui::Button("...")) {
hex::openFileBrowser("hex.builtin.tools.file_tools.combiner.output.picker"_lang, DialogMode::Save, {}, [](const std::string &path) {
outputPath = path;
});
}
}
ImGui::EndDisabled();
ImGui::BeginDisabled(files.empty() || outputPath.empty());
{
if (combining)
ImGui::TextSpinner("hex.builtin.tools.file_tools.combiner.combining"_lang);
else {
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.combine"_lang)) {
combining = true;
std::thread([]{
ON_SCOPE_EXIT { combining = false; };
File output(outputPath, File::Mode::Create);
if (!output.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.combiner.error.open_output"_lang);
return;
}
for (const auto &file : files) {
File input(file, File::Mode::Read);
if (!input.isValid()) {
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.combiner.open_input"_lang, std::filesystem::path(file).filename().string()));
return;
}
constexpr auto BufferSize = 0xFF'FFFF;
auto inputSize = input.getSize();
for (u64 inputOffset = 0; inputOffset < inputSize; inputOffset += BufferSize) {
output.write(input.readBytes(std::min<u64>(BufferSize, inputSize - inputOffset)));
output.flush();
}
}
files.clear();
selectedIndex = 0;
outputPath.clear();
View::showMessagePopup("hex.builtin.tools.file_tools.combiner.success"_lang);
}).detach();
}
}
}
ImGui::EndDisabled();
}
void drawFileTools() {
if (ImGui::BeginTabBar("file_tools_tabs")) {
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.shredder"_lang)) {
drawFileToolShredder();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.splitter"_lang)) {
drawFileToolSplitter();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("hex.builtin.tools.file_tools.combiner"_lang)) {
drawFileToolCombiner();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
void registerToolEntries() {
ContentRegistry::Tools::add("hex.builtin.tools.demangler", drawDemangler);
ContentRegistry::Tools::add("hex.builtin.tools.ascii_table", drawASCIITable);
@ -676,6 +1046,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Tools::add("hex.builtin.tools.permissions", drawPermissionsCalculator);
ContentRegistry::Tools::add("hex.builtin.tools.file_uploader", drawFileUploader);
ContentRegistry::Tools::add("hex.builtin.tools.wiki_explain", drawWikiExplainer);
ContentRegistry::Tools::add("hex.builtin.tools.file_tools", drawFileTools);
}
}

View File

@ -578,6 +578,47 @@ namespace hex::plugin::builtin {
{ "hex.builtin.tools.wiki_explain.search", "Suchen" },
{ "hex.builtin.tools.wiki_explain.results", "Resultate" },
{ "hex.builtin.tools.wiki_explain.invalid_response", "Ungültige Antwort von Wikipedia!" },
{ "hex.builtin.tools.file_tools", "File Tools" },
{ "hex.builtin.tools.file_tools.shredder", "Schredder" },
{ "hex.builtin.tools.file_tools.shredder.warning", "Dieses Tool zerstört eine Datei UNWIEDERRUFLICH. Mit Vorsicht verwenden" },
{ "hex.builtin.tools.file_tools.shredder.input", "Datei zum schreddern" },
{ "hex.builtin.tools.file_tools.shredder.picker", "Öffne Datei zum schreddern" },
{ "hex.builtin.tools.file_tools.shredder.fast", "Schneller Modus" },
{ "hex.builtin.tools.file_tools.shredder.shredding", "Schreddert..." },
{ "hex.builtin.tools.file_tools.shredder.shred", "Schreddern" },
{ "hex.builtin.tools.file_tools.shredder.error.open", "Öffnen der ausgewählten Datei fehlgeschlagen" },
{ "hex.builtin.tools.file_tools.shredder.success", "Datei erfolgreich geschreddert!" },
{ "hex.builtin.tools.file_tools.splitter", "Splitter" },
{ "hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy", "\" Floppy disk (1200KiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy", "\" Floppy disk (1400KiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.zip100", "Zip 100 Disk (100MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.zip200", "Zip 200 Disk (200MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom650", "CD-ROM (650MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom700", "CD-ROM (700MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.fat32", "FAT32 (4GiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.custom", "Benutzerdefiniert" },
{ "hex.builtin.tools.file_tools.splitter.input", "Zu splittende Datei " },
{ "hex.builtin.tools.file_tools.splitter.picker.input", "Zu splittende Datei öffnen" },
{ "hex.builtin.tools.file_tools.splitter.output", "Ziel Pfad" },
{ "hex.builtin.tools.file_tools.splitter.picker.output", "Ziel Pfad setzen" },
{ "hex.builtin.tools.file_tools.splitter.splitting", "Splittet..." },
{ "hex.builtin.tools.file_tools.splitter.split", "Splitten" },
{ "hex.builtin.tools.file_tools.splitter.error.open", "Öffnen der ausgewählten Datei fehlgeschlagen" },
{ "hex.builtin.tools.file_tools.splitter.error.size", "Datei ist kleiner als Zielgrösse" },
{ "hex.builtin.tools.file_tools.splitter.error.create", "Erstellen der Teildatei {0} fehlgeschlagen" },
{ "hex.builtin.tools.file_tools.splitter.success", "Datei erfolgreich gesplittet!" },
{ "hex.builtin.tools.file_tools.combiner", "Kombinierer" },
{ "hex.builtin.tools.file_tools.combiner.add", "Hinzufügen..." },
{ "hex.builtin.tools.file_tools.combiner.add.picker", "Datei hinzufügen" },
{ "hex.builtin.tools.file_tools.combiner.delete", "Entfernen" },
{ "hex.builtin.tools.file_tools.combiner.clear", "Alle entfernen" },
{ "hex.builtin.tools.file_tools.combiner.output", "Zieldatei " },
{ "hex.builtin.tools.file_tools.combiner.output.picker", "Ziel Pfad setzen" },
{ "hex.builtin.tools.file_tools.combiner.combining", "Kombiniert..." },
{ "hex.builtin.tools.file_tools.combiner.combine", "Kombinieren" },
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Erstellen der Zieldatei fehlgeschlagen" },
{ "hex.builtin.tools.file_tools.combiner.open_input", "Öffnen der Inputdatei {0} fehlgeschlagen" },
{ "hex.builtin.tools.file_tools.combiner.success", "Dateien erfolgreich kombiniert!" },
{ "hex.builtin.setting.imhex", "ImHex" },
{ "hex.builtin.setting.imhex.recent_files", "Kürzlich geöffnete Dateien" },

View File

@ -579,6 +579,47 @@ namespace hex::plugin::builtin {
{ "hex.builtin.tools.wiki_explain.search", "Search" },
{ "hex.builtin.tools.wiki_explain.results", "Results" },
{ "hex.builtin.tools.wiki_explain.invalid_response", "Invalid response from Wikipedia!" },
{ "hex.builtin.tools.file_tools", "File Tools" },
{ "hex.builtin.tools.file_tools.shredder", "Shredder" },
{ "hex.builtin.tools.file_tools.shredder.warning", "This tool IRRECOVERABLY destroys a file. Use with caution" },
{ "hex.builtin.tools.file_tools.shredder.input", "File to shred " },
{ "hex.builtin.tools.file_tools.shredder.picker", "Open File to Shred" },
{ "hex.builtin.tools.file_tools.shredder.fast", "Fast Mode" },
{ "hex.builtin.tools.file_tools.shredder.shredding", "Shredding..." },
{ "hex.builtin.tools.file_tools.shredder.shred", "Shred" },
{ "hex.builtin.tools.file_tools.shredder.error.open", "Failed to open selected file!" },
{ "hex.builtin.tools.file_tools.shredder.success", "Shredded successfully!" },
{ "hex.builtin.tools.file_tools.splitter", "Splitter" },
{ "hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy", "\" Floppy disk (1200KiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy", "\" Floppy disk (1400KiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.zip100", "Zip 100 Disk (100MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.zip200", "Zip 200 Disk (200MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom650", "CD-ROM (650MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom700", "CD-ROM (700MiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.fat32", "FAT32 (4GiB)" },
{ "hex.builtin.tools.file_tools.splitter.sizes.custom", "Custom" },
{ "hex.builtin.tools.file_tools.splitter.input", "File to split " },
{ "hex.builtin.tools.file_tools.splitter.picker.input", "Open File to split" },
{ "hex.builtin.tools.file_tools.splitter.output", "Output path " },
{ "hex.builtin.tools.file_tools.splitter.picker.output", "Set base path" },
{ "hex.builtin.tools.file_tools.splitter.picker.splitting", "Splitting..." },
{ "hex.builtin.tools.file_tools.splitter.picker.split", "Split" },
{ "hex.builtin.tools.file_tools.splitter.picker.error.open", "Failed to open selected file!" },
{ "hex.builtin.tools.file_tools.splitter.picker.error.size", "File is smaller than part size" },
{ "hex.builtin.tools.file_tools.splitter.picker.error.create", "Failed to create part file {0}" },
{ "hex.builtin.tools.file_tools.splitter.picker.success", "File split successfully!" },
{ "hex.builtin.tools.file_tools.combiner", "Combiner" },
{ "hex.builtin.tools.file_tools.combiner.add", "Add..." },
{ "hex.builtin.tools.file_tools.combiner.add.picker", "Add file" },
{ "hex.builtin.tools.file_tools.combiner.delete", "Delete" },
{ "hex.builtin.tools.file_tools.combiner.clear", "Clear" },
{ "hex.builtin.tools.file_tools.combiner.output", "Output file " },
{ "hex.builtin.tools.file_tools.combiner.output.picker", "Set output base path" },
{ "hex.builtin.tools.file_tools.combiner.combining", "Combining..." },
{ "hex.builtin.tools.file_tools.combiner.combine", "Combine" },
{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Failed to create output file" },
{ "hex.builtin.tools.file_tools.combiner.open_input", "Failed to open input file {0}" },
{ "hex.builtin.tools.file_tools.combiner.success", "Files combined successfully!" },
{ "hex.builtin.setting.imhex", "ImHex" },
{ "hex.builtin.setting.imhex.recent_files", "Recent Files" },

View File

@ -577,6 +577,47 @@ namespace hex::plugin::builtin {
{ "hex.builtin.tools.wiki_explain.search", "Cerca" },
{ "hex.builtin.tools.wiki_explain.results", "Risultati" },
{ "hex.builtin.tools.wiki_explain.invalid_response", "Risposta non valida da Wikipedia!" },
//{ "hex.builtin.tools.file_tools", "File Tools" },
//{ "hex.builtin.tools.file_tools.shredder", "Shredder" },
//{ "hex.builtin.tools.file_tools.shredder.warning", "This tool IRRECOVERABLY destroys a file. Use with caution" },
//{ "hex.builtin.tools.file_tools.shredder.input", "File to shred " },
//{ "hex.builtin.tools.file_tools.shredder.picker", "Open File to Shred" },
//{ "hex.builtin.tools.file_tools.shredder.fast", "Fast Mode" },
//{ "hex.builtin.tools.file_tools.shredder.shredding", "Shredding..." },
//{ "hex.builtin.tools.file_tools.shredder.shred", "Shred" },
//{ "hex.builtin.tools.file_tools.shredder.error.open", "Failed to open selected file!" },
//{ "hex.builtin.tools.file_tools.shredder.success", "Shredded successfully!" },
//{ "hex.builtin.tools.file_tools.splitter", "Splitter" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy", "5¼\" Floppy disk (1200KiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy", "3½\" Floppy disk (1400KiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.zip100", "Zip 100 Disk (100MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.zip200", "Zip 200 Disk (200MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom650", "CD-ROM (650MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom700", "CD-ROM (700MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.fat32", "FAT32 (4GiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.custom", "Custom" },
//{ "hex.builtin.tools.file_tools.splitter.input", "File to split " },
//{ "hex.builtin.tools.file_tools.splitter.picker.input", "Open File to split" },
//{ "hex.builtin.tools.file_tools.splitter.output", "Output path " },
//{ "hex.builtin.tools.file_tools.splitter.picker.output", "Set base path" },
//{ "hex.builtin.tools.file_tools.splitter.picker.splitting", "Splitting..." },
//{ "hex.builtin.tools.file_tools.splitter.picker.split", "Split" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.open", "Failed to open selected file!" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.size", "File is smaller than part size" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.create", "Failed to create part file {0}" },
//{ "hex.builtin.tools.file_tools.splitter.picker.success", "File split successfully!" },
//{ "hex.builtin.tools.file_tools.combiner", "Combiner" },
//{ "hex.builtin.tools.file_tools.combiner.add", "Add..." },
//{ "hex.builtin.tools.file_tools.combiner.add.picker", "Add file" },
//{ "hex.builtin.tools.file_tools.combiner.delete", "Delete" },
//{ "hex.builtin.tools.file_tools.combiner.clear", "Clear" },
//{ "hex.builtin.tools.file_tools.combiner.output", "Output file " },
//{ "hex.builtin.tools.file_tools.combiner.output.picker", "Set output base path" },
//{ "hex.builtin.tools.file_tools.combiner.combining", "Combining..." },
//{ "hex.builtin.tools.file_tools.combiner.combine", "Combine" },
//{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Failed to create output file" },
//{ "hex.builtin.tools.file_tools.combiner.open_input", "Failed to open input file {0}" },
//{ "hex.builtin.tools.file_tools.combiner.success", "Files combined successfully!" },
{ "hex.builtin.setting.imhex", "ImHex" },
{ "hex.builtin.setting.imhex.recent_files", "File recenti" },

View File

@ -579,6 +579,47 @@ namespace hex::plugin::builtin {
{ "hex.builtin.tools.wiki_explain.search", "搜索" },
{ "hex.builtin.tools.wiki_explain.results", "结果" },
{ "hex.builtin.tools.wiki_explain.invalid_response", "接收到来自Wikipedia的无效响应" },
//{ "hex.builtin.tools.file_tools", "File Tools" },
//{ "hex.builtin.tools.file_tools.shredder", "Shredder" },
//{ "hex.builtin.tools.file_tools.shredder.warning", "This tool IRRECOVERABLY destroys a file. Use with caution" },
//{ "hex.builtin.tools.file_tools.shredder.input", "File to shred " },
//{ "hex.builtin.tools.file_tools.shredder.picker", "Open File to Shred" },
//{ "hex.builtin.tools.file_tools.shredder.fast", "Fast Mode" },
//{ "hex.builtin.tools.file_tools.shredder.shredding", "Shredding..." },
//{ "hex.builtin.tools.file_tools.shredder.shred", "Shred" },
//{ "hex.builtin.tools.file_tools.shredder.error.open", "Failed to open selected file!" },
//{ "hex.builtin.tools.file_tools.shredder.success", "Shredded successfully!" },
//{ "hex.builtin.tools.file_tools.splitter", "Splitter" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.5_75_floppy", "5¼\" Floppy disk (1200KiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.3_5_floppy", "3½\" Floppy disk (1400KiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.zip100", "Zip 100 Disk (100MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.zip200", "Zip 200 Disk (200MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom650", "CD-ROM (650MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.cdrom700", "CD-ROM (700MiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.fat32", "FAT32 (4GiB)" },
//{ "hex.builtin.tools.file_tools.splitter.sizes.custom", "Custom" },
//{ "hex.builtin.tools.file_tools.splitter.input", "File to split " },
//{ "hex.builtin.tools.file_tools.splitter.picker.input", "Open File to split" },
//{ "hex.builtin.tools.file_tools.splitter.output", "Output path " },
//{ "hex.builtin.tools.file_tools.splitter.picker.output", "Set base path" },
//{ "hex.builtin.tools.file_tools.splitter.picker.splitting", "Splitting..." },
//{ "hex.builtin.tools.file_tools.splitter.picker.split", "Split" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.open", "Failed to open selected file!" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.size", "File is smaller than part size" },
//{ "hex.builtin.tools.file_tools.splitter.picker.error.create", "Failed to create part file {0}" },
//{ "hex.builtin.tools.file_tools.splitter.picker.success", "File split successfully!" },
//{ "hex.builtin.tools.file_tools.combiner", "Combiner" },
//{ "hex.builtin.tools.file_tools.combiner.add", "Add..." },
//{ "hex.builtin.tools.file_tools.combiner.add.picker", "Add file" },
//{ "hex.builtin.tools.file_tools.combiner.delete", "Delete" },
//{ "hex.builtin.tools.file_tools.combiner.clear", "Clear" },
//{ "hex.builtin.tools.file_tools.combiner.output", "Output file " },
//{ "hex.builtin.tools.file_tools.combiner.output.picker", "Set output base path" },
//{ "hex.builtin.tools.file_tools.combiner.combining", "Combining..." },
//{ "hex.builtin.tools.file_tools.combiner.combine", "Combine" },
//{ "hex.builtin.tools.file_tools.combiner.error.open_output", "Failed to create output file" },
//{ "hex.builtin.tools.file_tools.combiner.open_input", "Failed to open input file {0}" },
//{ "hex.builtin.tools.file_tools.combiner.success", "Files combined successfully!" },
{ "hex.builtin.setting.imhex", "ImHex" },
{ "hex.builtin.setting.imhex.recent_files", "最近文件" },

View File

@ -30,9 +30,10 @@ namespace hex {
~File();
bool isValid() const { return this->m_file != nullptr; }
[[nodiscard]] bool isValid() const { return this->m_file != nullptr; }
void seek(u64 offset);
void close();
size_t readBuffer(u8 *buffer, size_t size);
std::vector<u8> readBytes(size_t numBytes = 0);
@ -42,13 +43,18 @@ namespace hex {
void write(const std::vector<u8> &bytes);
void write(const std::string &string);
size_t getSize() const;
[[nodiscard]] size_t getSize() const;
void setSize(u64 size);
void flush();
void remove();
auto getHandle() { return this->m_file; }
const std::string& getPath() { return this->m_path; }
private:
FILE *m_file;
std::string m_path;
};
}

View File

@ -8,12 +8,12 @@ namespace hex::literals {
return bytes;
}
constexpr static inline unsigned long long operator ""_kiB(unsigned long long kiB) noexcept {
constexpr static inline unsigned long long operator ""_KiB(unsigned long long kiB) noexcept {
return operator ""_Bytes(kiB * 1024);
}
constexpr static inline unsigned long long operator ""_MiB(unsigned long long MiB) noexcept {
return operator ""_kiB(MiB * 1024);
return operator ""_KiB(MiB * 1024);
}
constexpr static inline unsigned long long operator ""_GiB(unsigned long long GiB) noexcept {

View File

@ -65,7 +65,7 @@ namespace hex {
static std::vector<ContentRegistry::Tools::Entry> toolsEntries;
static std::vector<ContentRegistry::DataInspector::Entry> dataInspectorEntries;
static u32 patternPaletteOffset;
static std::string errorPopupMessage;
static std::string popupMessage;
static std::list<ImHexApi::Bookmarks::Entry> bookmarkEntries;
static std::vector<pl::PatternData*> patternData;

View File

@ -42,6 +42,7 @@ namespace hex {
static void drawCommonInterfaces();
static void showMessagePopup(const std::string &message);
static void showErrorPopup(const std::string &errorMessage);
static void showFatalPopup(const std::string &errorMessage);
@ -53,10 +54,8 @@ namespace hex {
[[nodiscard]] const std::string& getUnlocalizedName() const;
protected:
void discardNavigationRequests();
void confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function<void()> &leftButtonFn, const std::function<void()> &rightButtonFn);
static void confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function<void()> &leftButtonFn, const std::function<void()> &rightButtonFn);
static void discardNavigationRequests();
static inline std::string toWindowName(const std::string &unlocalizedName) {
return LangEntry(unlocalizedName) + "###" + unlocalizedName;

View File

@ -3,7 +3,7 @@
namespace hex {
File::File(const std::string &path, Mode mode) {
File::File(const std::string &path, Mode mode) : m_path(path) {
if (mode == File::Mode::Read)
this->m_file = fopen64(path.c_str(), "rb");
else if (mode == File::Mode::Write)
@ -23,14 +23,20 @@ namespace hex {
}
File::~File() {
if (isValid())
fclose(this->m_file);
this->close();
}
void File::seek(u64 offset) {
fseeko64(this->m_file, offset, SEEK_SET);
}
void File::close() {
if (isValid()) {
fclose(this->m_file);
this->m_file = nullptr;
}
}
size_t File::readBuffer(u8 *buffer, size_t size) {
if (!isValid()) return 0;
@ -41,7 +47,7 @@ namespace hex {
if (!isValid()) return { };
std::vector<u8> bytes(numBytes ?: getSize());
auto bytesRead = fread(bytes.data(), bytes.size(), 1, this->m_file);
auto bytesRead = fread(bytes.data(), 1, bytes.size(), this->m_file);
bytes.resize(bytesRead);
@ -63,7 +69,7 @@ namespace hex {
void File::write(const std::vector<u8> &bytes) {
if (!isValid()) return;
fwrite(bytes.data(), bytes.size(), 1, this->m_file);
fwrite(bytes.data(), 1, bytes.size(), this->m_file);
}
void File::write(const std::string &string) {
@ -89,4 +95,13 @@ namespace hex {
ftruncate64(fileno(this->m_file), size);
}
void File::flush() {
fflush(this->m_file);
}
void File::remove() {
this->close();
std::remove(this->m_path.c_str());
}
}

View File

@ -17,7 +17,7 @@ namespace hex {
std::vector<ContentRegistry::Tools::Entry> SharedData::toolsEntries;
std::vector<ContentRegistry::DataInspector::Entry> SharedData::dataInspectorEntries;
u32 SharedData::patternPaletteOffset;
std::string SharedData::errorPopupMessage;
std::string SharedData::popupMessage;
std::list<ImHexApi::Bookmarks::Entry> SharedData::bookmarkEntries;
std::vector<pl::PatternData*> SharedData::patternData;

View File

@ -24,8 +24,9 @@ namespace hex {
}
void View::drawCommonInterfaces() {
if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s", SharedData::errorPopupMessage.c_str());
ImGui::SetNextWindowSize(ImVec2(200, 100) * SharedData::globalScale);
if (ImGui::BeginPopupModal("hex.common.info"_lang)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
@ -34,8 +35,20 @@ namespace hex {
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("hex.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s", SharedData::errorPopupMessage.c_str());
ImGui::SetNextWindowSize(ImVec2(200, 100) * SharedData::globalScale);
if (ImGui::BeginPopupModal("hex.common.error"_lang)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
ImGui::SetNextWindowSize(ImVec2(200, 100) * SharedData::globalScale);
if (ImGui::BeginPopupModal("hex.common.fatal"_lang, nullptr)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) {
@ -47,14 +60,20 @@ namespace hex {
}
}
void View::showMessagePopup(const std::string &message) {
SharedData::popupMessage = message;
View::doLater([] { ImGui::OpenPopup("hex.common.info"_lang); });
}
void View::showErrorPopup(const std::string &errorMessage) {
SharedData::errorPopupMessage = errorMessage;
SharedData::popupMessage = errorMessage;
View::doLater([] { ImGui::OpenPopup("hex.common.error"_lang); });
}
void View::showFatalPopup(const std::string &errorMessage) {
SharedData::errorPopupMessage = errorMessage;
SharedData::popupMessage = errorMessage;
View::doLater([] { ImGui::OpenPopup("hex.common.fatal"_lang); });
}
@ -64,11 +83,11 @@ namespace hex {
}
ImVec2 View::getMinSize() {
return ImVec2(480, 720);
return ImVec2(480, 720) * SharedData::globalScale;
}
ImVec2 View::getMaxSize() {
return ImVec2(FLT_MAX, FLT_MAX);
return { FLT_MAX, FLT_MAX };
}