aboutsummaryrefslogtreecommitdiff
path: root/primedev/mods/autodownload
diff options
context:
space:
mode:
authorJack <66967891+ASpoonPlaysGames@users.noreply.github.com>2024-01-20 22:40:27 +0000
committerGitHub <noreply@github.com>2024-01-20 23:40:27 +0100
commit447cace77f2533e616f82e42787c14f7fcbc039b (patch)
tree152ea76ec2196a808cf3aa0828cbe3436dc0b37d /primedev/mods/autodownload
parent7c9ffa1cabbd03a87a1b8efa1d0db329ba9ecc77 (diff)
downloadNorthstarLauncher-1.22.1-rc2.tar.gz
NorthstarLauncher-1.22.1-rc2.zip
Add and use ScopeGuard (#643)v1.22.1-rc2
Use a scope guard instead of `GOTO` statements for curl cleanup
Diffstat (limited to 'primedev/mods/autodownload')
-rw-r--r--primedev/mods/autodownload/moddownloader.cpp131
1 files changed, 68 insertions, 63 deletions
diff --git a/primedev/mods/autodownload/moddownloader.cpp b/primedev/mods/autodownload/moddownloader.cpp
index 165399e3..80be8d19 100644
--- a/primedev/mods/autodownload/moddownloader.cpp
+++ b/primedev/mods/autodownload/moddownloader.cpp
@@ -1,4 +1,5 @@
#include "moddownloader.h"
+#include "util/utils.h"
#include <rapidjson/fwd.h>
#include <mz_strm_mem.h>
#include <mz.h>
@@ -74,6 +75,7 @@ void ModDownloader::FetchModsListFromAPI()
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, WriteToString);
result = curl_easy_perform(easyhandle);
+ ScopeGuard cleanup([&] { curl_easy_cleanup(easyhandle); });
if (result == CURLcode::CURLE_OK)
{
@@ -82,7 +84,7 @@ void ModDownloader::FetchModsListFromAPI()
else
{
spdlog::error("Fetching mods list failed: {}", curl_easy_strerror(result));
- goto REQUEST_END_CLEANUP;
+ return;
}
// Load mods list into local state
@@ -110,9 +112,6 @@ void ModDownloader::FetchModsListFromAPI()
}
spdlog::info("Done loading verified mods list.");
-
- REQUEST_END_CLEANUP:
- curl_easy_cleanup(easyhandle);
});
requestThread.detach();
}
@@ -170,23 +169,23 @@ std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view
curl_easy_setopt(easyhandle, CURLOPT_XFERINFOFUNCTION, ModDownloader::ModFetchingProgressCallback);
curl_easy_setopt(easyhandle, CURLOPT_XFERINFODATA, this);
result = curl_easy_perform(easyhandle);
+ ScopeGuard cleanup(
+ [&]
+ {
+ curl_easy_cleanup(easyhandle);
+ fclose(fp);
+ });
if (result == CURLcode::CURLE_OK)
{
spdlog::info("Mod archive successfully fetched.");
- goto REQUEST_END_CLEANUP;
+ return std::optional<fs::path>(downloadPath);
}
else
{
spdlog::error("Fetching mod archive failed: {}", curl_easy_strerror(result));
- failed = true;
- goto REQUEST_END_CLEANUP;
+ return std::optional<fs::path>();
}
-
-REQUEST_END_CLEANUP:
- curl_easy_cleanup(easyhandle);
- fclose(fp);
- return failed ? std::optional<fs::path>() : std::optional<fs::path>(downloadPath);
}
bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecksum)
@@ -212,6 +211,22 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
std::vector<char> buffer(bufferSize, '\0');
std::ifstream fp(modPath.generic_string(), std::ios::binary);
+ ScopeGuard cleanup(
+ [&]
+ {
+ if (NULL != hashHandle)
+ {
+ BCryptDestroyHash(hashHandle); // Handle to hash/MAC object which needs to be destroyed
+ }
+
+ if (NULL != algorithmHandle)
+ {
+ BCryptCloseAlgorithmProvider(
+ algorithmHandle, // Handle to the algorithm provider which needs to be closed
+ 0); // Flags
+ }
+ });
+
// Open an algorithm handle
// This sample passes BCRYPT_HASH_REUSABLE_FLAG with BCryptAlgorithmProvider(...) to load a provider which supports reusable hash
status = BCryptOpenAlgorithmProvider(
@@ -222,7 +237,7 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
if (!NT_SUCCESS(status))
{
modState.state = MOD_CORRUPTED;
- goto cleanup;
+ return false;
}
// Obtain the length of the hash
@@ -235,7 +250,6 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
0); // Flags
if (!NT_SUCCESS(status))
{
- // goto cleanup;
modState.state = MOD_CORRUPTED;
return false;
}
@@ -252,7 +266,7 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
if (!NT_SUCCESS(status))
{
modState.state = MOD_CORRUPTED;
- goto cleanup;
+ return false;
}
// Hash archive content
@@ -273,7 +287,7 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
if (!NT_SUCCESS(status))
{
modState.state = MOD_CORRUPTED;
- goto cleanup;
+ return false;
}
}
}
@@ -289,7 +303,7 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
if (!NT_SUCCESS(status))
{
modState.state = MOD_CORRUPTED;
- goto cleanup;
+ return false;
}
// Convert hash to string using bytes raw values
@@ -302,21 +316,6 @@ bool ModDownloader::IsModLegit(fs::path modPath, std::string_view expectedChecks
spdlog::info("Expected checksum: {}", expectedChecksum.data());
spdlog::info("Computed checksum: {}", ss.str());
return expectedChecksum.compare(ss.str()) == 0;
-
-cleanup:
- if (NULL != hashHandle)
- {
- BCryptDestroyHash(hashHandle); // Handle to hash/MAC object which needs to be destroyed
- }
-
- if (NULL != algorithmHandle)
- {
- BCryptCloseAlgorithmProvider(
- algorithmHandle, // Handle to the algorithm provider which needs to be closed
- 0); // Flags
- }
-
- return false;
}
bool ModDownloader::IsModAuthorized(std::string_view modName, std::string_view modVersion)
@@ -367,11 +366,20 @@ void ModDownloader::ExtractMod(fs::path modPath)
fs::path modDirectory;
file = unzOpen(modPath.generic_string().c_str());
+ ScopeGuard cleanup(
+ [&]
+ {
+ if (unzClose(file) != MZ_OK)
+ {
+ spdlog::error("Failed closing mod archive after extraction.");
+ }
+ });
+
if (file == NULL)
{
spdlog::error("Cannot open archive located at {}.", modPath.generic_string());
modState.state = FAILED_READING_ARCHIVE;
- goto EXTRACTION_CLEANUP;
+ return;
}
unz_global_info64 gi;
@@ -381,7 +389,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Failed getting information from archive (error code: {})", status);
modState.state = FAILED_READING_ARCHIVE;
- goto EXTRACTION_CLEANUP;
+ return;
}
// Update state
@@ -414,7 +422,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Parent directory ({}) creation failed.", fileDestination.parent_path().generic_string());
modState.state = FAILED_WRITING_TO_DISK;
- goto EXTRACTION_CLEANUP;
+ return;
}
}
@@ -426,7 +434,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Directory creation failed: {}", ec.message());
modState.state = FAILED_WRITING_TO_DISK;
- goto EXTRACTION_CLEANUP;
+ return;
}
}
// ...else create file
@@ -437,7 +445,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("File \"{}\" was not found in archive.", zipFilename);
modState.state = FAILED_READING_ARCHIVE;
- goto EXTRACTION_CLEANUP;
+ return;
}
// Create file
@@ -452,7 +460,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Could not open file {} from archive.", zipFilename);
modState.state = FAILED_READING_ARCHIVE;
- goto EXTRACTION_CLEANUP;
+ return;
}
// Create destination file
@@ -461,7 +469,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Failed creating destination file.");
modState.state = FAILED_WRITING_TO_DISK;
- goto EXTRACTION_CLEANUP;
+ return;
}
// Allocate memory for buffer
@@ -470,7 +478,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("Error while allocating memory.");
modState.state = FAILED_WRITING_TO_DISK;
- goto EXTRACTION_CLEANUP;
+ return;
}
// Extract file to destination
@@ -501,7 +509,7 @@ void ModDownloader::ExtractMod(fs::path modPath)
{
spdlog::error("An error occurred during file extraction (code: {})", err);
modState.state = FAILED_WRITING_TO_DISK;
- goto EXTRACTION_CLEANUP;
+ return;
}
err = unzCloseCurrentFile(file);
if (err != UNZ_OK)
@@ -522,16 +530,10 @@ void ModDownloader::ExtractMod(fs::path modPath)
if (status != UNZ_OK)
{
spdlog::error("Error while browsing archive files (error code: {}).", status);
- goto EXTRACTION_CLEANUP;
+ return;
}
}
}
-
-EXTRACTION_CLEANUP:
- if (unzClose(file) != MZ_OK)
- {
- spdlog::error("Failed closing mod archive after extraction.");
- }
}
void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
@@ -548,6 +550,22 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
{
fs::path archiveLocation;
+ ScopeGuard cleanup(
+ [&]
+ {
+ try
+ {
+ remove(archiveLocation);
+ }
+ catch (const std::exception& a)
+ {
+ spdlog::error("Error while removing downloaded archive: {}", a.what());
+ }
+
+ modState.state = DONE;
+ spdlog::info("Done downloading {}.", modName);
+ });
+
// Download mod archive
std::string expectedHash = verifiedMods[modName].versions[modVersion].checksum;
std::optional<fs::path> fetchingResult = FetchModFromDistantStore(std::string_view(modName), std::string_view(modVersion));
@@ -555,31 +573,18 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
{
spdlog::error("Something went wrong while fetching archive, aborting.");
modState.state = MOD_FETCHING_FAILED;
- goto REQUEST_END_CLEANUP;
+ return;
}
archiveLocation = fetchingResult.value();
if (!IsModLegit(archiveLocation, std::string_view(expectedHash)))
{
spdlog::warn("Archive hash does not match expected checksum, aborting.");
modState.state = MOD_CORRUPTED;
- goto REQUEST_END_CLEANUP;
+ return;
}
// Extract downloaded mod archive
ExtractMod(archiveLocation);
-
- REQUEST_END_CLEANUP:
- try
- {
- remove(archiveLocation);
- }
- catch (const std::exception& a)
- {
- spdlog::error("Error while removing downloaded archive: {}", a.what());
- }
-
- modState.state = DONE;
- spdlog::info("Done downloading {}.", modName);
});
requestThread.detach();