/* * 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 #include #include namespace OpenVulkano { 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; } } WebResourceLoader::WebResourceLoader() { m_cacheDirectory = AppFolders::GetAppCacheDir() / "resources"; std::filesystem::create_directories(m_cacheDirectory); curl_global_init(CURL_GLOBAL_DEFAULT); } WebResourceLoader::~WebResourceLoader() { curl_global_cleanup(); } 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; 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) { curl_easy_cleanup(curl); throw std::runtime_error("Failed to download resource: '" + url + "' - " + curl_easy_strerror(result)); } curl_easy_cleanup(curl); } std::filesystem::path cacheFilePath = GetCacheFilePath(url); std::ofstream file(cacheFilePath, std::ios::binary); file.write(buffer.data(), buffer.size()); return Array(buffer); } bool WebResourceLoader::IsUrl(const std::string& str) { return str.find("http://") == 0 || str.find("https://") == 0 || str.find("ftp://") == 0; } 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); } } throw std::runtime_error("Resource name is not a valid URL"); } }