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

tools: Added Anonfiles uploader

This commit is contained in:
WerWolv 2021-08-28 00:45:59 +02:00
parent c56159da89
commit 3138d2c4a2
14 changed files with 423 additions and 134 deletions

View File

@ -1,6 +1,9 @@
#include <hex/plugin.hpp>
#include <hex/helpers/net.hpp>
#include <regex>
#include <chrono>
#include <llvm/Demangle/Demangle.h>
#include "math_evaluator.hpp"
@ -9,6 +12,8 @@ namespace hex::plugin::builtin {
namespace {
using namespace std::literals::chrono_literals;
void drawDemangler() {
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
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() {
ContentRegistry::Tools::add("hex.builtin.tools.demangler", drawDemangler);
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.base_converter", drawBaseConverter);
ContentRegistry::Tools::add("hex.builtin.tools.permissions", drawPermissionsCalculator);
ContentRegistry::Tools::add("hex.builtin.tools.file_uploader", drawFileUploader);
}
}

View File

@ -60,7 +60,7 @@ namespace hex::plugin::builtin {
// Save file as
ImGui::Disabled([&provider] {
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 == nullptr || !provider->isSavable());

View File

@ -76,6 +76,8 @@ namespace hex::plugin::builtin {
{ "hex.common.set", "Setzen" },
{ "hex.common.close", "Schliessen" },
{ "hex.common.dont_show_again", "Nicht mehr anzeigen" },
{ "hex.common.link", "Link" },
{ "hex.common.file", "Datei" },
{ "hex.view.bookmarks.name", "Lesezeichen" },
{ "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.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.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.recent_files", "Kürzlich geöffnete Dateien" },

View File

@ -76,6 +76,8 @@ namespace hex::plugin::builtin {
{ "hex.common.set", "Set" },
{ "hex.common.close", "Close" },
{ "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.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.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.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.recent_files", "Recent Files" },

View File

@ -75,6 +75,8 @@ namespace hex::plugin::builtin {
{ "hex.common.set", "Imposta" },
//{ "hex.common.close", "Close" },
//{ "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.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.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.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.recent_files", "File recenti" },

View File

@ -2,17 +2,20 @@
#include <hex.hpp>
#include <future>
#include <string>
#include <filesystem>
#include <atomic>
#include <curl/curl.h>
#include <nlohmann/json.hpp>
#include <curl/curl.h>
namespace hex {
template<typename T>
struct Response {
u32 code;
T response;
s32 code;
T body;
};
class Net {
@ -20,11 +23,28 @@ namespace hex {
Net();
~Net();
Response<std::string> getString(std::string_view url);
Response<nlohmann::json> getJson(std::string_view url);
std::future<Response<std::string>> getString(const std::string &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:
CURL *m_ctx;
struct curl_slist *m_headers = nullptr;
std::mutex m_transmissionActive;
float m_progress = 0.0F;
bool m_shouldCancel = false;
};
}

View File

@ -15,11 +15,13 @@
#include <fmt/chrono.h>
#ifdef __MINGW32__
#include <winsock.h>
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <nfd.hpp>
#if defined(__APPLE__) || defined(__FreeBSD__)
#define off64_t off_t
#define fopen64 fopen
@ -331,30 +333,87 @@ namespace hex {
std::vector<std::string> getPath(ImHexPath path);
#define SCOPE_GUARD ::hex::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 DialogMode {
Open,
Save,
Folder
};
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 {

View File

@ -7,7 +7,6 @@
#include <fontawesome_font.h>
#include <codicons_font.h>
#include <nfd.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/event.hpp>
@ -32,13 +31,6 @@ namespace hex {
virtual bool isAvailable();
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 std::vector<std::function<void()>>& getDeferedCalls();

View File

@ -3,10 +3,9 @@
#include <hex/helpers/utils.hpp>
#include <filesystem>
#include <cstdio>
#include <mbedtls/ssl.h>
#include <mbedtls/x509.h>
#include <mbedtls/x509_crt.h>
#include <mbedtls/error.h>
#include <hex/resources.hpp>
@ -14,21 +13,33 @@
namespace hex {
Net::Net() {
curl_global_sslset(CURLSSLBACKEND_MBEDTLS, nullptr, nullptr);
curl_global_init(CURL_GLOBAL_ALL);
FIRST_TIME {
curl_global_sslset(CURLSSLBACKEND_MBEDTLS, nullptr, nullptr);
curl_global_init(CURL_GLOBAL_ALL);
};
FINAL_CLEANUP {
curl_global_cleanup();
};
this->m_ctx = curl_easy_init();
}
Net::~Net() {
curl_easy_cleanup(this->m_ctx);
curl_global_cleanup();
}
static size_t writeToString(void *contents, size_t size, size_t nmemb, void *userp){
static_cast<std::string*>(userp)->append((char*)contents, size * nmemb);
static size_t writeToString(void *contents, size_t size, size_t nmemb, void *userdata){
static_cast<std::string*>(userdata)->append((char*)contents, 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) {
auto* cfg = static_cast<mbedtls_ssl_config*>(sslctx);
@ -41,9 +52,21 @@ namespace hex {
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) {
struct curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Cache-Control: no-cache");
int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
auto &net = *static_cast<Net*>(contents);
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())
for (const auto &[key, value] : extraHeaders) {
@ -51,65 +74,131 @@ namespace hex {
entry += ": ";
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())
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(ctx, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2);
curl_easy_setopt(ctx, CURLOPT_URL, path.data());
curl_easy_setopt(ctx, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(ctx, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(ctx, CURLOPT_USERAGENT, "ImHex/1.0");
curl_easy_setopt(ctx, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, writeToString);
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(ctx, CURLOPT_CAINFO, nullptr);
curl_easy_setopt(ctx, CURLOPT_CAPATH, nullptr);
curl_easy_setopt(ctx, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(ctx, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
curl_easy_setopt(ctx, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(ctx, CURLOPT_TIMEOUT_MS, 2000L);
curl_easy_setopt(ctx, CURLOPT_CONNECTTIMEOUT_MS, 2000L);
curl_easy_setopt(ctx, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(ctx, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(this->m_ctx, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(this->m_ctx, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_easy_setopt(this->m_ctx, CURLOPT_URL, url.c_str());
curl_easy_setopt(this->m_ctx, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(this->m_ctx, CURLOPT_HTTPHEADER, this->m_headers);
curl_easy_setopt(this->m_ctx, CURLOPT_USERAGENT, "ImHex/1.0");
curl_easy_setopt(this->m_ctx, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEFUNCTION, writeToString);
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(this->m_ctx, CURLOPT_CAINFO, nullptr);
curl_easy_setopt(this->m_ctx, CURLOPT_CAPATH, nullptr);
curl_easy_setopt(this->m_ctx, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(this->m_ctx, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(this->m_ctx, CURLOPT_TIMEOUT_MS, 0L);
curl_easy_setopt(this->m_ctx, CURLOPT_CONNECTTIMEOUT_MS, 2000L);
curl_easy_setopt(this->m_ctx, CURLOPT_XFERINFODATA, this);
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::string response;
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
setCommonSettings(this->m_ctx, response, url, {}, "");
std::optional<s32> Net::execute() {
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_slist_free_all(this->m_headers);
this->m_headers = nullptr;
this->m_progress = 0.0F;
this->m_shouldCancel = false;
if (result != CURLE_OK)
return Response<std::string>{ responseCode, "" };
return { };
else
return Response<std::string>{ responseCode, response };
return responseCode;
}
Response<nlohmann::json> Net::getJson(std::string_view url) {
std::string response;
std::future<Response<std::string>> Net::getString(const std::string &url) {
this->m_transmissionActive.lock();
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
setCommonSettings(this->m_ctx, response, url, {}, "");
return std::async(std::launch::async, [=, this]{
std::string response;
CURLcode result = curl_easy_perform(this->m_ctx);
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
u32 responseCode = 0;
curl_easy_getinfo(this->m_ctx, CURLINFO_RESPONSE_CODE, &responseCode);
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
setCommonSettings(response, url);
if (result != CURLE_OK)
return Response<nlohmann::json>{ responseCode, { } };
else
return Response<nlohmann::json>{ responseCode, nlohmann::json::parse(response) };
auto responseCode = execute();
return Response<std::string> { responseCode.value_or(0), 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 };
});
}
}

View File

@ -296,4 +296,30 @@ namespace hex {
#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();
}
}

View File

@ -24,32 +24,6 @@ namespace hex {
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() {
if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s", SharedData::errorPopupMessage.c_str());

View File

@ -31,15 +31,15 @@ namespace hex::init {
static bool checkForUpdates() {
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)
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;
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)
getInitArguments().push_back({ "update-available", latestVersion.data() });
@ -50,11 +50,11 @@ namespace hex::init {
static bool downloadInformation() {
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)
return false;
getInitArguments().push_back({ "tip-of-the-day", tip.response });
getInitArguments().push_back({ "tip-of-the-day", tip.body });
return true;
}

View File

@ -176,7 +176,7 @@ namespace hex {
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
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)) {
View::showErrorPopup("hex.view.hexeditor.error.create"_lang);
return;
@ -185,12 +185,12 @@ namespace hex {
this->getWindowOpenState() = true;
});
} 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->getWindowOpenState() = true;
});
} 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);
EventManager::post<EventProjectFileLoad>();
this->getWindowOpenState() = true;
@ -271,7 +271,7 @@ namespace hex {
}
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;
provider->saveAs(path);
});
@ -306,14 +306,14 @@ namespace hex {
ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine();
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;
});
}
ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine();
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;
});
}
@ -384,7 +384,7 @@ namespace hex {
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
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);
});
}
@ -416,7 +416,7 @@ namespace hex {
ImGui::Separator();
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);
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 (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")) {
ProjectFile::store(path);
}
@ -438,7 +438,7 @@ namespace hex {
}
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);
});
}
@ -448,7 +448,7 @@ namespace hex {
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.import"_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;
this->loadFromFile(path, base64);
@ -468,7 +468,7 @@ namespace hex {
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 patch = hex::loadIPSPatch(patchData);
@ -482,7 +482,7 @@ namespace hex {
}
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 patch = hex::loadIPS32Patch(patchData);
@ -512,7 +512,7 @@ namespace hex {
}
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);
});
}
@ -525,7 +525,7 @@ namespace hex {
}
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);
});
}

View File

@ -213,7 +213,7 @@ namespace hex {
void ViewPattern::drawMenu() {
if (ImGui::BeginMenu("hex.menu.file"_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);
});
}