/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "WebResourceLoader.hpp" #include "IO/AppFolders.hpp" #include "Base/Utils.hpp" #include "Base/Logger.hpp" #include #include #if __has_include("curl/curl.h") #include #else #pragma message ("Missing curl.h even though HAS_CURL is set") #undef HAS_CURL #endif namespace OpenVulkano { #ifdef HAS_CURL namespace { size_t CurlDownloader(void* contents, size_t size, size_t memBlockCount, void* userData) { size_t totalSize = size * memBlockCount; std::vector* buffer = static_cast*>(userData); buffer->insert(buffer->end(), static_cast(contents), static_cast(contents) + totalSize); return totalSize; } } #endif bool WebResourceLoader::IsUrl(const std::string& str) { return Utils::StartsWith(str, "http://") || Utils::StartsWith(str, "https://") || Utils::StartsWith(str, "ftp://"); } WebResourceLoader::WebResourceLoader() { m_cacheDirectory = AppFolders::GetAppCacheDir() / "resources"; std::filesystem::create_directories(m_cacheDirectory); #ifdef HAS_CURL curl_global_init(CURL_GLOBAL_DEFAULT); #endif } WebResourceLoader::~WebResourceLoader() { #ifdef HAS_CURL curl_global_cleanup(); #endif } std::filesystem::path WebResourceLoader::GetCacheFilePath(const std::string& url) { size_t hash = std::hash {}(url); std::string hashedUrl = std::to_string(hash); return m_cacheDirectory / hashedUrl; } Array WebResourceLoader::DownloadResource(const std::string& url) { std::vector buffer; #ifdef HAS_CURL CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CurlDownloader); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); #ifdef __APPLE__ curl_easy_setopt(curl, CURLOPT_SSLENGINE, "DarwinSSL"); #endif CURLcode result = curl_easy_perform(curl); if (result != CURLE_OK) { std::string error = curl_easy_strerror(result); Logger::APP->error("Failed to download resource: '" + url + "' - " + error); curl_easy_cleanup(curl); return Array(); } curl_easy_cleanup(curl); } std::filesystem::path cacheFilePath = GetCacheFilePath(url); std::ofstream file(cacheFilePath, std::ios::binary); file.write(buffer.data(), buffer.size()); #endif return Array(buffer); } Array WebResourceLoader::GetResource(const std::string& resourceName) { if (IsUrl(resourceName)) { std::filesystem::path cacheFilePath = GetCacheFilePath(resourceName); if (std::filesystem::exists(cacheFilePath)) { return Utils::ReadFile(cacheFilePath.string()); } else { return DownloadResource(resourceName); } } return Array(); } }