WebResourceLoader class

IMPORTANT: The class cannot download from https:// sources because OpenSSL is turned off in curl CMakeLists.txt
This commit is contained in:
Vladyslav Baranovskyi
2024-06-16 18:48:05 +03:00
parent 285396f9ce
commit 48607813a5
2 changed files with 118 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
/*
* 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 <fstream>
#include <sstream>
#include <curl/curl.h>
namespace OpenVulkano
{
namespace
{
size_t curlDownloader(void* contents, size_t size, size_t memBlockCount, void* userData)
{
size_t totalSize = size * memBlockCount;
std::vector<char>* buffer = static_cast<std::vector<char>*>(userData);
buffer->insert(buffer->end(), static_cast<char*>(contents), static_cast<char*>(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<std::string> {}(url);
std::string hashedUrl = std::to_string(hash);
return m_cacheDirectory / hashedUrl;
}
Array<char> WebResourceLoader::DownloadResource(const std::string& url)
{
std::vector<char> 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<char>(buffer);
}
bool WebResourceLoader::IsUrl(const std::string& str)
{
return str.find("http://") == 0 || str.find("https://") == 0 || str.find("ftp://") == 0;
}
Array<char> 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");
}
}