diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aab3a339..6f48f9251 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/plugins/builtin/source/content/tools_entries.cpp b/plugins/builtin/source/content/tools_entries.cpp index 086003a72..1e7cff57e 100644 --- a/plugins/builtin/source/content/tools_entries.cpp +++ b/plugins/builtin/source/content/tools_entries.cpp @@ -5,9 +5,13 @@ #include #include #include +#include +#include -#include +#include #include +#include +#include #include #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(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> 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 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 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(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 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(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); } } \ No newline at end of file diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index 1746349c8..5d9b4cbee 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -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", "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", "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" }, diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index daa789e52..df08740cf 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -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", "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", "Recent Files" }, diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index 78d2324f4..2fa5e3a86 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -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" }, diff --git a/plugins/builtin/source/lang/zh_CN.cpp b/plugins/builtin/source/lang/zh_CN.cpp index b5e8f1811..e5e524a15 100644 --- a/plugins/builtin/source/lang/zh_CN.cpp +++ b/plugins/builtin/source/lang/zh_CN.cpp @@ -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", "最近文件" }, diff --git a/plugins/libimhex/include/hex/helpers/file.hpp b/plugins/libimhex/include/hex/helpers/file.hpp index 51d2d6ad5..d19f1f290 100644 --- a/plugins/libimhex/include/hex/helpers/file.hpp +++ b/plugins/libimhex/include/hex/helpers/file.hpp @@ -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 readBytes(size_t numBytes = 0); @@ -42,13 +43,18 @@ namespace hex { void write(const std::vector &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; }; } \ No newline at end of file diff --git a/plugins/libimhex/include/hex/helpers/literals.hpp b/plugins/libimhex/include/hex/helpers/literals.hpp index 6d1e5908d..334b9bb94 100644 --- a/plugins/libimhex/include/hex/helpers/literals.hpp +++ b/plugins/libimhex/include/hex/helpers/literals.hpp @@ -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 { diff --git a/plugins/libimhex/include/hex/helpers/shared_data.hpp b/plugins/libimhex/include/hex/helpers/shared_data.hpp index f78d008b9..f0c628f0f 100644 --- a/plugins/libimhex/include/hex/helpers/shared_data.hpp +++ b/plugins/libimhex/include/hex/helpers/shared_data.hpp @@ -65,7 +65,7 @@ namespace hex { static std::vector toolsEntries; static std::vector dataInspectorEntries; static u32 patternPaletteOffset; - static std::string errorPopupMessage; + static std::string popupMessage; static std::list bookmarkEntries; static std::vector patternData; diff --git a/plugins/libimhex/include/hex/views/view.hpp b/plugins/libimhex/include/hex/views/view.hpp index f875a6eb4..d3abf368f 100644 --- a/plugins/libimhex/include/hex/views/view.hpp +++ b/plugins/libimhex/include/hex/views/view.hpp @@ -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 &leftButtonFn, const std::function &rightButtonFn); + static void confirmButtons(const std::string &textLeft, const std::string &textRight, const std::function &leftButtonFn, const std::function &rightButtonFn); + static void discardNavigationRequests(); static inline std::string toWindowName(const std::string &unlocalizedName) { return LangEntry(unlocalizedName) + "###" + unlocalizedName; diff --git a/plugins/libimhex/source/helpers/file.cpp b/plugins/libimhex/source/helpers/file.cpp index bce8ce739..11cb92de9 100644 --- a/plugins/libimhex/source/helpers/file.cpp +++ b/plugins/libimhex/source/helpers/file.cpp @@ -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 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 &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()); + } + } \ No newline at end of file diff --git a/plugins/libimhex/source/helpers/shared_data.cpp b/plugins/libimhex/source/helpers/shared_data.cpp index c8263c887..4ef5f12c1 100644 --- a/plugins/libimhex/source/helpers/shared_data.cpp +++ b/plugins/libimhex/source/helpers/shared_data.cpp @@ -17,7 +17,7 @@ namespace hex { std::vector SharedData::toolsEntries; std::vector SharedData::dataInspectorEntries; u32 SharedData::patternPaletteOffset; - std::string SharedData::errorPopupMessage; + std::string SharedData::popupMessage; std::list SharedData::bookmarkEntries; std::vector SharedData::patternData; diff --git a/plugins/libimhex/source/views/view.cpp b/plugins/libimhex/source/views/view.cpp index dd2201c35..50d69378a 100644 --- a/plugins/libimhex/source/views/view.cpp +++ b/plugins/libimhex/source/views/view.cpp @@ -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 }; }