From 8c5fd021f75604f2862bb20aa9e796632e76d1ee Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 22 Mar 2023 23:05:18 +0100 Subject: [PATCH] api: Hook up new http wrapper to the rest of ImHex --- lib/libimhex/CMakeLists.txt | 1 + .../include/hex/helpers/http_requests.hpp | 77 ++++++++++++------- lib/libimhex/source/helpers/http_requests.cpp | 30 ++++++++ main/source/init/tasks.cpp | 13 +++- 4 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 lib/libimhex/source/helpers/http_requests.cpp diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index 3aaf48a03..c6485d1bd 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -24,6 +24,7 @@ set(LIBIMHEX_SOURCES source/helpers/magic.cpp source/helpers/crypto.cpp source/helpers/net.cpp + source/helpers/http_requests.cpp source/helpers/opengl.cpp source/helpers/patches.cpp source/helpers/encoding_file.cpp diff --git a/lib/libimhex/include/hex/helpers/http_requests.hpp b/lib/libimhex/include/hex/helpers/http_requests.hpp index 428dcd20d..d4a097574 100644 --- a/lib/libimhex/include/hex/helpers/http_requests.hpp +++ b/lib/libimhex/include/hex/helpers/http_requests.hpp @@ -1,9 +1,16 @@ #pragma once +#include + #include +#include +#include +#include #include +#include + #include #include #include @@ -62,7 +69,36 @@ namespace hex { curl_easy_cleanup(this->m_curl); } - static void setCaCert(std::string data) { + HttpRequest(const HttpRequest&) = delete; + HttpRequest& operator=(const HttpRequest&) = delete; + + HttpRequest(HttpRequest &&other) noexcept { + this->m_curl = other.m_curl; + other.m_curl = nullptr; + + this->m_method = std::move(other.m_method); + this->m_url = std::move(other.m_url); + this->m_headers = std::move(other.m_headers); + this->m_body = std::move(other.m_body); + + this->m_caCert = std::move(other.m_caCert); + } + + HttpRequest& operator=(HttpRequest &&other) noexcept { + this->m_curl = other.m_curl; + other.m_curl = nullptr; + + this->m_method = std::move(other.m_method); + this->m_url = std::move(other.m_url); + this->m_headers = std::move(other.m_headers); + this->m_body = std::move(other.m_body); + + this->m_caCert = std::move(other.m_caCert); + + return *this; + } + + static void setCACert(std::string data) { HttpRequest::s_caCertData = std::move(data); } @@ -74,7 +110,7 @@ namespace hex { this->m_body = std::move(body); } - template + template std::future> downloadFile(const std::fs::path &path) { return std::async(std::launch::async, [this, path] { T response; @@ -112,7 +148,7 @@ namespace hex { }); } - template + template std::future> uploadFile(const std::fs::path &path, const std::string &mimeName = "filename") { return std::async(std::launch::async, [this, path, mimeName]{ auto fileName = wolv::util::toUTF8String(path.filename()); @@ -154,9 +190,9 @@ namespace hex { return this->executeImpl(responseData); }); } - template + template std::future> uploadFile(std::vector data, const std::string &mimeName = "filename") { - return std::async(std::launch::async, [this, data = std::move(data)]{ + return std::async(std::launch::async, [this, data = std::move(data), mimeName]{ curl_mime *mime = curl_mime_init(this->m_curl); curl_mimepart *part = curl_mime_addpart(mime); @@ -174,7 +210,7 @@ namespace hex { }); } - template + template std::future> execute() { return std::async(std::launch::async, [this] { T data; @@ -187,29 +223,14 @@ namespace hex { } protected: + void setDefaultConfig(); + template Result executeImpl(T &data) { curl_easy_setopt(this->m_curl, CURLOPT_URL, this->m_url.c_str()); curl_easy_setopt(this->m_curl, CURLOPT_CUSTOMREQUEST, this->m_method.c_str()); - curl_easy_setopt(this->m_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); - curl_easy_setopt(this->m_curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); - curl_easy_setopt(this->m_curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(this->m_curl, CURLOPT_USERAGENT, "ImHex/1.0"); - curl_easy_setopt(this->m_curl, CURLOPT_DEFAULT_PROTOCOL, "https"); - curl_easy_setopt(this->m_curl, CURLOPT_SSL_VERIFYPEER, 1L); - curl_easy_setopt(this->m_curl, CURLOPT_SSL_VERIFYHOST, 2L); - curl_easy_setopt(this->m_curl, CURLOPT_TIMEOUT_MS, 0L); - curl_easy_setopt(this->m_curl, CURLOPT_CONNECTTIMEOUT_MS, 10000); - curl_easy_setopt(this->m_curl, CURLOPT_NOSIGNAL, 1L); - - #if defined(IMHEX_USE_BUNDLED_CA) - curl_easy_setopt(this->m_curl, CURLOPT_CAINFO, nullptr); - curl_easy_setopt(this->m_curl, CURLOPT_CAPATH, nullptr); - curl_easy_setopt(this->m_curl, CURLOPT_SSLCERTTYPE, "PEM"); - curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction); - curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_DATA, &this->m_caCert); - #endif + setDefaultConfig(); if (!this->m_body.empty()) { curl_easy_setopt(this->m_curl, CURLOPT_POSTFIELDS, this->m_body.c_str()); @@ -219,13 +240,13 @@ namespace hex { headers = curl_slist_append(headers, "Cache-Control: no-cache"); for (auto &[key, value] : this->m_headers) { - std::string header = key + ": " + value; + std::string header = hex::format("{}: {}", key, value); headers = curl_slist_append(headers, header.c_str()); } curl_easy_setopt(this->m_curl, CURLOPT_HTTPHEADER, headers); auto result = curl_easy_perform(this->m_curl); - printf("curl result: %d\n", result); + printf("Curl result: %s\n", curl_easy_strerror(result)); u32 statusCode = 0; curl_easy_getinfo(this->m_curl, CURLINFO_RESPONSE_CODE, &statusCode); @@ -268,8 +289,8 @@ namespace hex { std::string m_body; std::map m_headers; - mbedtls_x509_crt m_caCert; - static inline std::string s_caCertData; + [[maybe_unused]] std::unique_ptr m_caCert; + static std::string s_caCertData; }; } \ No newline at end of file diff --git a/lib/libimhex/source/helpers/http_requests.cpp b/lib/libimhex/source/helpers/http_requests.cpp new file mode 100644 index 000000000..d92bb777a --- /dev/null +++ b/lib/libimhex/source/helpers/http_requests.cpp @@ -0,0 +1,30 @@ +#include + +namespace hex { + + std::string HttpRequest::s_caCertData; + + void HttpRequest::setDefaultConfig() { + curl_easy_setopt(this->m_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); + curl_easy_setopt(this->m_curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + curl_easy_setopt(this->m_curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(this->m_curl, CURLOPT_USERAGENT, "ImHex/1.0"); + curl_easy_setopt(this->m_curl, CURLOPT_DEFAULT_PROTOCOL, "https"); + curl_easy_setopt(this->m_curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(this->m_curl, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(this->m_curl, CURLOPT_TIMEOUT_MS, 0L); + curl_easy_setopt(this->m_curl, CURLOPT_CONNECTTIMEOUT_MS, 10000); + curl_easy_setopt(this->m_curl, CURLOPT_NOSIGNAL, 1L); + + #if defined(IMHEX_USE_BUNDLED_CA) + curl_easy_setopt(this->m_curl, CURLOPT_CAINFO, nullptr); + curl_easy_setopt(this->m_curl, CURLOPT_CAPATH, nullptr); + curl_easy_setopt(this->m_curl, CURLOPT_SSLCERTTYPE, "PEM"); + curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction); + + this->m_caCert = std::make_unique(); + curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_DATA, this->m_caCert.get()); + #endif + } + +} \ No newline at end of file diff --git a/main/source/init/tasks.cpp b/main/source/init/tasks.cpp index fcecbd057..f7d0c5882 100644 --- a/main/source/init/tasks.cpp +++ b/main/source/init/tasks.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -65,13 +66,13 @@ namespace hex::init { hex::log::debug("Using romfs: '{}'", romfs::name()); // Load the SSL certificate - constexpr static auto CaCertPath = "cacert.pem"; + constexpr static auto CaCertFileName = "cacert.pem"; // Look for a custom certificate in the config folder std::fs::path caCertPath; for (const auto &folder : fs::getDefaultPaths(fs::ImHexPath::Config)) { for (const auto &file : std::fs::directory_iterator(folder)) { - if (file.path().filename() == CaCertPath) { + if (file.path().filename() == CaCertFileName) { caCertPath = file.path(); break; } @@ -79,10 +80,14 @@ namespace hex::init { } // If a custom certificate was found, use it, otherwise use the one from the romfs + std::string caCertData; if (!caCertPath.empty()) - Net::setCACert(wolv::io::File(caCertPath, wolv::io::File::Mode::Read).readString()); + caCertData = wolv::io::File(caCertPath, wolv::io::File::Mode::Read).readString(); else - Net::setCACert(std::string(romfs::get(CaCertPath).string())); + caCertData = std::string(romfs::get(CaCertFileName).string()); + + Net::setCACert(caCertData); + HttpRequest::setCACert(caCertData); return true; }