tools: Added Anonfiles uploader
This commit is contained in:
parent
c56159da89
commit
3138d2c4a2
@ -1,6 +1,9 @@
|
|||||||
#include <hex/plugin.hpp>
|
#include <hex/plugin.hpp>
|
||||||
|
|
||||||
|
#include <hex/helpers/net.hpp>
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include <llvm/Demangle/Demangle.h>
|
#include <llvm/Demangle/Demangle.h>
|
||||||
#include "math_evaluator.hpp"
|
#include "math_evaluator.hpp"
|
||||||
@ -9,6 +12,8 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
void drawDemangler() {
|
void drawDemangler() {
|
||||||
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
|
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
|
||||||
static std::string demangledName;
|
static std::string demangledName;
|
||||||
@ -399,6 +404,98 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawFileUploader() {
|
||||||
|
struct UploadedFile {
|
||||||
|
std::string fileName, link, size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static hex::Net net;
|
||||||
|
static std::future<Response<std::string>> uploadProcess;
|
||||||
|
static std::filesystem::path currFile;
|
||||||
|
static std::vector<UploadedFile> links;
|
||||||
|
|
||||||
|
bool uploading = uploadProcess.valid() && uploadProcess.wait_for(0s) != std::future_status::ready;
|
||||||
|
|
||||||
|
ImGui::Header("hex.builtin.tools.file_uploader.control"_lang, true);
|
||||||
|
if (!uploading) {
|
||||||
|
if (ImGui::Button("hex.builtin.tools.file_uploader.upload"_lang)) {
|
||||||
|
hex::openFileBrowser("hex.builtin.tools.file_uploader.done"_lang, DialogMode::Open, { }, [&](auto path){
|
||||||
|
uploadProcess = net.uploadFile("https://api.anonfiles.com/upload", path);
|
||||||
|
currFile = path;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ImGui::Button("hex.common.cancel"_lang)) {
|
||||||
|
net.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::ProgressBar(net.getProgress(), ImVec2(0, 0), uploading ? nullptr : "Done!");
|
||||||
|
|
||||||
|
ImGui::Header("hex.builtin.tools.file_uploader.recent"_lang);
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("##links", 3, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg, ImVec2(0, 400))) {
|
||||||
|
ImGui::TableSetupScrollFreeze(0, 1);
|
||||||
|
ImGui::TableSetupColumn("hex.common.file"_lang);
|
||||||
|
ImGui::TableSetupColumn("hex.common.link"_lang);
|
||||||
|
ImGui::TableSetupColumn("hex.common.size"_lang);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
ImGuiListClipper clipper;
|
||||||
|
clipper.Begin(links.size());
|
||||||
|
|
||||||
|
while (clipper.Step()) {
|
||||||
|
for (s32 i = clipper.DisplayEnd - 1; i >= clipper.DisplayStart; i--) {
|
||||||
|
auto &[fileName, link, size] = links[i];
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(fileName.c_str());
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (ImGui::Hyperlink(link.c_str())) {
|
||||||
|
if (ImGui::GetMergedKeyModFlags() == ImGuiKeyModFlags_Ctrl)
|
||||||
|
hex::openWebpage(link);
|
||||||
|
else
|
||||||
|
ImGui::SetClipboardText(link.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::InfoTooltip("hex.builtin.tools.file_uploader.tooltip"_lang);
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(size.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clipper.End();
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uploadProcess.valid() && uploadProcess.wait_for(0s) == std::future_status::ready) {
|
||||||
|
auto response = uploadProcess.get();
|
||||||
|
if (response.code == 200) {
|
||||||
|
try {
|
||||||
|
auto json = nlohmann::json::parse(response.body);
|
||||||
|
links.push_back({
|
||||||
|
currFile.filename().string(),
|
||||||
|
json["data"]["file"]["url"]["short"],
|
||||||
|
json["data"]["file"]["metadata"]["size"]["readable"]
|
||||||
|
});
|
||||||
|
} catch (...) {
|
||||||
|
View::showErrorPopup("hex.builtin.tools.file_uploader.invalid_response"_lang);
|
||||||
|
}
|
||||||
|
} else if (response.code == 0) {
|
||||||
|
// Canceled by user, no action needed
|
||||||
|
} else View::showErrorPopup(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.code));
|
||||||
|
|
||||||
|
uploadProcess = { };
|
||||||
|
currFile.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void registerToolEntries() {
|
void registerToolEntries() {
|
||||||
ContentRegistry::Tools::add("hex.builtin.tools.demangler", drawDemangler);
|
ContentRegistry::Tools::add("hex.builtin.tools.demangler", drawDemangler);
|
||||||
ContentRegistry::Tools::add("hex.builtin.tools.ascii_table", drawASCIITable);
|
ContentRegistry::Tools::add("hex.builtin.tools.ascii_table", drawASCIITable);
|
||||||
@ -407,6 +504,7 @@ namespace hex::plugin::builtin {
|
|||||||
ContentRegistry::Tools::add("hex.builtin.tools.calc", drawMathEvaluator);
|
ContentRegistry::Tools::add("hex.builtin.tools.calc", drawMathEvaluator);
|
||||||
ContentRegistry::Tools::add("hex.builtin.tools.base_converter", drawBaseConverter);
|
ContentRegistry::Tools::add("hex.builtin.tools.base_converter", drawBaseConverter);
|
||||||
ContentRegistry::Tools::add("hex.builtin.tools.permissions", drawPermissionsCalculator);
|
ContentRegistry::Tools::add("hex.builtin.tools.permissions", drawPermissionsCalculator);
|
||||||
|
ContentRegistry::Tools::add("hex.builtin.tools.file_uploader", drawFileUploader);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -60,7 +60,7 @@ namespace hex::plugin::builtin {
|
|||||||
// Save file as
|
// Save file as
|
||||||
ImGui::Disabled([&provider] {
|
ImGui::Disabled([&provider] {
|
||||||
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||||
View::openFileBrowser("hex.view.hexeditor.save_as"_lang, View::DialogMode::Save, { }, [&provider](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [&provider](auto path) {
|
||||||
provider->saveAs(path);
|
provider->saveAs(path);
|
||||||
});
|
});
|
||||||
}, provider == nullptr || !provider->isSavable());
|
}, provider == nullptr || !provider->isSavable());
|
||||||
|
@ -76,6 +76,8 @@ namespace hex::plugin::builtin {
|
|||||||
{ "hex.common.set", "Setzen" },
|
{ "hex.common.set", "Setzen" },
|
||||||
{ "hex.common.close", "Schliessen" },
|
{ "hex.common.close", "Schliessen" },
|
||||||
{ "hex.common.dont_show_again", "Nicht mehr anzeigen" },
|
{ "hex.common.dont_show_again", "Nicht mehr anzeigen" },
|
||||||
|
{ "hex.common.link", "Link" },
|
||||||
|
{ "hex.common.file", "Datei" },
|
||||||
|
|
||||||
{ "hex.view.bookmarks.name", "Lesezeichen" },
|
{ "hex.view.bookmarks.name", "Lesezeichen" },
|
||||||
{ "hex.view.bookmarks.default_title", "Lesezeichen [0x{0:X} - 0x{1:X}]" },
|
{ "hex.view.bookmarks.default_title", "Lesezeichen [0x{0:X} - 0x{1:X}]" },
|
||||||
@ -538,6 +540,14 @@ namespace hex::plugin::builtin {
|
|||||||
{ "hex.builtin.tools.permissions.setuid_error", "User benötigt execute Rechte, damit setuid bit gilt!" },
|
{ "hex.builtin.tools.permissions.setuid_error", "User benötigt execute Rechte, damit setuid bit gilt!" },
|
||||||
{ "hex.builtin.tools.permissions.setgid_error", "Group benötigt execute Rechte, damit setgid bit gilt!" },
|
{ "hex.builtin.tools.permissions.setgid_error", "Group benötigt execute Rechte, damit setgid bit gilt!" },
|
||||||
{ "hex.builtin.tools.permissions.sticky_error", "Other benötigt execute Rechte, damit sticky bit gilt!" },
|
{ "hex.builtin.tools.permissions.sticky_error", "Other benötigt execute Rechte, damit sticky bit gilt!" },
|
||||||
|
{ "hex.builtin.tools.file_uploader", "File Uploader" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.control", "Einstellungen" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.upload", "Upload" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.done", "Fertig!" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.recent", "Letzte Uploads" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.tooltip", "Klicken zum Kopieren\nCTRL + Klicken zum öffnen" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.invalid_response", "Ungültige Antwort von Anonfiles!"_lang },
|
||||||
|
{ "hex.builtin.tools.file_uploader.error", "Dateiupload fehlgeschlagen\n\nError Code: {0}"_lang },
|
||||||
|
|
||||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||||
{ "hex.builtin.setting.imhex.recent_files", "Kürzlich geöffnete Dateien" },
|
{ "hex.builtin.setting.imhex.recent_files", "Kürzlich geöffnete Dateien" },
|
||||||
|
@ -76,6 +76,8 @@ namespace hex::plugin::builtin {
|
|||||||
{ "hex.common.set", "Set" },
|
{ "hex.common.set", "Set" },
|
||||||
{ "hex.common.close", "Close" },
|
{ "hex.common.close", "Close" },
|
||||||
{ "hex.common.dont_show_again", "Don't show again" },
|
{ "hex.common.dont_show_again", "Don't show again" },
|
||||||
|
{ "hex.common.link", "Link" },
|
||||||
|
{ "hex.common.file", "File" },
|
||||||
|
|
||||||
{ "hex.view.bookmarks.name", "Bookmarks" },
|
{ "hex.view.bookmarks.name", "Bookmarks" },
|
||||||
{ "hex.view.bookmarks.default_title", "Bookmark [0x{0:X} - 0x{1:X}]" },
|
{ "hex.view.bookmarks.default_title", "Bookmark [0x{0:X} - 0x{1:X}]" },
|
||||||
@ -538,6 +540,15 @@ namespace hex::plugin::builtin {
|
|||||||
{ "hex.builtin.tools.permissions.setuid_error", "User must have execute rights for setuid bit to apply!" },
|
{ "hex.builtin.tools.permissions.setuid_error", "User must have execute rights for setuid bit to apply!" },
|
||||||
{ "hex.builtin.tools.permissions.setgid_error", "Group must have execute rights for setgid bit to apply!" },
|
{ "hex.builtin.tools.permissions.setgid_error", "Group must have execute rights for setgid bit to apply!" },
|
||||||
{ "hex.builtin.tools.permissions.sticky_error", "Other must have execute rights for sticky bit to apply!" },
|
{ "hex.builtin.tools.permissions.sticky_error", "Other must have execute rights for sticky bit to apply!" },
|
||||||
|
{ "hex.builtin.tools.file_uploader", "File Uploader" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.control", "Control" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.upload", "Upload" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.done", "Done!" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.recent", "Recent Uploads" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.tooltip", "Click to copy\nCTRL + Click to open" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.invalid_response", "Invalid response from Anonfiles!" },
|
||||||
|
{ "hex.builtin.tools.file_uploader.error", "Failed to upload file!\n\nError Code: {0}" },
|
||||||
|
|
||||||
|
|
||||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||||
{ "hex.builtin.setting.imhex.recent_files", "Recent Files" },
|
{ "hex.builtin.setting.imhex.recent_files", "Recent Files" },
|
||||||
|
@ -75,6 +75,8 @@ namespace hex::plugin::builtin {
|
|||||||
{ "hex.common.set", "Imposta" },
|
{ "hex.common.set", "Imposta" },
|
||||||
//{ "hex.common.close", "Close" },
|
//{ "hex.common.close", "Close" },
|
||||||
//{ "hex.common.dont_show_again", "Don't show again" },
|
//{ "hex.common.dont_show_again", "Don't show again" },
|
||||||
|
//{ "hex.common.link", "Link" },
|
||||||
|
//{ "hex.common.file", "File" },
|
||||||
|
|
||||||
{ "hex.view.bookmarks.name", "Segnalibri" },
|
{ "hex.view.bookmarks.name", "Segnalibri" },
|
||||||
{ "hex.view.bookmarks.default_title", "Segnalibro [0x{0:X} - 0x{1:X}]" },
|
{ "hex.view.bookmarks.default_title", "Segnalibro [0x{0:X} - 0x{1:X}]" },
|
||||||
@ -537,6 +539,14 @@ namespace hex::plugin::builtin {
|
|||||||
//{ "hex.builtin.tools.permissions.setuid_error", "User must have execute rights for setuid bit to apply!" },
|
//{ "hex.builtin.tools.permissions.setuid_error", "User must have execute rights for setuid bit to apply!" },
|
||||||
//{ "hex.builtin.tools.permissions.setgid_error", "Group must have execute rights for setgid bit to apply!" },
|
//{ "hex.builtin.tools.permissions.setgid_error", "Group must have execute rights for setgid bit to apply!" },
|
||||||
//{ "hex.builtin.tools.permissions.sticky_error", "Other must have execute rights for sticky bit to apply!" },
|
//{ "hex.builtin.tools.permissions.sticky_error", "Other must have execute rights for sticky bit to apply!" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader", "File Uploader" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.control", "Control" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.upload", "Upload" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.done", "Done!" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.recent", "Recent Uploads" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.tooltip", "Click to copy\nCTRL + Click to open" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.invalid_response", "Invalid response from Anonfiles!" },
|
||||||
|
//{ "hex.builtin.tools.file_uploader.error", "Failed to upload file!\n\nError Code: {0}" },
|
||||||
|
|
||||||
{ "hex.builtin.setting.imhex", "ImHex" },
|
{ "hex.builtin.setting.imhex", "ImHex" },
|
||||||
{ "hex.builtin.setting.imhex.recent_files", "File recenti" },
|
{ "hex.builtin.setting.imhex.recent_files", "File recenti" },
|
||||||
|
@ -2,17 +2,20 @@
|
|||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Response {
|
struct Response {
|
||||||
u32 code;
|
s32 code;
|
||||||
T response;
|
T body;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Net {
|
class Net {
|
||||||
@ -20,11 +23,28 @@ namespace hex {
|
|||||||
Net();
|
Net();
|
||||||
~Net();
|
~Net();
|
||||||
|
|
||||||
Response<std::string> getString(std::string_view url);
|
std::future<Response<std::string>> getString(const std::string &url);
|
||||||
Response<nlohmann::json> getJson(std::string_view url);
|
std::future<Response<nlohmann::json>> getJson(const std::string &url);
|
||||||
|
|
||||||
|
std::future<Response<std::string>> uploadFile(const std::string &url, const std::filesystem::path &filePath);
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
float getProgress() const { return this->m_progress; }
|
||||||
|
|
||||||
|
void cancel() { this->m_shouldCancel = true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setCommonSettings(std::string &response, const std::string &url, const std::map<std::string, std::string> &extraHeaders = { }, const std::string &body = { });
|
||||||
|
std::optional<s32> execute();
|
||||||
|
|
||||||
|
friend int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
||||||
private:
|
private:
|
||||||
CURL *m_ctx;
|
CURL *m_ctx;
|
||||||
|
struct curl_slist *m_headers = nullptr;
|
||||||
|
|
||||||
|
std::mutex m_transmissionActive;
|
||||||
|
float m_progress = 0.0F;
|
||||||
|
bool m_shouldCancel = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -15,11 +15,13 @@
|
|||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#include <winsock.h>
|
#include <winsock2.h>
|
||||||
#else
|
#else
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <nfd.hpp>
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
#define off64_t off_t
|
#define off64_t off_t
|
||||||
#define fopen64 fopen
|
#define fopen64 fopen
|
||||||
@ -331,30 +333,87 @@ namespace hex {
|
|||||||
|
|
||||||
std::vector<std::string> getPath(ImHexPath path);
|
std::vector<std::string> getPath(ImHexPath path);
|
||||||
|
|
||||||
#define SCOPE_GUARD ::hex::ScopeGuardOnExit() + [&]()
|
enum class DialogMode {
|
||||||
#define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_) = SCOPE_GUARD
|
Open,
|
||||||
template<class F>
|
Save,
|
||||||
class ScopeGuard {
|
Folder
|
||||||
private:
|
|
||||||
F m_func;
|
|
||||||
bool m_active;
|
|
||||||
public:
|
|
||||||
constexpr ScopeGuard(F func) : m_func(std::move(func)), m_active(true) { }
|
|
||||||
~ScopeGuard() { if (this->m_active) { this->m_func(); } }
|
|
||||||
void release() { this->m_active = false; }
|
|
||||||
|
|
||||||
ScopeGuard(ScopeGuard &&other) noexcept : m_func(std::move(other.m_func)), m_active(other.m_active) {
|
|
||||||
other.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopeGuard& operator=(ScopeGuard &&) = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ScopeGuardOnExit { };
|
void openFileBrowser(std::string_view title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::string)> &callback);
|
||||||
|
|
||||||
|
namespace scope_guard {
|
||||||
|
|
||||||
|
#define SCOPE_GUARD ::hex::scope_guard::ScopeGuardOnExit() + [&]()
|
||||||
|
#define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_) = SCOPE_GUARD
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
class ScopeGuard {
|
||||||
|
private:
|
||||||
|
F m_func;
|
||||||
|
bool m_active;
|
||||||
|
public:
|
||||||
|
constexpr ScopeGuard(F func) : m_func(std::move(func)), m_active(true) { }
|
||||||
|
~ScopeGuard() { if (this->m_active) { this->m_func(); } }
|
||||||
|
void release() { this->m_active = false; }
|
||||||
|
|
||||||
|
ScopeGuard(ScopeGuard &&other) noexcept : m_func(std::move(other.m_func)), m_active(other.m_active) {
|
||||||
|
other.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopeGuard& operator=(ScopeGuard &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ScopeGuardOnExit { };
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
|
||||||
|
return ScopeGuard<F>(std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace first_time_exec {
|
||||||
|
|
||||||
|
#define FIRST_TIME static auto ANONYMOUS_VARIABLE(FIRST_TIME_) = ::hex::first_time_exec::FirstTimeExecutor() + [&]()
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
class FirstTimeExecute {
|
||||||
|
public:
|
||||||
|
constexpr FirstTimeExecute(F func) { func(); }
|
||||||
|
|
||||||
|
FirstTimeExecute& operator=(FirstTimeExecute &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FirstTimeExecutor { };
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
constexpr FirstTimeExecute<F> operator+(FirstTimeExecutor, F&& f) {
|
||||||
|
return FirstTimeExecute<F>(std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace final_cleanup {
|
||||||
|
|
||||||
|
#define FINAL_CLEANUP static auto ANONYMOUS_VARIABLE(ON_EXIT_) = ::hex::final_cleanup::FinalCleanupExecutor() + [&]()
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
class FinalCleanupExecute {
|
||||||
|
F m_func;
|
||||||
|
public:
|
||||||
|
constexpr FinalCleanupExecute(F func) : m_func(func) { }
|
||||||
|
constexpr ~FinalCleanupExecute() { this->m_func(); }
|
||||||
|
|
||||||
|
FinalCleanupExecute& operator=(FinalCleanupExecute &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FinalCleanupExecutor { };
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
constexpr FinalCleanupExecute<F> operator+(FinalCleanupExecutor, F&& f) {
|
||||||
|
return FinalCleanupExecute<F>(std::forward<F>(f));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
constexpr ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) {
|
|
||||||
return ScopeGuard<F>(std::forward<F>(f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Region {
|
struct Region {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include <fontawesome_font.h>
|
#include <fontawesome_font.h>
|
||||||
#include <codicons_font.h>
|
#include <codicons_font.h>
|
||||||
#include <nfd.hpp>
|
|
||||||
|
|
||||||
#include <hex/api/imhex_api.hpp>
|
#include <hex/api/imhex_api.hpp>
|
||||||
#include <hex/api/event.hpp>
|
#include <hex/api/event.hpp>
|
||||||
@ -32,13 +31,6 @@ namespace hex {
|
|||||||
virtual bool isAvailable();
|
virtual bool isAvailable();
|
||||||
virtual bool shouldProcess() { return this->isAvailable() && this->getWindowOpenState(); }
|
virtual bool shouldProcess() { return this->isAvailable() && this->getWindowOpenState(); }
|
||||||
|
|
||||||
enum class DialogMode {
|
|
||||||
Open,
|
|
||||||
Save,
|
|
||||||
Folder
|
|
||||||
};
|
|
||||||
|
|
||||||
static void openFileBrowser(std::string_view title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::string)> &callback);
|
|
||||||
static void doLater(std::function<void()> &&function);
|
static void doLater(std::function<void()> &&function);
|
||||||
static std::vector<std::function<void()>>& getDeferedCalls();
|
static std::vector<std::function<void()>>& getDeferedCalls();
|
||||||
|
|
||||||
|
@ -3,10 +3,9 @@
|
|||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include <mbedtls/ssl.h>
|
#include <mbedtls/ssl.h>
|
||||||
#include <mbedtls/x509.h>
|
|
||||||
#include <mbedtls/x509_crt.h>
|
|
||||||
#include <mbedtls/error.h>
|
#include <mbedtls/error.h>
|
||||||
|
|
||||||
#include <hex/resources.hpp>
|
#include <hex/resources.hpp>
|
||||||
@ -14,21 +13,33 @@
|
|||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
Net::Net() {
|
Net::Net() {
|
||||||
curl_global_sslset(CURLSSLBACKEND_MBEDTLS, nullptr, nullptr);
|
FIRST_TIME {
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
curl_global_sslset(CURLSSLBACKEND_MBEDTLS, nullptr, nullptr);
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
};
|
||||||
|
|
||||||
|
FINAL_CLEANUP {
|
||||||
|
curl_global_cleanup();
|
||||||
|
};
|
||||||
|
|
||||||
this->m_ctx = curl_easy_init();
|
this->m_ctx = curl_easy_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Net::~Net() {
|
Net::~Net() {
|
||||||
curl_easy_cleanup(this->m_ctx);
|
curl_easy_cleanup(this->m_ctx);
|
||||||
curl_global_cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t writeToString(void *contents, size_t size, size_t nmemb, void *userp){
|
static size_t writeToString(void *contents, size_t size, size_t nmemb, void *userdata){
|
||||||
static_cast<std::string*>(userp)->append((char*)contents, size * nmemb);
|
static_cast<std::string*>(userdata)->append((char*)contents, size * nmemb);
|
||||||
return size * nmemb;
|
return size * nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t readFromFile(void *contents, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
FILE *file = static_cast<FILE*>(userdata);
|
||||||
|
|
||||||
|
return fread(contents, size, nmemb, file);
|
||||||
|
}
|
||||||
|
|
||||||
static CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userdata) {
|
static CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userdata) {
|
||||||
auto* cfg = static_cast<mbedtls_ssl_config*>(sslctx);
|
auto* cfg = static_cast<mbedtls_ssl_config*>(sslctx);
|
||||||
|
|
||||||
@ -41,9 +52,21 @@ namespace hex {
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setCommonSettings(CURL *ctx, std::string &response, std::string_view path, const std::map<std::string, std::string> &extraHeaders, const std::string &body) {
|
int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||||
struct curl_slist *headers = nullptr;
|
auto &net = *static_cast<Net*>(contents);
|
||||||
headers = curl_slist_append(headers, "Cache-Control: no-cache");
|
|
||||||
|
if (dlTotal > 0)
|
||||||
|
net.m_progress = float(dlNow) / dlTotal;
|
||||||
|
else if (ulTotal > 0)
|
||||||
|
net.m_progress = float(ulNow) / ulTotal;
|
||||||
|
else
|
||||||
|
net.m_progress = 0.0F;
|
||||||
|
|
||||||
|
return net.m_shouldCancel ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Net::setCommonSettings(std::string &response, const std::string &url, const std::map<std::string, std::string> &extraHeaders, const std::string &body) {
|
||||||
|
this->m_headers = curl_slist_append(this->m_headers, "Cache-Control: no-cache");
|
||||||
|
|
||||||
if (!extraHeaders.empty())
|
if (!extraHeaders.empty())
|
||||||
for (const auto &[key, value] : extraHeaders) {
|
for (const auto &[key, value] : extraHeaders) {
|
||||||
@ -51,65 +74,131 @@ namespace hex {
|
|||||||
entry += ": ";
|
entry += ": ";
|
||||||
entry += value;
|
entry += value;
|
||||||
|
|
||||||
headers = curl_slist_append(headers, entry.c_str());
|
this->m_headers = curl_slist_append(this->m_headers, entry.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!body.empty())
|
if (!body.empty())
|
||||||
curl_easy_setopt(ctx, CURLOPT_POSTFIELDS, body.c_str());
|
curl_easy_setopt(this->m_ctx, CURLOPT_POSTFIELDS, body.c_str());
|
||||||
|
|
||||||
curl_easy_setopt(ctx, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
curl_easy_setopt(this->m_ctx, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||||
curl_easy_setopt(ctx, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
|
curl_easy_setopt(this->m_ctx, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
curl_easy_setopt(ctx, CURLOPT_URL, path.data());
|
curl_easy_setopt(this->m_ctx, CURLOPT_URL, url.c_str());
|
||||||
curl_easy_setopt(ctx, CURLOPT_FOLLOWLOCATION, 1L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
curl_easy_setopt(ctx, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(this->m_ctx, CURLOPT_HTTPHEADER, this->m_headers);
|
||||||
curl_easy_setopt(ctx, CURLOPT_USERAGENT, "ImHex/1.0");
|
curl_easy_setopt(this->m_ctx, CURLOPT_USERAGENT, "ImHex/1.0");
|
||||||
curl_easy_setopt(ctx, CURLOPT_DEFAULT_PROTOCOL, "https");
|
curl_easy_setopt(this->m_ctx, CURLOPT_DEFAULT_PROTOCOL, "https");
|
||||||
curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, writeToString);
|
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEFUNCTION, writeToString);
|
||||||
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 1L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||||
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYHOST, 2L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||||
curl_easy_setopt(ctx, CURLOPT_CAINFO, nullptr);
|
curl_easy_setopt(this->m_ctx, CURLOPT_CAINFO, nullptr);
|
||||||
curl_easy_setopt(ctx, CURLOPT_CAPATH, nullptr);
|
curl_easy_setopt(this->m_ctx, CURLOPT_CAPATH, nullptr);
|
||||||
curl_easy_setopt(ctx, CURLOPT_SSLCERTTYPE, "PEM");
|
curl_easy_setopt(this->m_ctx, CURLOPT_SSLCERTTYPE, "PEM");
|
||||||
curl_easy_setopt(ctx, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
|
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
|
||||||
curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &response);
|
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEDATA, &response);
|
||||||
curl_easy_setopt(ctx, CURLOPT_TIMEOUT_MS, 2000L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_TIMEOUT_MS, 0L);
|
||||||
curl_easy_setopt(ctx, CURLOPT_CONNECTTIMEOUT_MS, 2000L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_CONNECTTIMEOUT_MS, 2000L);
|
||||||
curl_easy_setopt(ctx, CURLOPT_NOPROGRESS, 1L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_XFERINFODATA, this);
|
||||||
curl_easy_setopt(ctx, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(this->m_ctx, CURLOPT_XFERINFOFUNCTION, progressCallback);
|
||||||
|
curl_easy_setopt(this->m_ctx, CURLOPT_NOSIGNAL, 1L);
|
||||||
|
curl_easy_setopt(this->m_ctx, CURLOPT_NOPROGRESS, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response<std::string> Net::getString(std::string_view url) {
|
std::optional<s32> Net::execute() {
|
||||||
std::string response;
|
|
||||||
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
|
|
||||||
setCommonSettings(this->m_ctx, response, url, {}, "");
|
|
||||||
|
|
||||||
CURLcode result = curl_easy_perform(this->m_ctx);
|
CURLcode result = curl_easy_perform(this->m_ctx);
|
||||||
|
|
||||||
u32 responseCode = 0;
|
s32 responseCode = 0;
|
||||||
curl_easy_getinfo(this->m_ctx, CURLINFO_RESPONSE_CODE, &responseCode);
|
curl_easy_getinfo(this->m_ctx, CURLINFO_RESPONSE_CODE, &responseCode);
|
||||||
|
|
||||||
|
curl_slist_free_all(this->m_headers);
|
||||||
|
this->m_headers = nullptr;
|
||||||
|
this->m_progress = 0.0F;
|
||||||
|
this->m_shouldCancel = false;
|
||||||
|
|
||||||
if (result != CURLE_OK)
|
if (result != CURLE_OK)
|
||||||
return Response<std::string>{ responseCode, "" };
|
return { };
|
||||||
else
|
else
|
||||||
return Response<std::string>{ responseCode, response };
|
return responseCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response<nlohmann::json> Net::getJson(std::string_view url) {
|
std::future<Response<std::string>> Net::getString(const std::string &url) {
|
||||||
std::string response;
|
this->m_transmissionActive.lock();
|
||||||
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
|
return std::async(std::launch::async, [=, this]{
|
||||||
setCommonSettings(this->m_ctx, response, url, {}, "");
|
std::string response;
|
||||||
|
|
||||||
CURLcode result = curl_easy_perform(this->m_ctx);
|
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
||||||
|
|
||||||
u32 responseCode = 0;
|
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
|
||||||
curl_easy_getinfo(this->m_ctx, CURLINFO_RESPONSE_CODE, &responseCode);
|
setCommonSettings(response, url);
|
||||||
|
|
||||||
if (result != CURLE_OK)
|
auto responseCode = execute();
|
||||||
return Response<nlohmann::json>{ responseCode, { } };
|
|
||||||
else
|
return Response<std::string> { responseCode.value_or(0), response };
|
||||||
return Response<nlohmann::json>{ responseCode, nlohmann::json::parse(response) };
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<Response<nlohmann::json>> Net::getJson(const std::string &url) {
|
||||||
|
this->m_transmissionActive.lock();
|
||||||
|
|
||||||
|
return std::async(std::launch::async, [=, this]{
|
||||||
|
std::string response;
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
||||||
|
|
||||||
|
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
|
||||||
|
setCommonSettings(response, url, {});
|
||||||
|
|
||||||
|
auto responseCode = execute();
|
||||||
|
|
||||||
|
return Response<nlohmann::json> { responseCode.value_or(0), nlohmann::json::parse(response) };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::future<Response<std::string>> Net::uploadFile(const std::string &url, const std::filesystem::path &filePath) {
|
||||||
|
this->m_transmissionActive.lock();
|
||||||
|
|
||||||
|
return std::async(std::launch::async, [=, this] {
|
||||||
|
std::string response;
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
||||||
|
|
||||||
|
FILE *file = fopen(filePath.string().c_str(), "rb");
|
||||||
|
if (file == nullptr)
|
||||||
|
return Response<std::string> { 400, { } };
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
size_t fileSize = ftell(file);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
curl_mime *mime = curl_mime_init(this->m_ctx);
|
||||||
|
curl_mimepart *part = curl_mime_addpart(mime);
|
||||||
|
|
||||||
|
auto fileName = filePath.filename().string();
|
||||||
|
curl_mime_data_cb(part, fileSize,
|
||||||
|
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
|
||||||
|
auto file = static_cast<FILE*>(arg);
|
||||||
|
return fread(buffer, size, nitems, file);
|
||||||
|
},
|
||||||
|
[](void *arg, curl_off_t offset, int origin) -> int {
|
||||||
|
auto file = static_cast<FILE*>(arg);
|
||||||
|
fseek(file, offset, origin);
|
||||||
|
return CURL_SEEKFUNC_OK;
|
||||||
|
},
|
||||||
|
[](void *arg) {
|
||||||
|
auto file = static_cast<FILE*>(arg);
|
||||||
|
fclose(file);
|
||||||
|
}, file);
|
||||||
|
curl_mime_filename(part, fileName.c_str());
|
||||||
|
curl_mime_name(part, "file");
|
||||||
|
|
||||||
|
setCommonSettings(response, url);
|
||||||
|
curl_easy_setopt(this->m_ctx, CURLOPT_MIMEPOST, mime);
|
||||||
|
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "POST");
|
||||||
|
|
||||||
|
auto responseCode = execute();
|
||||||
|
|
||||||
|
return Response<std::string> { responseCode.value_or(0), response };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -296,4 +296,30 @@ namespace hex {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openFileBrowser(std::string_view title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::string)> &callback) {
|
||||||
|
NFD::Init();
|
||||||
|
|
||||||
|
nfdchar_t *outPath;
|
||||||
|
nfdresult_t result;
|
||||||
|
switch (mode) {
|
||||||
|
case DialogMode::Open:
|
||||||
|
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), nullptr);
|
||||||
|
break;
|
||||||
|
case DialogMode::Save:
|
||||||
|
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), nullptr);
|
||||||
|
break;
|
||||||
|
case DialogMode::Folder:
|
||||||
|
result = NFD::PickFolder(outPath, nullptr);
|
||||||
|
break;
|
||||||
|
default: __builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NFD_OKAY) {
|
||||||
|
callback(outPath);
|
||||||
|
NFD::FreePath(outPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
NFD::Quit();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -24,32 +24,6 @@ namespace hex {
|
|||||||
return SharedData::deferredCalls;
|
return SharedData::deferredCalls;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::openFileBrowser(std::string_view title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::string)> &callback) {
|
|
||||||
NFD::Init();
|
|
||||||
|
|
||||||
nfdchar_t *outPath;
|
|
||||||
nfdresult_t result;
|
|
||||||
switch (mode) {
|
|
||||||
case DialogMode::Open:
|
|
||||||
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), nullptr);
|
|
||||||
break;
|
|
||||||
case DialogMode::Save:
|
|
||||||
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), nullptr);
|
|
||||||
break;
|
|
||||||
case DialogMode::Folder:
|
|
||||||
result = NFD::PickFolder(outPath, nullptr);
|
|
||||||
break;
|
|
||||||
default: __builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == NFD_OKAY) {
|
|
||||||
callback(outPath);
|
|
||||||
NFD::FreePath(outPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
NFD::Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::drawCommonInterfaces() {
|
void View::drawCommonInterfaces() {
|
||||||
if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text("%s", SharedData::errorPopupMessage.c_str());
|
ImGui::Text("%s", SharedData::errorPopupMessage.c_str());
|
||||||
|
@ -31,15 +31,15 @@ namespace hex::init {
|
|||||||
static bool checkForUpdates() {
|
static bool checkForUpdates() {
|
||||||
hex::Net net;
|
hex::Net net;
|
||||||
|
|
||||||
auto releases = net.getJson("https://api.github.com/repos/WerWolv/ImHex/releases/latest");
|
auto releases = net.getJson("https://api.github.com/repos/WerWolv/ImHex/releases/latest").get();
|
||||||
if (releases.code != 200)
|
if (releases.code != 200)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!releases.response.contains("tag_name") || !releases.response["tag_name"].is_string())
|
if (!releases.body.contains("tag_name") || !releases.body["tag_name"].is_string())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto currVersion = "v" + std::string(IMHEX_VERSION).substr(0, 5);
|
auto currVersion = "v" + std::string(IMHEX_VERSION).substr(0, 5);
|
||||||
auto latestVersion = releases.response["tag_name"].get<std::string_view>();
|
auto latestVersion = releases.body["tag_name"].get<std::string_view>();
|
||||||
|
|
||||||
if (latestVersion != currVersion)
|
if (latestVersion != currVersion)
|
||||||
getInitArguments().push_back({ "update-available", latestVersion.data() });
|
getInitArguments().push_back({ "update-available", latestVersion.data() });
|
||||||
@ -50,11 +50,11 @@ namespace hex::init {
|
|||||||
static bool downloadInformation() {
|
static bool downloadInformation() {
|
||||||
hex::Net net;
|
hex::Net net;
|
||||||
|
|
||||||
auto tip = net.getString("https://api.werwolv.net/imhex/tip");
|
auto tip = net.getString("https://api.werwolv.net/imhex/tip").get();
|
||||||
if (tip.code != 200)
|
if (tip.code != 200)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
getInitArguments().push_back({ "tip-of-the-day", tip.response });
|
getInitArguments().push_back({ "tip-of-the-day", tip.body });
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ namespace hex {
|
|||||||
|
|
||||||
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
|
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
|
||||||
if (name == "Create File") {
|
if (name == "Create File") {
|
||||||
View::openFileBrowser("hex.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||||
if (!this->createFile(path)) {
|
if (!this->createFile(path)) {
|
||||||
View::showErrorPopup("hex.view.hexeditor.error.create"_lang);
|
View::showErrorPopup("hex.view.hexeditor.error.create"_lang);
|
||||||
return;
|
return;
|
||||||
@ -185,12 +185,12 @@ namespace hex {
|
|||||||
this->getWindowOpenState() = true;
|
this->getWindowOpenState() = true;
|
||||||
});
|
});
|
||||||
} else if (name == "Open File") {
|
} else if (name == "Open File") {
|
||||||
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
this->openFile(path);
|
this->openFile(path);
|
||||||
this->getWindowOpenState() = true;
|
this->getWindowOpenState() = true;
|
||||||
});
|
});
|
||||||
} else if (name == "Open Project") {
|
} else if (name == "Open Project") {
|
||||||
View::openFileBrowser("hex.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||||
ProjectFile::load(path);
|
ProjectFile::load(path);
|
||||||
EventManager::post<EventProjectFileLoad>();
|
EventManager::post<EventProjectFileLoad>();
|
||||||
this->getWindowOpenState() = true;
|
this->getWindowOpenState() = true;
|
||||||
@ -271,7 +271,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void saveAs() {
|
static void saveAs() {
|
||||||
View::openFileBrowser("hex.view.hexeditor.save_as"_lang, View::DialogMode::Save, { }, [](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [](auto path) {
|
||||||
auto provider = SharedData::currentProvider;
|
auto provider = SharedData::currentProvider;
|
||||||
provider->saveAs(path);
|
provider->saveAs(path);
|
||||||
});
|
});
|
||||||
@ -306,14 +306,14 @@ namespace hex {
|
|||||||
ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly);
|
ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("hex.view.hexeditor.script.script"_lang)) {
|
if (ImGui::Button("hex.view.hexeditor.script.script"_lang)) {
|
||||||
View::openFileBrowser("hex.view.hexeditor.script.script.title"_lang, DialogMode::Open, { { "Python Script", "py" } }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.script.script.title"_lang, DialogMode::Open, { { "Python Script", "py" } }, [this](auto path) {
|
||||||
this->m_loaderScriptScriptPath = path;
|
this->m_loaderScriptScriptPath = path;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly);
|
ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button("hex.view.hexeditor.script.file"_lang)) {
|
if (ImGui::Button("hex.view.hexeditor.script.file"_lang)) {
|
||||||
View::openFileBrowser("hex.view.hexeditor.script.file.title"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.script.file.title"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
this->m_loaderScriptFilePath = path;
|
this->m_loaderScriptFilePath = path;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -384,7 +384,7 @@ namespace hex {
|
|||||||
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) {
|
||||||
|
|
||||||
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
EventManager::post<EventFileDropped>(path);
|
EventManager::post<EventFileDropped>(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -416,7 +416,7 @@ namespace hex {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_project"_lang, "")) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_project"_lang, "")) {
|
||||||
View::openFileBrowser("hex.view.hexeditor.menu.file.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.menu.file.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||||
ProjectFile::load(path);
|
ProjectFile::load(path);
|
||||||
EventManager::post<EventProjectFileLoad>();
|
EventManager::post<EventProjectFileLoad>();
|
||||||
});
|
});
|
||||||
@ -424,7 +424,7 @@ namespace hex {
|
|||||||
|
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save_project"_lang, "", false, provider != nullptr && provider->isWritable())) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save_project"_lang, "", false, provider != nullptr && provider->isWritable())) {
|
||||||
if (ProjectFile::getProjectFilePath() == "") {
|
if (ProjectFile::getProjectFilePath() == "") {
|
||||||
View::openFileBrowser("hex.view.hexeditor.save_project"_lang, DialogMode::Save, { { "Project File", "hexproj" } }, [](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.save_project"_lang, DialogMode::Save, { { "Project File", "hexproj" } }, [](auto path) {
|
||||||
if (path.ends_with(".hexproj")) {
|
if (path.ends_with(".hexproj")) {
|
||||||
ProjectFile::store(path);
|
ProjectFile::store(path);
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.load_encoding_file"_lang)) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.load_encoding_file"_lang)) {
|
||||||
View::openFileBrowser("hex.view.hexeditor.load_enconding_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.load_enconding_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
this->m_currEncodingFile = EncodingFile(EncodingFile::Type::Thingy, path);
|
this->m_currEncodingFile = EncodingFile(EncodingFile::Type::Thingy, path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -448,7 +448,7 @@ namespace hex {
|
|||||||
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.import"_lang)) {
|
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.import"_lang)) {
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.base64"_lang)) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.base64"_lang)) {
|
||||||
|
|
||||||
View::openFileBrowser("hex.view.hexeditor.menu.file.import.base64"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.menu.file.import.base64"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
std::vector<u8> base64;
|
std::vector<u8> base64;
|
||||||
this->loadFromFile(path, base64);
|
this->loadFromFile(path, base64);
|
||||||
|
|
||||||
@ -468,7 +468,7 @@ namespace hex {
|
|||||||
|
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips"_lang)) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips"_lang)) {
|
||||||
|
|
||||||
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
auto patchData = hex::readFile(path);
|
auto patchData = hex::readFile(path);
|
||||||
auto patch = hex::loadIPSPatch(patchData);
|
auto patch = hex::loadIPSPatch(patchData);
|
||||||
|
|
||||||
@ -482,7 +482,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips32"_lang)) {
|
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips32"_lang)) {
|
||||||
View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||||
auto patchData = hex::readFile(path);
|
auto patchData = hex::readFile(path);
|
||||||
auto patch = hex::loadIPS32Patch(patchData);
|
auto patch = hex::loadIPS32Patch(patchData);
|
||||||
|
|
||||||
@ -512,7 +512,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->m_dataToSave = generateIPSPatch(patches);
|
this->m_dataToSave = generateIPSPatch(patches);
|
||||||
View::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||||
this->saveToFile(path, this->m_dataToSave);
|
this->saveToFile(path, this->m_dataToSave);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -525,7 +525,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->m_dataToSave = generateIPS32Patch(patches);
|
this->m_dataToSave = generateIPS32Patch(patches);
|
||||||
View::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
hex::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||||
this->saveToFile(path, this->m_dataToSave);
|
this->saveToFile(path, this->m_dataToSave);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ namespace hex {
|
|||||||
void ViewPattern::drawMenu() {
|
void ViewPattern::drawMenu() {
|
||||||
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
||||||
if (ImGui::MenuItem("hex.view.pattern.menu.file.load_pattern"_lang)) {
|
if (ImGui::MenuItem("hex.view.pattern.menu.file.load_pattern"_lang)) {
|
||||||
View::openFileBrowser("hex.view.pattern.open_pattern"_lang, DialogMode::Open, { { "Pattern File", "hexpat" } }, [this](auto path) {
|
hex::openFileBrowser("hex.view.pattern.open_pattern"_lang, DialogMode::Open, { { "Pattern File", "hexpat" } }, [this](auto path) {
|
||||||
this->loadPatternFile(path);
|
this->loadPatternFile(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user