sys: Updated to use the new HttpRequest helper instead of Net
This commit is contained in:
parent
e7e2af9f91
commit
15be24db62
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
@ -1 +1 @@
|
|||||||
Subproject commit c24015b8f5b5e99bab18978a9d10f2e8c859f9b2
|
Subproject commit 3b7a928b7e53e98c5ef7372f1429032f6d622c10
|
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 0c3dcfdc3c81002f209df4efa9c0425a376c55f9
|
Subproject commit 25922e11b9cc6bbde1a321f5bd6ab2e622b07531
|
@ -23,7 +23,6 @@ set(LIBIMHEX_SOURCES
|
|||||||
source/helpers/fs.cpp
|
source/helpers/fs.cpp
|
||||||
source/helpers/magic.cpp
|
source/helpers/magic.cpp
|
||||||
source/helpers/crypto.cpp
|
source/helpers/crypto.cpp
|
||||||
source/helpers/net.cpp
|
|
||||||
source/helpers/http_requests.cpp
|
source/helpers/http_requests.cpp
|
||||||
source/helpers/opengl.cpp
|
source/helpers/opengl.cpp
|
||||||
source/helpers/patches.cpp
|
source/helpers/patches.cpp
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include <hex/helpers/logger.hpp>
|
||||||
#include <hex/helpers/fmt.hpp>
|
#include <hex/helpers/fmt.hpp>
|
||||||
|
|
||||||
#include <wolv/io/file.hpp>
|
#include <wolv/io/file.hpp>
|
||||||
@ -25,7 +26,8 @@ namespace hex {
|
|||||||
|
|
||||||
class ResultBase {
|
class ResultBase {
|
||||||
public:
|
public:
|
||||||
explicit ResultBase(u32 statusCode) : m_statusCode(statusCode) { }
|
ResultBase() = default;
|
||||||
|
explicit ResultBase(u32 statusCode) : m_statusCode(statusCode), m_valid(true) { }
|
||||||
|
|
||||||
[[nodiscard]] u32 getStatusCode() const {
|
[[nodiscard]] u32 getStatusCode() const {
|
||||||
return this->m_statusCode;
|
return this->m_statusCode;
|
||||||
@ -35,13 +37,19 @@ namespace hex {
|
|||||||
return this->getStatusCode() == 200;
|
return this->getStatusCode() == 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isValid() const {
|
||||||
|
return this->m_valid;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 m_statusCode;
|
u32 m_statusCode = 0;
|
||||||
|
bool m_valid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Result : public ResultBase {
|
class Result : public ResultBase {
|
||||||
public:
|
public:
|
||||||
|
Result() = default;
|
||||||
Result(u32 statusCode, T data) : ResultBase(statusCode), m_data(std::move(data)) { }
|
Result(u32 statusCode, T data) : ResultBase(statusCode), m_data(std::move(data)) { }
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@ -102,6 +110,18 @@ namespace hex {
|
|||||||
HttpRequest::s_caCertData = std::move(data);
|
HttpRequest::s_caCertData = std::move(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setProxy(std::string proxy) {
|
||||||
|
HttpRequest::s_proxyUrl = std::move(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMethod(std::string method) {
|
||||||
|
this->m_method = std::move(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUrl(std::string url) {
|
||||||
|
this->m_url = std::move(url);
|
||||||
|
}
|
||||||
|
|
||||||
void addHeader(std::string key, std::string value) {
|
void addHeader(std::string key, std::string value) {
|
||||||
this->m_headers[std::move(key)] = std::move(value);
|
this->m_headers[std::move(key)] = std::move(value);
|
||||||
}
|
}
|
||||||
@ -110,24 +130,28 @@ namespace hex {
|
|||||||
this->m_body = std::move(body);
|
this->m_body = std::move(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTimeout(u32 timeout) {
|
||||||
|
this->m_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getProgress() const {
|
||||||
|
return this->m_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel() {
|
||||||
|
this->m_canceled = true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T = std::string>
|
template<typename T = std::string>
|
||||||
std::future<Result<T>> downloadFile(const std::fs::path &path) {
|
std::future<Result<T>> downloadFile(const std::fs::path &path) {
|
||||||
return std::async(std::launch::async, [this, path] {
|
return std::async(std::launch::async, [this, path] {
|
||||||
T response;
|
std::vector<u8> response;
|
||||||
|
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, [](void *contents, size_t size, size_t nmemb, void *userdata){
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
|
||||||
auto &file = *reinterpret_cast<wolv::io::File*>(userdata);
|
|
||||||
|
|
||||||
file.write(reinterpret_cast<const u8*>(contents), size * nmemb);
|
|
||||||
|
|
||||||
return size * nmemb;
|
|
||||||
});
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &file);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &file);
|
||||||
|
|
||||||
this->executeImpl<T>(response);
|
return this->executeImpl<T>(response);
|
||||||
|
|
||||||
return Result<T>(200, std::move(response));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,13 +159,7 @@ namespace hex {
|
|||||||
return std::async(std::launch::async, [this] {
|
return std::async(std::launch::async, [this] {
|
||||||
std::vector<u8> response;
|
std::vector<u8> response;
|
||||||
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, [](void *contents, size_t size, size_t nmemb, void *userdata){
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||||
auto &response = *reinterpret_cast<std::vector<u8>*>(userdata);
|
|
||||||
|
|
||||||
response.insert(response.end(), reinterpret_cast<const u8*>(contents), reinterpret_cast<const u8*>(contents) + size * nmemb);
|
|
||||||
|
|
||||||
return size * nmemb;
|
|
||||||
});
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &response);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &response);
|
||||||
|
|
||||||
return this->executeImpl<std::vector<u8>>(response);
|
return this->executeImpl<std::vector<u8>>(response);
|
||||||
@ -183,8 +201,8 @@ namespace hex {
|
|||||||
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_MIMEPOST, mime);
|
curl_easy_setopt(this->m_curl, CURLOPT_MIMEPOST, mime);
|
||||||
|
|
||||||
T responseData;
|
std::vector<u8> responseData;
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToContainer<T>);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &responseData);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||||
|
|
||||||
return this->executeImpl<T>(responseData);
|
return this->executeImpl<T>(responseData);
|
||||||
@ -202,8 +220,8 @@ namespace hex {
|
|||||||
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_MIMEPOST, mime);
|
curl_easy_setopt(this->m_curl, CURLOPT_MIMEPOST, mime);
|
||||||
|
|
||||||
T responseData;
|
std::vector<u8> responseData;
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToContainer<T>);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &responseData);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||||
|
|
||||||
return this->executeImpl<T>(responseData);
|
return this->executeImpl<T>(responseData);
|
||||||
@ -213,20 +231,46 @@ namespace hex {
|
|||||||
template<typename T = std::string>
|
template<typename T = std::string>
|
||||||
std::future<Result<T>> execute() {
|
std::future<Result<T>> execute() {
|
||||||
return std::async(std::launch::async, [this] {
|
return std::async(std::launch::async, [this] {
|
||||||
T data;
|
|
||||||
|
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToContainer<T>);
|
std::vector<u8> responseData;
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &data);
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
|
||||||
|
curl_easy_setopt(this->m_curl, CURLOPT_WRITEDATA, &responseData);
|
||||||
|
|
||||||
return this->executeImpl<T>(data);
|
return this->executeImpl<T>(responseData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string urlEncode(const std::string &input) {
|
||||||
|
auto escapedString = curl_easy_escape(this->m_curl, input.c_str(), std::strlen(input.c_str()));
|
||||||
|
|
||||||
|
if (escapedString != nullptr) {
|
||||||
|
std::string output = escapedString;
|
||||||
|
curl_free(escapedString);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string urlDecode(const std::string &input) {
|
||||||
|
auto unescapedString = curl_easy_unescape(this->m_curl, input.c_str(), std::strlen(input.c_str()), nullptr);
|
||||||
|
|
||||||
|
if (unescapedString != nullptr) {
|
||||||
|
std::string output = unescapedString;
|
||||||
|
curl_free(unescapedString);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setDefaultConfig();
|
void setDefaultConfig();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Result<T> executeImpl(T &data) {
|
Result<T> executeImpl(std::vector<u8> &data) {
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_URL, this->m_url.c_str());
|
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_CUSTOMREQUEST, this->m_method.c_str());
|
||||||
|
|
||||||
@ -245,52 +289,49 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(this->m_curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
auto result = curl_easy_perform(this->m_curl);
|
{
|
||||||
printf("Curl result: %s\n", curl_easy_strerror(result));
|
std::scoped_lock lock(this->m_transmissionMutex);
|
||||||
|
|
||||||
|
auto result = curl_easy_perform(this->m_curl);
|
||||||
|
if (result != CURLE_OK){
|
||||||
|
char *url = nullptr;
|
||||||
|
curl_easy_getinfo(this->m_curl, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
|
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", this->m_method, url, u32(result), curl_easy_strerror(result));
|
||||||
|
if (!HttpRequest::s_proxyUrl.empty()){
|
||||||
|
log::info("A custom proxy '{0}' is in use. Is it working correctly?", HttpRequest::s_proxyUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 statusCode = 0;
|
u32 statusCode = 0;
|
||||||
curl_easy_getinfo(this->m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
|
curl_easy_getinfo(this->m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
|
||||||
|
|
||||||
return Result<T>(statusCode, std::move(data));
|
return Result<T>(statusCode, { data.begin(), data.end() });
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]]
|
[[maybe_unused]] static CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userData);
|
||||||
static CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userData) {
|
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||||
hex::unused(ctx, userData);
|
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||||
|
static int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
||||||
auto *cfg = static_cast<mbedtls_ssl_config *>(sslctx);
|
|
||||||
|
|
||||||
auto crt = static_cast<mbedtls_x509_crt*>(userData);
|
|
||||||
mbedtls_x509_crt_init(crt);
|
|
||||||
|
|
||||||
mbedtls_x509_crt_parse(crt, reinterpret_cast<const u8 *>(HttpRequest::s_caCertData.data()), HttpRequest::s_caCertData.size());
|
|
||||||
|
|
||||||
mbedtls_ssl_conf_ca_chain(cfg, crt, nullptr);
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static size_t writeToContainer(void *contents, size_t size, size_t nmemb, void *userdata) {
|
|
||||||
auto &response = *reinterpret_cast<T*>(userdata);
|
|
||||||
auto startSize = response.size();
|
|
||||||
|
|
||||||
response.resize(startSize + size * nmemb);
|
|
||||||
std::memcpy(response.data() + startSize, contents, size * nmemb);
|
|
||||||
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CURL *m_curl;
|
CURL *m_curl;
|
||||||
|
|
||||||
|
std::mutex m_transmissionMutex;
|
||||||
|
|
||||||
std::string m_method;
|
std::string m_method;
|
||||||
std::string m_url;
|
std::string m_url;
|
||||||
std::string m_body;
|
std::string m_body;
|
||||||
std::map<std::string, std::string> m_headers;
|
std::map<std::string, std::string> m_headers;
|
||||||
|
u32 m_timeout = 1000;
|
||||||
|
|
||||||
|
float m_progress = 0.0F;
|
||||||
|
bool m_canceled = false;
|
||||||
|
|
||||||
[[maybe_unused]] std::unique_ptr<mbedtls_x509_crt> m_caCert;
|
[[maybe_unused]] std::unique_ptr<mbedtls_x509_crt> m_caCert;
|
||||||
static std::string s_caCertData;
|
static std::string s_caCertData, s_proxyUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <hex.hpp>
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <future>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <curl/system.h>
|
|
||||||
#include <mbedtls/ssl.h>
|
|
||||||
|
|
||||||
#include <hex/helpers/fs.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace hex {
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct Response {
|
|
||||||
i32 code;
|
|
||||||
T body;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Response<void> {
|
|
||||||
i32 code;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Net {
|
|
||||||
public:
|
|
||||||
Net();
|
|
||||||
~Net();
|
|
||||||
|
|
||||||
constexpr static u32 DefaultTimeout = 2'000;
|
|
||||||
|
|
||||||
std::future<Response<std::string>> getString(const std::string &url, u32 timeout = DefaultTimeout, const std::map<std::string, std::string> &extraHeaders = {}, const std::string &body = {});
|
|
||||||
std::future<Response<nlohmann::json>> getJson(const std::string &url, u32 timeout = DefaultTimeout, const std::map<std::string, std::string> &extraHeaders = {}, const std::string &body = {});
|
|
||||||
|
|
||||||
std::future<Response<nlohmann::json>> postJson(const std::string &url, u32 timeout = DefaultTimeout, const std::map<std::string, std::string> &extraHeaders = {}, const std::string &body = {});
|
|
||||||
|
|
||||||
std::future<Response<std::string>> uploadFile(const std::string &url, const std::fs::path &filePath, u32 timeout = DefaultTimeout);
|
|
||||||
std::future<Response<void>> downloadFile(const std::string &url, const std::fs::path &filePath, u32 timeout = DefaultTimeout);
|
|
||||||
|
|
||||||
[[nodiscard]] std::string encode(const std::string &input);
|
|
||||||
[[nodiscard]] std::string decode(const std::string &input);
|
|
||||||
|
|
||||||
[[nodiscard]] float getProgress() const { return this->m_progress; }
|
|
||||||
|
|
||||||
void cancel() { this->m_shouldCancel = true; }
|
|
||||||
|
|
||||||
static void setProxy(const std::string &url);
|
|
||||||
static void setCACert(const std::string &content);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setCommonSettings(std::string &response, const std::string &url, u32 timeout = 2000, const std::map<std::string, std::string> &extraHeaders = {}, const std::string &body = {});
|
|
||||||
std::optional<i32> execute();
|
|
||||||
|
|
||||||
friend int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
|
||||||
friend CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userData);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CURL *m_ctx;
|
|
||||||
mbedtls_x509_crt m_caCert;
|
|
||||||
curl_slist *m_headers = nullptr;
|
|
||||||
|
|
||||||
std::mutex m_transmissionActive;
|
|
||||||
float m_progress = 0.0F;
|
|
||||||
bool m_shouldCancel = false;
|
|
||||||
|
|
||||||
static std::string s_proxyUrl;
|
|
||||||
static std::string s_caCert;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -26,11 +26,11 @@ namespace hex {
|
|||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
[[nodiscard]] std::vector<u8> read(const std::fs::path &path);
|
[[nodiscard]] std::vector<u8> readVector(const std::fs::path &path);
|
||||||
[[nodiscard]] std::string readString(const std::fs::path &path);
|
[[nodiscard]] std::string readString(const std::fs::path &path);
|
||||||
|
|
||||||
void write(const std::fs::path &path, const std::vector<u8> &data);
|
void writeVector(const std::fs::path &path, const std::vector<u8> &data);
|
||||||
void write(const std::fs::path &path, const std::string &data);
|
void writeString(const std::fs::path &path, const std::string &data);
|
||||||
|
|
||||||
[[nodiscard]] std::vector<std::fs::path> listEntries(const std::fs::path &basePath = "/");
|
[[nodiscard]] std::vector<std::fs::path> listEntries(const std::fs::path &basePath = "/");
|
||||||
[[nodiscard]] bool contains(const std::fs::path &path);
|
[[nodiscard]] bool contains(const std::fs::path &path);
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <hex/data_processor/node.hpp>
|
#include <hex/data_processor/node.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ namespace hex {
|
|||||||
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create);
|
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create);
|
||||||
|
|
||||||
if (file.isValid()) {
|
if (file.isValid()) {
|
||||||
file.write(getSettingsData().dump(4));
|
file.writeString(getSettingsData().dump(4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace hex {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto metadataContent = tar.read(MetadataPath);
|
const auto metadataContent = tar.readVector(MetadataPath);
|
||||||
|
|
||||||
if (!std::string(metadataContent.begin(), metadataContent.end()).starts_with(MetadataHeaderMagic))
|
if (!std::string(metadataContent.begin(), metadataContent.end()).starts_with(MetadataHeaderMagic))
|
||||||
return false;
|
return false;
|
||||||
@ -131,7 +131,7 @@ namespace hex {
|
|||||||
|
|
||||||
{
|
{
|
||||||
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, IMHEX_VERSION);
|
const auto metadataContent = hex::format("{}\n{}", MetadataHeaderMagic, IMHEX_VERSION);
|
||||||
tar.write(MetadataPath, metadataContent);
|
tar.writeString(MetadataPath, metadataContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImHexApi::Provider::resetDirty();
|
ImHexApi::Provider::resetDirty();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
std::string HttpRequest::s_caCertData;
|
std::string HttpRequest::s_caCertData;
|
||||||
|
std::string HttpRequest::s_proxyUrl;
|
||||||
|
|
||||||
void HttpRequest::setDefaultConfig() {
|
void HttpRequest::setDefaultConfig() {
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
curl_easy_setopt(this->m_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||||
@ -13,8 +14,11 @@ namespace hex {
|
|||||||
curl_easy_setopt(this->m_curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
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_SSL_VERIFYHOST, 2L);
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_TIMEOUT_MS, 0L);
|
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_CONNECTTIMEOUT_MS, this->m_timeout);
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(this->m_curl, CURLOPT_NOSIGNAL, 1L);
|
||||||
|
curl_easy_setopt(this->m_curl, CURLOPT_XFERINFODATA, this);
|
||||||
|
curl_easy_setopt(this->m_curl, CURLOPT_XFERINFOFUNCTION, progressCallback);
|
||||||
|
curl_easy_setopt(this->m_curl, CURLOPT_PROXY, s_proxyUrl.c_str());
|
||||||
|
|
||||||
#if defined(IMHEX_USE_BUNDLED_CA)
|
#if defined(IMHEX_USE_BUNDLED_CA)
|
||||||
curl_easy_setopt(this->m_curl, CURLOPT_CAINFO, nullptr);
|
curl_easy_setopt(this->m_curl, CURLOPT_CAINFO, nullptr);
|
||||||
@ -27,4 +31,50 @@ namespace hex {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CURLcode HttpRequest::sslCtxFunction(CURL *ctx, void *sslctx, void *userData) {
|
||||||
|
hex::unused(ctx, userData);
|
||||||
|
|
||||||
|
auto *cfg = static_cast<mbedtls_ssl_config *>(sslctx);
|
||||||
|
|
||||||
|
auto crt = static_cast<mbedtls_x509_crt*>(userData);
|
||||||
|
mbedtls_x509_crt_init(crt);
|
||||||
|
|
||||||
|
mbedtls_x509_crt_parse(crt, reinterpret_cast<const u8 *>(HttpRequest::s_caCertData.data()), HttpRequest::s_caCertData.size());
|
||||||
|
|
||||||
|
mbedtls_ssl_conf_ca_chain(cfg, crt, nullptr);
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HttpRequest::writeToVector(void *contents, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
auto &response = *reinterpret_cast<std::vector<u8>*>(userdata);
|
||||||
|
auto startSize = response.size();
|
||||||
|
|
||||||
|
response.resize(startSize + size * nmemb);
|
||||||
|
std::memcpy(response.data() + startSize, contents, size * nmemb);
|
||||||
|
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HttpRequest::writeToFile(void *contents, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
auto &file = *reinterpret_cast<wolv::io::File*>(userdata);
|
||||||
|
|
||||||
|
file.writeBuffer(reinterpret_cast<const u8*>(contents), size * nmemb);
|
||||||
|
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||||
|
auto &request = *static_cast<HttpRequest *>(contents);
|
||||||
|
|
||||||
|
if (dlTotal > 0)
|
||||||
|
request.m_progress = float(dlNow) / dlTotal;
|
||||||
|
else if (ulTotal > 0)
|
||||||
|
request.m_progress = float(ulNow) / ulTotal;
|
||||||
|
else
|
||||||
|
request.m_progress = 0.0F;
|
||||||
|
|
||||||
|
return request.m_canceled ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,306 +0,0 @@
|
|||||||
#include <hex/helpers/net.hpp>
|
|
||||||
|
|
||||||
#include <hex/helpers/utils.hpp>
|
|
||||||
#include <hex/helpers/logger.hpp>
|
|
||||||
|
|
||||||
#include <hex/api/content_registry.hpp>
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
#include <wolv/io/file.hpp>
|
|
||||||
#include <wolv/utils/guards.hpp>
|
|
||||||
|
|
||||||
namespace hex {
|
|
||||||
|
|
||||||
Net::Net() {
|
|
||||||
AT_FIRST_TIME {
|
|
||||||
curl_global_sslset(CURLSSLBACKEND_MBEDTLS, nullptr, nullptr);
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
|
||||||
};
|
|
||||||
|
|
||||||
AT_FINAL_CLEANUP {
|
|
||||||
curl_global_cleanup();
|
|
||||||
};
|
|
||||||
|
|
||||||
this->m_ctx = curl_easy_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Net::~Net() {
|
|
||||||
curl_easy_cleanup(this->m_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 writeToFile(void *contents, size_t size, size_t nmemb, void *userdata) {
|
|
||||||
FILE *file = static_cast<FILE *>(userdata);
|
|
||||||
|
|
||||||
return fwrite(contents, size, nmemb, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]]
|
|
||||||
CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userData) {
|
|
||||||
hex::unused(ctx, userData);
|
|
||||||
|
|
||||||
auto *cfg = static_cast<mbedtls_ssl_config *>(sslctx);
|
|
||||||
|
|
||||||
auto crt = static_cast<mbedtls_x509_crt*>(userData);
|
|
||||||
mbedtls_x509_crt_init(crt);
|
|
||||||
|
|
||||||
mbedtls_x509_crt_parse(crt, reinterpret_cast<const u8 *>(Net::s_caCert.data()), Net::s_caCert.size());
|
|
||||||
|
|
||||||
mbedtls_ssl_conf_ca_chain(cfg, crt, nullptr);
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, u32 timeout, 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) {
|
|
||||||
std::string entry = key;
|
|
||||||
entry += ": ";
|
|
||||||
entry += value;
|
|
||||||
|
|
||||||
this->m_headers = curl_slist_append(this->m_headers, entry.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!body.empty())
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_POSTFIELDS, body.c_str());
|
|
||||||
|
|
||||||
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_WRITEDATA, &response);
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_TIMEOUT_MS, 0L);
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_CONNECTTIMEOUT_MS, timeout);
|
|
||||||
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);
|
|
||||||
|
|
||||||
#if defined(IMHEX_USE_BUNDLED_CA)
|
|
||||||
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_SSL_CTX_DATA, &this->m_caCert);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_PROXY, Net::s_proxyUrl.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<i32> Net::execute() {
|
|
||||||
CURLcode result = curl_easy_perform(this->m_ctx);
|
|
||||||
if (result != CURLE_OK){
|
|
||||||
char *url = nullptr;
|
|
||||||
curl_easy_getinfo(this->m_ctx, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
log::error("Net request '{0}' failed with error {1}: '{2}'", url, u32(result), curl_easy_strerror(result));
|
|
||||||
if(!Net::s_proxyUrl.empty()){
|
|
||||||
log::info("A custom proxy '{}' is in use. Is it working correctly?", Net::s_proxyUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long 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 std::nullopt;
|
|
||||||
else
|
|
||||||
return i32(responseCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<Response<std::string>> Net::getString(const std::string &url, u32 timeout, const std::map<std::string, std::string> &extraHeaders, const std::string &body) {
|
|
||||||
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, timeout, extraHeaders, body);
|
|
||||||
|
|
||||||
auto responseCode = execute();
|
|
||||||
|
|
||||||
return Response<std::string> { responseCode.value_or(0), response };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<Response<nlohmann::json>> Net::getJson(const std::string &url, u32 timeout, const std::map<std::string, std::string> &extraHeaders, const std::string &body) {
|
|
||||||
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, timeout, extraHeaders, body);
|
|
||||||
|
|
||||||
auto responseCode = execute();
|
|
||||||
if (!responseCode.has_value())
|
|
||||||
return Response<nlohmann::json> { 0, { } };
|
|
||||||
else
|
|
||||||
return Response<nlohmann::json> { responseCode.value_or(0), nlohmann::json::parse(response, nullptr, false, true) };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<Response<nlohmann::json>> Net::postJson(const std::string &url, u32 timeout, const std::map<std::string, std::string> &extraHeaders, const std::string &body) {
|
|
||||||
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, "POST");
|
|
||||||
setCommonSettings(response, url, timeout, extraHeaders, body);
|
|
||||||
|
|
||||||
auto responseCode = execute();
|
|
||||||
if (!responseCode.has_value())
|
|
||||||
return Response<nlohmann::json> { 0, { } };
|
|
||||||
else
|
|
||||||
return Response<nlohmann::json> { responseCode.value_or(0), nlohmann::json::parse(response, nullptr, false, true) };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<Response<std::string>> Net::uploadFile(const std::string &url, const std::fs::path &filePath, u32 timeout) {
|
|
||||||
this->m_transmissionActive.lock();
|
|
||||||
|
|
||||||
return std::async(std::launch::async, [=, this] {
|
|
||||||
std::string response;
|
|
||||||
|
|
||||||
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
|
||||||
|
|
||||||
wolv::io::File file(filePath, wolv::io::File::Mode::Read);
|
|
||||||
if (!file.isValid())
|
|
||||||
return Response<std::string> { 400, {} };
|
|
||||||
|
|
||||||
curl_mime *mime = curl_mime_init(this->m_ctx);
|
|
||||||
curl_mimepart *part = curl_mime_addpart(mime);
|
|
||||||
|
|
||||||
auto fileName = wolv::util::toUTF8String(filePath.filename());
|
|
||||||
curl_mime_data_cb(part, file.getSize(),
|
|
||||||
[](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);
|
|
||||||
|
|
||||||
if (fseek(file, offset, origin) != 0)
|
|
||||||
return CURL_SEEKFUNC_CANTSEEK;
|
|
||||||
else
|
|
||||||
return CURL_SEEKFUNC_OK;
|
|
||||||
},
|
|
||||||
[](void *arg) {
|
|
||||||
auto file = static_cast<FILE*>(arg);
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
},
|
|
||||||
file.getHandle());
|
|
||||||
curl_mime_filename(part, fileName.c_str());
|
|
||||||
curl_mime_name(part, "file");
|
|
||||||
|
|
||||||
setCommonSettings(response, url, timeout);
|
|
||||||
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 };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::future<Response<void>> Net::downloadFile(const std::string &url, const std::fs::path &filePath, u32 timeout) {
|
|
||||||
this->m_transmissionActive.lock();
|
|
||||||
|
|
||||||
return std::async(std::launch::async, [=, this] {
|
|
||||||
std::string response;
|
|
||||||
|
|
||||||
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
|
||||||
|
|
||||||
wolv::io::File file(filePath, wolv::io::File::Mode::Create);
|
|
||||||
if (!file.isValid())
|
|
||||||
return Response<void> { 400 };
|
|
||||||
|
|
||||||
setCommonSettings(response, url, timeout);
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_CUSTOMREQUEST, "GET");
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEFUNCTION, writeToFile);
|
|
||||||
curl_easy_setopt(this->m_ctx, CURLOPT_WRITEDATA, file.getHandle());
|
|
||||||
auto responseCode = execute();
|
|
||||||
|
|
||||||
return Response<void> { responseCode.value_or(0) };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Net::encode(const std::string &input) {
|
|
||||||
auto escapedString = curl_easy_escape(this->m_ctx, input.c_str(), std::strlen(input.c_str()));
|
|
||||||
|
|
||||||
if (escapedString != nullptr) {
|
|
||||||
std::string output = escapedString;
|
|
||||||
curl_free(escapedString);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Net::decode(const std::string &input) {
|
|
||||||
auto unescapedString = curl_easy_unescape(this->m_ctx, input.c_str(), std::strlen(input.c_str()), nullptr);
|
|
||||||
|
|
||||||
if (unescapedString != nullptr) {
|
|
||||||
std::string output = unescapedString;
|
|
||||||
curl_free(unescapedString);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Net::s_proxyUrl;
|
|
||||||
void Net::setProxy(const std::string &url) {
|
|
||||||
Net::s_proxyUrl = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Net::s_caCert;
|
|
||||||
void Net::setCACert(const std::string &content) {
|
|
||||||
Net::s_caCert = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -84,7 +84,7 @@ namespace hex {
|
|||||||
this->m_valid = false;
|
this->m_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> Tar::read(const std::fs::path &path) {
|
std::vector<u8> Tar::readVector(const std::fs::path &path) {
|
||||||
mtar_header_t header;
|
mtar_header_t header;
|
||||||
|
|
||||||
auto fixedPath = path.string();
|
auto fixedPath = path.string();
|
||||||
@ -100,11 +100,11 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string Tar::readString(const std::fs::path &path) {
|
std::string Tar::readString(const std::fs::path &path) {
|
||||||
auto result = this->read(path);
|
auto result = this->readVector(path);
|
||||||
return { result.begin(), result.end() };
|
return { result.begin(), result.end() };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tar::write(const std::fs::path &path, const std::vector<u8> &data) {
|
void Tar::writeVector(const std::fs::path &path, const std::vector<u8> &data) {
|
||||||
if (path.has_parent_path()) {
|
if (path.has_parent_path()) {
|
||||||
std::fs::path pathPart;
|
std::fs::path pathPart;
|
||||||
for (const auto &part : path.parent_path()) {
|
for (const auto &part : path.parent_path()) {
|
||||||
@ -126,8 +126,8 @@ namespace hex {
|
|||||||
mtar_write_data(&this->m_ctx, data.data(), data.size());
|
mtar_write_data(&this->m_ctx, data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tar::write(const std::fs::path &path, const std::string &data) {
|
void Tar::writeString(const std::fs::path &path, const std::string &data) {
|
||||||
this->write(path, std::vector<u8>(data.begin(), data.end()));
|
this->writeVector(path, { data.begin(), data.end() });
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeFile(mtar_t *ctx, mtar_header_t *header, const std::fs::path &path) {
|
static void writeFile(mtar_t *ctx, mtar_header_t *header, const std::fs::path &path) {
|
||||||
@ -140,7 +140,7 @@ namespace hex {
|
|||||||
buffer.resize(std::min<u64>(BufferSize, header->size - offset));
|
buffer.resize(std::min<u64>(BufferSize, header->size - offset));
|
||||||
|
|
||||||
mtar_read_data(ctx, buffer.data(), buffer.size());
|
mtar_read_data(ctx, buffer.data(), buffer.size());
|
||||||
outputFile.write(buffer);
|
outputFile.writeVector(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace hex::prv {
|
|||||||
bufferSize = std::min<size_t>(bufferSize, this->getActualSize() - offset);
|
bufferSize = std::min<size_t>(bufferSize, this->getActualSize() - offset);
|
||||||
|
|
||||||
this->read(offset + this->getBaseAddress(), buffer.data(), bufferSize, true);
|
this->read(offset + this->getBaseAddress(), buffer.data(), bufferSize, true);
|
||||||
file.write(buffer.data(), bufferSize);
|
file.writeBuffer(buffer.data(), bufferSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <hex/api/project_file_manager.hpp>
|
#include <hex/api/project_file_manager.hpp>
|
||||||
#include <hex/api/theme_manager.hpp>
|
#include <hex/api/theme_manager.hpp>
|
||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/helpers/net.hpp>
|
|
||||||
#include <hex/helpers/http_requests.hpp>
|
#include <hex/helpers/http_requests.hpp>
|
||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
#include <hex/helpers/logger.hpp>
|
#include <hex/helpers/logger.hpp>
|
||||||
@ -35,15 +34,23 @@ namespace hex::init {
|
|||||||
|
|
||||||
// Check if we should check for updates
|
// Check if we should check for updates
|
||||||
if (showCheckForUpdates == 1){
|
if (showCheckForUpdates == 1){
|
||||||
hex::Net net;
|
HttpRequest request("GET", GitHubApiURL + "/releases/latest"s);
|
||||||
|
request.setTimeout(2000);
|
||||||
|
|
||||||
// Query the GitHub API for the latest release version
|
// Query the GitHub API for the latest release version
|
||||||
auto releases = net.getJson(GitHubApiURL + "/releases/latest"s, 2000).get();
|
auto response = request.execute().get();
|
||||||
if (releases.code != 200)
|
if (response.getStatusCode() != 200)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
nlohmann::json releases;
|
||||||
|
try {
|
||||||
|
releases = nlohmann::json::parse(response.getData());
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the response is valid
|
// Check if the response is valid
|
||||||
if (!releases.body.contains("tag_name") || !releases.body["tag_name"].is_string())
|
if (!releases.contains("tag_name") || !releases["tag_name"].is_string())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Convert the current version string to a format that can be compared to the latest release
|
// Convert the current version string to a format that can be compared to the latest release
|
||||||
@ -52,7 +59,7 @@ namespace hex::init {
|
|||||||
auto currVersion = "v" + versionString.substr(0, versionLength);
|
auto currVersion = "v" + versionString.substr(0, versionLength);
|
||||||
|
|
||||||
// Get the latest release version string
|
// Get the latest release version string
|
||||||
auto latestVersion = releases.body["tag_name"].get<std::string_view>();
|
auto latestVersion = releases["tag_name"].get<std::string_view>();
|
||||||
|
|
||||||
// Check if the latest release is different from the current version
|
// Check if the latest release is different from the current version
|
||||||
if (latestVersion != currVersion)
|
if (latestVersion != currVersion)
|
||||||
@ -86,7 +93,6 @@ namespace hex::init {
|
|||||||
else
|
else
|
||||||
caCertData = std::string(romfs::get(CaCertFileName).string());
|
caCertData = std::string(romfs::get(CaCertFileName).string());
|
||||||
|
|
||||||
Net::setCACert(caCertData);
|
|
||||||
HttpRequest::setCACert(caCertData);
|
HttpRequest::setCACert(caCertData);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
|
|
||||||
#include <hex/ui/view.hpp>
|
#include <hex/ui/view.hpp>
|
||||||
#include <hex/helpers/net.hpp>
|
#include <hex/helpers/http_requests.hpp>
|
||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -48,9 +48,9 @@ namespace hex::plugin::builtin {
|
|||||||
[[nodiscard]] ImVec2 getMaxSize() const override { return { 900, 700 }; }
|
[[nodiscard]] ImVec2 getMaxSize() const override { return { 900, 700 }; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Net m_net;
|
HttpRequest m_httpRequest = HttpRequest("GET", "");
|
||||||
std::future<Response<std::string>> m_apiRequest;
|
std::future<HttpRequest::Result<std::string>> m_apiRequest;
|
||||||
std::future<Response<void>> m_download;
|
std::future<HttpRequest::Result<std::string>> m_download;
|
||||||
std::fs::path m_downloadPath;
|
std::fs::path m_downloadPath;
|
||||||
RequestStatus m_requestStatus = RequestStatus::NotAttempted;
|
RequestStatus m_requestStatus = RequestStatus::NotAttempted;
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ namespace hex::plugin::builtin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto base64 = inputFile.readBytes();
|
auto base64 = inputFile.readVector();
|
||||||
|
|
||||||
if (!base64.empty()) {
|
if (!base64.empty()) {
|
||||||
auto data = crypt::decode64(base64);
|
auto data = crypt::decode64(base64);
|
||||||
@ -83,7 +83,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (!outputFile.isValid())
|
if (!outputFile.isValid())
|
||||||
View::showErrorPopup("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
|
View::showErrorPopup("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
|
||||||
|
|
||||||
outputFile.write(data);
|
outputFile.writeVector(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -95,7 +95,7 @@ namespace hex::plugin::builtin {
|
|||||||
void importIPSPatch() {
|
void importIPSPatch() {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
||||||
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readBytes();
|
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readVector();
|
||||||
auto patch = hex::loadIPSPatch(patchData);
|
auto patch = hex::loadIPSPatch(patchData);
|
||||||
if (!patch.has_value()) {
|
if (!patch.has_value()) {
|
||||||
handleIPSError(patch.error());
|
handleIPSError(patch.error());
|
||||||
@ -121,7 +121,7 @@ namespace hex::plugin::builtin {
|
|||||||
void importIPS32Patch() {
|
void importIPS32Patch() {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
||||||
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readBytes();
|
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readVector();
|
||||||
auto patch = hex::loadIPS32Patch(patchData);
|
auto patch = hex::loadIPS32Patch(patchData);
|
||||||
if (!patch.has_value()) {
|
if (!patch.has_value()) {
|
||||||
handleIPSError(patch.error());
|
handleIPSError(patch.error());
|
||||||
@ -148,7 +148,7 @@ namespace hex::plugin::builtin {
|
|||||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
|
||||||
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
|
||||||
auto provider = ImHexApi::Provider::get();
|
auto provider = ImHexApi::Provider::get();
|
||||||
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readBytes();
|
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readVector();
|
||||||
|
|
||||||
if (patchData.size() != provider->getActualSize()) {
|
if (patchData.size() != provider->getActualSize()) {
|
||||||
View::showErrorPopup("hex.builtin.menu.file.import.modified_file.popup.invalid_size"_lang);
|
View::showErrorPopup("hex.builtin.menu.file.import.modified_file.popup.invalid_size"_lang);
|
||||||
@ -202,7 +202,7 @@ namespace hex::plugin::builtin {
|
|||||||
bytes.resize(std::min<u64>(3000, provider->getActualSize() - address));
|
bytes.resize(std::min<u64>(3000, provider->getActualSize() - address));
|
||||||
provider->read(provider->getBaseAddress() + address, bytes.data(), bytes.size());
|
provider->read(provider->getBaseAddress() + address, bytes.data(), bytes.size());
|
||||||
|
|
||||||
outputFile.write(crypt::encode64(bytes));
|
outputFile.writeVector(crypt::encode64(bytes));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -232,7 +232,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.has_value())
|
if (data.has_value())
|
||||||
file.write(data.value());
|
file.writeVector(data.value());
|
||||||
else {
|
else {
|
||||||
handleIPSError(data.error());
|
handleIPSError(data.error());
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.has_value())
|
if (data.has_value())
|
||||||
file.write(data.value());
|
file.writeVector(data.value());
|
||||||
else
|
else
|
||||||
handleIPSError(data.error());
|
handleIPSError(data.error());
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
#include <hex/helpers/net.hpp>
|
#include <hex/helpers/http_requests.hpp>
|
||||||
|
|
||||||
#include <pl/core/token.hpp>
|
#include <pl/core/token.hpp>
|
||||||
#include <pl/core/log_console.hpp>
|
#include <pl/core/log_console.hpp>
|
||||||
@ -9,6 +9,7 @@
|
|||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
|
|
||||||
#include <llvm/Demangle/Demangle.h>
|
#include <llvm/Demangle/Demangle.h>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
void registerPatternLanguageFunctions() {
|
void registerPatternLanguageFunctions() {
|
||||||
@ -67,8 +68,8 @@ namespace hex::plugin::builtin {
|
|||||||
ContentRegistry::PatternLanguage::addDangerousFunction(nsHexHttp, "get", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
ContentRegistry::PatternLanguage::addDangerousFunction(nsHexHttp, "get", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
|
||||||
const auto url = params[0].toString(false);
|
const auto url = params[0].toString(false);
|
||||||
|
|
||||||
hex::Net net;
|
hex::HttpRequest request("GET", url);
|
||||||
return net.getString(url).get().body;
|
return request.execute().get().getData();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,11 +67,11 @@ namespace hex::plugin::builtin {
|
|||||||
json["type"] = provider->getTypeName();
|
json["type"] = provider->getTypeName();
|
||||||
json["settings"] = provider->storeSettings();
|
json["settings"] = provider->storeSettings();
|
||||||
|
|
||||||
tar.write(basePath / hex::format("{}.json", id), json.dump(4));
|
tar.writeString(basePath / hex::format("{}.json", id), json.dump(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
tar.write(basePath / "providers.json",
|
tar.writeString(basePath / "providers.json",
|
||||||
nlohmann::json({ {"providers", providerIds } }).dump(4)
|
nlohmann::json({ { "providers", providerIds } }).dump(4)
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,7 +77,7 @@ namespace hex::plugin::builtin {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
writeFile.seek(offset);
|
writeFile.seek(offset);
|
||||||
writeFile.write(reinterpret_cast<const u8*>(buffer), size);
|
writeFile.writeBuffer(reinterpret_cast<const u8*>(buffer), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileProvider::save() {
|
void FileProvider::save() {
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include <hex/api/localization.hpp>
|
#include <hex/api/localization.hpp>
|
||||||
#include <hex/api/theme_manager.hpp>
|
#include <hex/api/theme_manager.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/net.hpp>
|
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
#include <hex/helpers/http_requests.hpp>
|
||||||
#include <hex/helpers/logger.hpp>
|
#include <hex/helpers/logger.hpp>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
@ -517,8 +517,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
static const std::string proxySetting { "hex.builtin.setting.proxy" };
|
static const std::string proxySetting { "hex.builtin.setting.proxy" };
|
||||||
|
|
||||||
// init hex::Net proxy url
|
HttpRequest::setProxy(ContentRegistry::Settings::read(proxySetting, "hex.builtin.setting.proxy.url", ""));
|
||||||
hex::Net::setProxy(ContentRegistry::Settings::read(proxySetting, "hex.builtin.setting.proxy.url", ""));
|
|
||||||
|
|
||||||
ContentRegistry::Settings::addCategoryDescription(proxySetting, "hex.builtin.setting.proxy.description");
|
ContentRegistry::Settings::addCategoryDescription(proxySetting, "hex.builtin.setting.proxy.description");
|
||||||
|
|
||||||
@ -531,14 +530,14 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
if (ImGui::Checkbox("hex.builtin.setting.proxy.enable"_lang, &enableProxy)) {
|
if (ImGui::Checkbox("hex.builtin.setting.proxy.enable"_lang, &enableProxy)) {
|
||||||
setting = enableProxy ? proxyUrl : "";
|
setting = enableProxy ? proxyUrl : "";
|
||||||
hex::Net::setProxy(enableProxy ? proxyUrl : "");
|
HttpRequest::setProxy(enableProxy ? proxyUrl : "");
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::BeginDisabled(!enableProxy);
|
ImGui::BeginDisabled(!enableProxy);
|
||||||
if (ImGui::InputText("##proxy_url", proxyUrl)) {
|
if (ImGui::InputText("##proxy_url", proxyUrl)) {
|
||||||
setting = proxyUrl;
|
setting = proxyUrl;
|
||||||
hex::Net::setProxy(proxyUrl);
|
HttpRequest::setProxy(proxyUrl);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
#include <hex/api/imhex_api.hpp>
|
#include <hex/api/imhex_api.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/net.hpp>
|
#include <hex/helpers/http_requests.hpp>
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
#include <hex/helpers/fmt.hpp>
|
#include <hex/helpers/fmt.hpp>
|
||||||
#include <hex/helpers/literals.hpp>
|
#include <hex/helpers/literals.hpp>
|
||||||
@ -570,8 +570,8 @@ namespace hex::plugin::builtin {
|
|||||||
std::string fileName, link, size;
|
std::string fileName, link, size;
|
||||||
};
|
};
|
||||||
|
|
||||||
static hex::Net net;
|
static HttpRequest request("POST", "https://api.anonfiles.com/upload");
|
||||||
static std::future<Response<std::string>> uploadProcess;
|
static std::future<HttpRequest::Result<std::string>> uploadProcess;
|
||||||
static std::fs::path currFile;
|
static std::fs::path currFile;
|
||||||
static std::vector<UploadedFile> links;
|
static std::vector<UploadedFile> links;
|
||||||
|
|
||||||
@ -581,19 +581,19 @@ namespace hex::plugin::builtin {
|
|||||||
if (!uploading) {
|
if (!uploading) {
|
||||||
if (ImGui::Button("hex.builtin.tools.file_uploader.upload"_lang)) {
|
if (ImGui::Button("hex.builtin.tools.file_uploader.upload"_lang)) {
|
||||||
fs::openFileBrowser(fs::DialogMode::Open, {}, [&](auto path) {
|
fs::openFileBrowser(fs::DialogMode::Open, {}, [&](auto path) {
|
||||||
uploadProcess = net.uploadFile("https://api.anonfiles.com/upload", path);
|
uploadProcess = request.uploadFile(path);
|
||||||
currFile = path;
|
currFile = path;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ImGui::Button("hex.builtin.common.cancel"_lang)) {
|
if (ImGui::Button("hex.builtin.common.cancel"_lang)) {
|
||||||
net.cancel();
|
request.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::ProgressBar(net.getProgress(), ImVec2(0, 0), uploading ? nullptr : "Done!");
|
ImGui::ProgressBar(request.getProgress(), ImVec2(0, 0), uploading ? nullptr : "Done!");
|
||||||
|
|
||||||
ImGui::Header("hex.builtin.tools.file_uploader.recent"_lang);
|
ImGui::Header("hex.builtin.tools.file_uploader.recent"_lang);
|
||||||
|
|
||||||
@ -637,9 +637,9 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
if (uploadProcess.valid() && uploadProcess.wait_for(0s) == std::future_status::ready) {
|
if (uploadProcess.valid() && uploadProcess.wait_for(0s) == std::future_status::ready) {
|
||||||
auto response = uploadProcess.get();
|
auto response = uploadProcess.get();
|
||||||
if (response.code == 200) {
|
if (response.getStatusCode() == 200) {
|
||||||
try {
|
try {
|
||||||
auto json = nlohmann::json::parse(response.body);
|
auto json = nlohmann::json::parse(response.getData());
|
||||||
links.push_back({
|
links.push_back({
|
||||||
wolv::util::toUTF8String(currFile.filename()),
|
wolv::util::toUTF8String(currFile.filename()),
|
||||||
json["data"]["file"]["url"]["short"],
|
json["data"]["file"]["url"]["short"],
|
||||||
@ -648,9 +648,9 @@ namespace hex::plugin::builtin {
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
View::showErrorPopup("hex.builtin.tools.file_uploader.invalid_response"_lang);
|
View::showErrorPopup("hex.builtin.tools.file_uploader.invalid_response"_lang);
|
||||||
}
|
}
|
||||||
} else if (response.code == 0) {
|
} else if (response.getStatusCode() == 0) {
|
||||||
// Canceled by user, no action needed
|
// Canceled by user, no action needed
|
||||||
} else View::showErrorPopup(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.code));
|
} else View::showErrorPopup(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.getStatusCode()));
|
||||||
|
|
||||||
uploadProcess = {};
|
uploadProcess = {};
|
||||||
currFile.clear();
|
currFile.clear();
|
||||||
@ -663,19 +663,13 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void drawWikiExplainer() {
|
void drawWikiExplainer() {
|
||||||
static hex::Net net;
|
static HttpRequest request("GET", "");
|
||||||
|
|
||||||
static std::string resultTitle, resultExtract;
|
static std::string resultTitle, resultExtract;
|
||||||
static std::future<Response<std::string>> searchProcess;
|
static std::future<HttpRequest::Result<std::string>> searchProcess;
|
||||||
static bool extendedSearch = false;
|
static bool extendedSearch = false;
|
||||||
|
|
||||||
static auto searchString = [] {
|
std::string searchString;
|
||||||
std::string s;
|
|
||||||
s.reserve(0xFFFF);
|
|
||||||
std::memset(s.data(), 0x00, s.capacity());
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}();
|
|
||||||
|
|
||||||
ImGui::Header("hex.builtin.tools.wiki_explain.control"_lang, true);
|
ImGui::Header("hex.builtin.tools.wiki_explain.control"_lang, true);
|
||||||
|
|
||||||
@ -689,7 +683,8 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
if (startSearch && !searchString.empty()) {
|
if (startSearch && !searchString.empty()) {
|
||||||
searchProcess = net.getString(getWikipediaApiUrl() + "&exintro"s + "&titles="s + net.encode(searchString));
|
request.setUrl(getWikipediaApiUrl() + "&exintro"s + "&titles="s + request.urlEncode(searchString));
|
||||||
|
searchProcess = request.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Header("hex.builtin.tools.wiki_explain.results"_lang);
|
ImGui::Header("hex.builtin.tools.wiki_explain.results"_lang);
|
||||||
@ -705,16 +700,19 @@ namespace hex::plugin::builtin {
|
|||||||
if (searchProcess.valid() && searchProcess.wait_for(0s) == std::future_status::ready) {
|
if (searchProcess.valid() && searchProcess.wait_for(0s) == std::future_status::ready) {
|
||||||
try {
|
try {
|
||||||
auto response = searchProcess.get();
|
auto response = searchProcess.get();
|
||||||
if (response.code != 200) throw std::runtime_error("Invalid response");
|
if (response.getStatusCode() != 200) throw std::runtime_error("Invalid response");
|
||||||
|
|
||||||
auto json = nlohmann::json::parse(response.body);
|
auto json = nlohmann::json::parse(response.getData());
|
||||||
|
|
||||||
resultTitle = json["query"]["pages"][0]["title"].get<std::string>();
|
resultTitle = json["query"]["pages"][0]["title"].get<std::string>();
|
||||||
resultExtract = json["query"]["pages"][0]["extract"].get<std::string>();
|
resultExtract = json["query"]["pages"][0]["extract"].get<std::string>();
|
||||||
|
|
||||||
if (!extendedSearch && resultExtract.ends_with(':')) {
|
if (!extendedSearch && resultExtract.ends_with(':')) {
|
||||||
extendedSearch = true;
|
extendedSearch = true;
|
||||||
searchProcess = net.getString(getWikipediaApiUrl() + "&titles="s + net.encode(searchString));
|
|
||||||
|
request.setUrl(getWikipediaApiUrl() + "&titles="s + request.urlEncode(searchString));
|
||||||
|
searchProcess = request.execute();
|
||||||
|
|
||||||
resultTitle.clear();
|
resultTitle.clear();
|
||||||
resultExtract.clear();
|
resultExtract.clear();
|
||||||
} else {
|
} else {
|
||||||
@ -839,7 +837,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
for (const auto &pattern : overwritePattern) {
|
for (const auto &pattern : overwritePattern) {
|
||||||
for (u64 offset = 0; offset < fileSize; offset += 3) {
|
for (u64 offset = 0; offset < fileSize; offset += 3) {
|
||||||
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
|
file.writeBuffer(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
|
||||||
task.update(offset);
|
task.update(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,7 +964,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
constexpr static auto BufferSize = 0xFF'FFFF;
|
constexpr static auto BufferSize = 0xFF'FFFF;
|
||||||
for (u64 partOffset = 0; partOffset < splitSize; partOffset += BufferSize) {
|
for (u64 partOffset = 0; partOffset < splitSize; partOffset += BufferSize) {
|
||||||
partFile.write(file.readBytes(std::min<u64>(BufferSize, splitSize - partOffset)));
|
partFile.writeVector(file.readVector(std::min<u64>(BufferSize, splitSize - partOffset)));
|
||||||
partFile.flush();
|
partFile.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,7 +1091,7 @@ namespace hex::plugin::builtin {
|
|||||||
constexpr static auto BufferSize = 0xFF'FFFF;
|
constexpr static auto BufferSize = 0xFF'FFFF;
|
||||||
auto inputSize = input.getSize();
|
auto inputSize = input.getSize();
|
||||||
for (u64 inputOffset = 0; inputOffset < inputSize; inputOffset += BufferSize) {
|
for (u64 inputOffset = 0; inputOffset < inputSize; inputOffset += BufferSize) {
|
||||||
output.write(input.readBytes(std::min<u64>(BufferSize, inputSize - inputOffset)));
|
output.writeVector(input.readVector(std::min<u64>(BufferSize, inputSize - inputOffset)));
|
||||||
output.flush();
|
output.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ namespace hex::plugin::builtin {
|
|||||||
.basePath = "bookmarks.json",
|
.basePath = "bookmarks.json",
|
||||||
.required = false,
|
.required = false,
|
||||||
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||||
auto fileContent = tar.read(basePath);
|
auto fileContent = tar.readString(basePath);
|
||||||
if (fileContent.empty())
|
if (fileContent.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ namespace hex::plugin::builtin {
|
|||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
|
|
||||||
bool result = ViewBookmarks::exportBookmarks(provider, data);
|
bool result = ViewBookmarks::exportBookmarks(provider, data);
|
||||||
tar.write(basePath, data.dump(4));
|
tar.writeString(basePath, data.dump(4));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -403,7 +403,7 @@ namespace hex::plugin::builtin {
|
|||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
exportBookmarks(ImHexApi::Provider::get(), json);
|
exportBookmarks(ImHexApi::Provider::get(), json);
|
||||||
|
|
||||||
wolv::io::File(path, wolv::io::File::Mode::Create).write(json.dump(4));
|
wolv::io::File(path, wolv::io::File::Mode::Create).writeString(json.dump(4));
|
||||||
});
|
});
|
||||||
}, []{
|
}, []{
|
||||||
return ImHexApi::Provider::isValid() && !ProviderExtraData::getCurrent().bookmarks.empty();
|
return ImHexApi::Provider::isValid() && !ProviderExtraData::getCurrent().bookmarks.empty();
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
|
|
||||||
#include <wolv/utils/string.hpp>
|
#include <wolv/utils/string.hpp>
|
||||||
|
#include <wolv/io/file.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
@ -31,8 +31,8 @@ namespace hex::plugin::builtin {
|
|||||||
if (!file.is_regular_file()) continue;
|
if (!file.is_regular_file()) continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nlohmann::json content;
|
auto fileData = wolv::io::File(file.path(), wolv::io::File::Mode::Read).readString();
|
||||||
std::ifstream(file.path()) >> content;
|
auto content = nlohmann::json::parse(fileData);
|
||||||
|
|
||||||
for (auto value : content["values"]) {
|
for (auto value : content["values"]) {
|
||||||
Constant constant;
|
Constant constant;
|
||||||
|
@ -33,7 +33,7 @@ namespace hex::plugin::builtin {
|
|||||||
.store = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
.store = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||||
auto &data = ProviderExtraData::get(provider).dataProcessor;
|
auto &data = ProviderExtraData::get(provider).dataProcessor;
|
||||||
|
|
||||||
tar.write(basePath, ViewDataProcessor::saveNodes(data.mainWorkspace).dump(4));
|
tar.writeString(basePath, ViewDataProcessor::saveNodes(data.mainWorkspace).dump(4));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ namespace hex::plugin::builtin {
|
|||||||
[&](const std::fs::path &path) {
|
[&](const std::fs::path &path) {
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||||
if (file.isValid())
|
if (file.isValid())
|
||||||
file.write(ViewDataProcessor::saveNodes(data.mainWorkspace).dump(4));
|
file.writeString(ViewDataProcessor::saveNodes(data.mainWorkspace).dump(4));
|
||||||
});
|
});
|
||||||
}, []{
|
}, []{
|
||||||
auto &data = ProviderExtraData::getCurrent().dataProcessor;
|
auto &data = ProviderExtraData::getCurrent().dataProcessor;
|
||||||
@ -325,7 +325,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto &node = *it;
|
auto &node = *it;
|
||||||
fs::openFileBrowser(fs::DialogMode::Save, { {"hex.builtin.view.data_processor.name"_lang, "hexnode" } }, [&](const std::fs::path &path){
|
fs::openFileBrowser(fs::DialogMode::Save, { {"hex.builtin.view.data_processor.name"_lang, "hexnode" } }, [&](const std::fs::path &path){
|
||||||
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
|
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
|
||||||
outputFile.write(ViewDataProcessor::saveNode(node.get()).dump(4));
|
outputFile.writeString(ViewDataProcessor::saveNode(node.get()).dump(4));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
|
|||||||
.basePath = "hashes.json",
|
.basePath = "hashes.json",
|
||||||
.required = false,
|
.required = false,
|
||||||
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||||
auto fileContent = tar.read(basePath);
|
auto fileContent = tar.readString(basePath);
|
||||||
if (fileContent.empty())
|
if (fileContent.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ namespace hex::plugin::builtin {
|
|||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
|
|
||||||
bool result = ViewHashes::exportHashes(provider, data);
|
bool result = ViewHashes::exportHashes(provider, data);
|
||||||
tar.write(basePath, data.dump(4));
|
tar.writeString(basePath, data.dump(4));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@ namespace hex::plugin::builtin {
|
|||||||
.basePath = "patches.json",
|
.basePath = "patches.json",
|
||||||
.required = false,
|
.required = false,
|
||||||
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||||
auto json = nlohmann::json::parse(tar.read(basePath));
|
auto json = nlohmann::json::parse(tar.readString(basePath));
|
||||||
provider->getPatches() = json["patches"].get<std::map<u64, u8>>();
|
provider->getPatches() = json["patches"].get<std::map<u64, u8>>();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
.store = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
.store = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
json["patches"] = provider->getPatches();
|
json["patches"] = provider->getPatches();
|
||||||
tar.write(basePath, json.dump(4));
|
tar.writeString(basePath, json.dump(4));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -885,7 +885,7 @@ namespace hex::plugin::builtin {
|
|||||||
[this](const auto &path) {
|
[this](const auto &path) {
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||||
|
|
||||||
file.write(wolv::util::trim(this->m_textEditor.GetText()));
|
file.writeString(wolv::util::trim(this->m_textEditor.GetText()));
|
||||||
});
|
});
|
||||||
}, ImHexApi::Provider::isValid);
|
}, ImHexApi::Provider::isValid);
|
||||||
|
|
||||||
@ -1047,7 +1047,7 @@ namespace hex::plugin::builtin {
|
|||||||
else
|
else
|
||||||
sourceCode = ProviderExtraData::get(provider).patternLanguage.sourceCode;
|
sourceCode = ProviderExtraData::get(provider).patternLanguage.sourceCode;
|
||||||
|
|
||||||
tar.write(basePath, wolv::util::trim(sourceCode));
|
tar.writeString(basePath, wolv::util::trim(sourceCode));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
#include <hex/helpers/tar.hpp>
|
#include <hex/helpers/tar.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@ -34,6 +33,8 @@ namespace hex::plugin::builtin {
|
|||||||
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
|
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
|
||||||
this->getWindowOpenState() = true;
|
this->getWindowOpenState() = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this->m_httpRequest.setTimeout(30'0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewStore::drawStore() {
|
void ViewStore::drawStore() {
|
||||||
@ -72,7 +73,7 @@ namespace hex::plugin::builtin {
|
|||||||
entry.downloading = false;
|
entry.downloading = false;
|
||||||
|
|
||||||
auto response = this->m_download.get();
|
auto response = this->m_download.get();
|
||||||
if (response.code == 200) {
|
if (response.isSuccess()) {
|
||||||
entry.installed = true;
|
entry.installed = true;
|
||||||
entry.hasUpdate = false;
|
entry.hasUpdate = false;
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
downloadDoneCallback();
|
downloadDoneCallback();
|
||||||
} else
|
} else
|
||||||
log::error("Download failed! HTTP Code {}", response.code);
|
log::error("Download failed! HTTP Code {}", response.getStatusCode());
|
||||||
|
|
||||||
|
|
||||||
this->m_download = {};
|
this->m_download = {};
|
||||||
@ -143,14 +144,15 @@ namespace hex::plugin::builtin {
|
|||||||
this->m_nodes.clear();
|
this->m_nodes.clear();
|
||||||
this->m_themes.clear();
|
this->m_themes.clear();
|
||||||
|
|
||||||
this->m_apiRequest = this->m_net.getString(ImHexApiURL + "/store"s, 30'0000);
|
this->m_httpRequest.setUrl(ImHexApiURL + "/store"s);
|
||||||
|
this->m_apiRequest = this->m_httpRequest.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewStore::parseResponse() {
|
void ViewStore::parseResponse() {
|
||||||
auto response = this->m_apiRequest.get();
|
auto response = this->m_apiRequest.get();
|
||||||
this->m_requestStatus = response.code == 200 ? RequestStatus::Succeeded : RequestStatus::Failed;
|
this->m_requestStatus = response.isSuccess() ? RequestStatus::Succeeded : RequestStatus::Failed;
|
||||||
if (this->m_requestStatus == RequestStatus::Succeeded) {
|
if (this->m_requestStatus == RequestStatus::Succeeded) {
|
||||||
auto json = nlohmann::json::parse(response.body);
|
auto json = nlohmann::json::parse(response.getData());
|
||||||
|
|
||||||
auto parseStoreEntries = [](auto storeJson, const std::string &name, fs::ImHexPath pathType, std::vector<StoreEntry> &results) {
|
auto parseStoreEntries = [](auto storeJson, const std::string &name, fs::ImHexPath pathType, std::vector<StoreEntry> &results) {
|
||||||
// Check if the response handles the type of files
|
// Check if the response handles the type of files
|
||||||
@ -172,11 +174,10 @@ namespace hex::plugin::builtin {
|
|||||||
if (wolv::io::fs::exists(path) && fs::isPathWritable(folder)) {
|
if (wolv::io::fs::exists(path) && fs::isPathWritable(folder)) {
|
||||||
storeEntry.installed = true;
|
storeEntry.installed = true;
|
||||||
|
|
||||||
std::ifstream file(path, std::ios::in | std::ios::binary);
|
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||||
std::vector<u8> data(wolv::io::fs::getFileSize(path), 0x00);
|
auto bytes = file.readVector();
|
||||||
file.read(reinterpret_cast<char *>(data.data()), data.size());
|
|
||||||
|
|
||||||
auto fileHash = crypt::sha256(data);
|
auto fileHash = crypt::sha256(bytes);
|
||||||
|
|
||||||
// Compare installed file hash with hash of repo file
|
// Compare installed file hash with hash of repo file
|
||||||
if (std::vector(fileHash.begin(), fileHash.end()) != crypt::decode16(storeEntry.hash))
|
if (std::vector(fileHash.begin(), fileHash.end()) != crypt::decode16(storeEntry.hash))
|
||||||
@ -233,7 +234,9 @@ namespace hex::plugin::builtin {
|
|||||||
if (!update || wolv::io::fs::exists(fullPath)) {
|
if (!update || wolv::io::fs::exists(fullPath)) {
|
||||||
downloading = true;
|
downloading = true;
|
||||||
this->m_downloadPath = fullPath;
|
this->m_downloadPath = fullPath;
|
||||||
this->m_download = this->m_net.downloadFile(url, fullPath, 30'0000);
|
|
||||||
|
this->m_httpRequest.setUrl(url);
|
||||||
|
this->m_download = this->m_httpRequest.downloadFile(fullPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace hex::plugin::builtin {
|
|||||||
auto json = api::ThemeManager::exportCurrentTheme(this->m_themeName);
|
auto json = api::ThemeManager::exportCurrentTheme(this->m_themeName);
|
||||||
|
|
||||||
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
|
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
|
||||||
outputFile.write(json.dump(4));
|
outputFile.writeString(json.dump(4));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ namespace hex::plugin::builtin {
|
|||||||
.basePath = "yara.json",
|
.basePath = "yara.json",
|
||||||
.required = false,
|
.required = false,
|
||||||
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
.load = [](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||||
auto fileContent = tar.read(basePath);
|
auto fileContent = tar.readString(basePath);
|
||||||
if (fileContent.empty())
|
if (fileContent.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tar.write(basePath, data.dump(4));
|
tar.writeString(basePath, data.dump(4));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ namespace hex::plugin::builtin {
|
|||||||
ProjectFile::clearPath();
|
ProjectFile::clearPath();
|
||||||
|
|
||||||
if (auto settings = provider->storeSettings(); !settings.is_null())
|
if (auto settings = provider->storeSettings(); !settings.is_null())
|
||||||
recentFile.write(settings.dump(4));
|
recentFile.writeString(settings.dump(4));
|
||||||
|
|
||||||
ProjectFile::setPath(path);
|
ProjectFile::setPath(path);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ TEST_SEQUENCE("FileAccess") {
|
|||||||
wolv::io::File file(FilePath, wolv::io::File::Mode::Create);
|
wolv::io::File file(FilePath, wolv::io::File::Mode::Create);
|
||||||
TEST_ASSERT(file.isValid());
|
TEST_ASSERT(file.isValid());
|
||||||
|
|
||||||
file.write(FileContent);
|
file.writeString(FileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -53,7 +53,7 @@ TEST_SEQUENCE("UTF-8 Path") {
|
|||||||
wolv::io::File file(FilePath, wolv::io::File::Mode::Create);
|
wolv::io::File file(FilePath, wolv::io::File::Mode::Create);
|
||||||
TEST_ASSERT(file.isValid());
|
TEST_ASSERT(file.isValid());
|
||||||
|
|
||||||
file.write(FileContent);
|
file.writeU8String(FileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1,47 +1,47 @@
|
|||||||
#include <hex/test/tests.hpp>
|
#include <hex/test/tests.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/net.hpp>
|
#include <hex/helpers/http_requests.hpp>
|
||||||
#include <wolv/io/file.hpp>
|
#include <wolv/io/file.hpp>
|
||||||
#include <hex/helpers/fs.hpp>
|
#include <hex/helpers/fs.hpp>
|
||||||
|
|
||||||
using namespace std::literals::string_literals;
|
using namespace std::literals::string_literals;
|
||||||
|
|
||||||
TEST_SEQUENCE("StoreAPI") {
|
TEST_SEQUENCE("StoreAPI") {
|
||||||
hex::Net net;
|
hex::HttpRequest request("GET", ImHexApiURL + "/store"s);
|
||||||
|
|
||||||
auto result = net.getString(ImHexApiURL + "/store"s).get();
|
auto result = request.execute().get();
|
||||||
|
|
||||||
if (result.code != 200)
|
if (result.getStatusCode() != 200)
|
||||||
TEST_FAIL();
|
TEST_FAIL();
|
||||||
|
|
||||||
if (result.body.empty())
|
if (result.getData().empty())
|
||||||
TEST_FAIL();
|
TEST_FAIL();
|
||||||
|
|
||||||
TEST_SUCCESS();
|
TEST_SUCCESS();
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_SEQUENCE("TipsAPI") {
|
TEST_SEQUENCE("TipsAPI") {
|
||||||
hex::Net net;
|
hex::HttpRequest request("GET", ImHexApiURL + "/tip"s);
|
||||||
|
|
||||||
auto result = net.getString(ImHexApiURL + "/tip"s).get();
|
auto result = request.execute().get();
|
||||||
|
|
||||||
if (result.code != 200)
|
if (result.getStatusCode() != 200)
|
||||||
TEST_FAIL();
|
TEST_FAIL();
|
||||||
|
|
||||||
if (result.body.empty())
|
if (result.getData().empty())
|
||||||
TEST_FAIL();
|
TEST_FAIL();
|
||||||
|
|
||||||
TEST_SUCCESS();
|
TEST_SUCCESS();
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_SEQUENCE("ContentAPI") {
|
TEST_SEQUENCE("ContentAPI") {
|
||||||
hex::Net net;
|
hex::HttpRequest request("GET", "https://api.werwolv.net/content/imhex/patterns/elf.hexpat");
|
||||||
|
|
||||||
const auto FilePath = std::fs::current_path() / "elf.hexpat";
|
const auto FilePath = std::fs::current_path() / "elf.hexpat";
|
||||||
|
|
||||||
auto result = net.downloadFile("https://api.werwolv.net/content/imhex/patterns/elf.hexpat", FilePath).get();
|
auto result = request.downloadFile(FilePath).get();
|
||||||
|
|
||||||
TEST_ASSERT(result.code == 200);
|
TEST_ASSERT(result.getStatusCode() == 200);
|
||||||
|
|
||||||
wolv::io::File file(FilePath, wolv::io::File::Mode::Read);
|
wolv::io::File file(FilePath, wolv::io::File::Mode::Read);
|
||||||
if (!file.isValid())
|
if (!file.isValid())
|
||||||
|
Loading…
Reference in New Issue
Block a user