#include namespace hex { std::string HttpRequest::s_caCertData; std::string HttpRequest::s_proxyUrl; HttpRequest::HttpRequest(std::string method, std::string url) : m_method(std::move(method)), m_url(std::move(url)) { AT_FIRST_TIME { curl_global_init(CURL_GLOBAL_ALL); }; AT_FINAL_CLEANUP { curl_global_cleanup(); }; this->m_curl = curl_easy_init(); } HttpRequest::~HttpRequest() { curl_easy_cleanup(this->m_curl); } 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, this->m_timeout); curl_easy_setopt(this->m_curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(this->m_curl, CURLOPT_NOPROGRESS, 0L); 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()); } CURLcode HttpRequest::sslCtxFunction(CURL *ctx, void *sslctx, void *userData) { hex::unused(ctx, userData); auto *cfg = static_cast(sslctx); auto crt = static_cast(userData); mbedtls_x509_crt_init(crt); mbedtls_x509_crt_parse(crt, reinterpret_cast(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*>(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(userdata); file.writeBuffer(reinterpret_cast(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(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; } }