/* * Copyright (C) 2026 oxmc / PawletOS * SPDX-License-Identifier: Apache-2.0 */ #include "http.h" #include #include #include namespace pawlet::hwupdate::http { namespace { constexpr long kConnectTimeoutSec = 15; constexpr long kTransferTimeoutSec = 300; constexpr char kUserAgent[] = "pawlethwd/1.0"; size_t WriteToString(char* ptr, size_t size, size_t nmemb, void* userdata) { auto* out = static_cast(userdata); out->append(ptr, size * nmemb); return size * nmemb; } size_t WriteToFile(char* ptr, size_t size, size_t nmemb, void* userdata) { auto* f = static_cast(userdata); return fwrite(ptr, size, nmemb, f) * size; } void ApplyCommon(CURL* c, const std::string& url) { curl_easy_setopt(c, CURLOPT_URL, url.c_str()); curl_easy_setopt(c, CURLOPT_USERAGENT, kUserAgent); curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(c, CURLOPT_MAXREDIRS, 5L); curl_easy_setopt(c, CURLOPT_CONNECTTIMEOUT, kConnectTimeoutSec); curl_easy_setopt(c, CURLOPT_TIMEOUT, kTransferTimeoutSec); curl_easy_setopt(c, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); // HTTPS only, verified against the system CA store. curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 2L); curl_easy_setopt(c, CURLOPT_CAPATH, "/system/etc/security/cacerts"); } } // namespace bool Get(const std::string& url, std::string* body, long* httpCode) { CURL* c = curl_easy_init(); if (!c) return false; body->clear(); ApplyCommon(c, url); curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, WriteToString); curl_easy_setopt(c, CURLOPT_WRITEDATA, body); CURLcode rc = curl_easy_perform(c); if (rc == CURLE_OK && httpCode) { curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, httpCode); } curl_easy_cleanup(c); if (rc != CURLE_OK) { LOG(WARNING) << "hwupdate: GET failed: " << curl_easy_strerror(rc); return false; } return true; } bool Download(const std::string& url, const std::string& destPath) { FILE* f = fopen(destPath.c_str(), "wb"); if (!f) { LOG(ERROR) << "hwupdate: cannot open " << destPath << " for write"; return false; } CURL* c = curl_easy_init(); if (!c) { fclose(f); return false; } ApplyCommon(c, url); curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, WriteToFile); curl_easy_setopt(c, CURLOPT_WRITEDATA, f); CURLcode rc = curl_easy_perform(c); long code = 0; curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &code); curl_easy_cleanup(c); fclose(f); if (rc != CURLE_OK || code != 200) { LOG(WARNING) << "hwupdate: download failed rc=" << curl_easy_strerror(rc) << " http=" << code; remove(destPath.c_str()); return false; } return true; } } // namespace pawlet::hwupdate::http