@@ -176,7 +176,7 @@ int ModDownloader::ModFetchingProgressCallback(
176
176
return 0 ;
177
177
}
178
178
179
- std::optional <fs::path> ModDownloader::FetchModFromDistantStore (std::string_view modName, VerifiedModVersion version)
179
+ std::tuple <fs::path, bool > ModDownloader::FetchModFromDistantStore (std::string_view modName, VerifiedModVersion version)
180
180
{
181
181
std::string url = version.downloadLink ;
182
182
std::string archiveName = fs::path (url).filename ().generic_string ();
@@ -190,7 +190,7 @@ std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view
190
190
modState.state = DOWNLOADING;
191
191
192
192
// Download the actual archive
193
- bool failed = false ;
193
+ bool success = false ;
194
194
FILE* fp = fopen (downloadPath.generic_string ().c_str (), " wb" );
195
195
CURLcode result;
196
196
CURL* easyhandle;
@@ -219,13 +219,14 @@ std::optional<fs::path> ModDownloader::FetchModFromDistantStore(std::string_view
219
219
if (result == CURLcode::CURLE_OK)
220
220
{
221
221
spdlog::info (" Mod archive successfully fetched." );
222
- return std::optional<fs::path>(downloadPath) ;
222
+ success = true ;
223
223
}
224
224
else
225
225
{
226
226
spdlog::error (" Fetching mod archive failed: {}" , curl_easy_strerror (result));
227
- return std::optional<fs::path>();
228
227
}
228
+
229
+ return {downloadPath, success};
229
230
}
230
231
231
232
bool ModDownloader::IsModLegit (fs::path modPath, std::string_view expectedChecksum)
@@ -399,11 +400,9 @@ int GetModArchiveSize(unzFile file, unz_global_info64 info)
399
400
return totalSize;
400
401
}
401
402
402
- void ModDownloader::ExtractMod (fs::path modPath, VerifiedModPlatform platform)
403
+ void ModDownloader::ExtractMod (fs::path modPath, fs::path destinationPath, VerifiedModPlatform platform)
403
404
{
404
405
unzFile file;
405
- std::string name;
406
- fs::path modDirectory;
407
406
408
407
file = unzOpen (modPath.generic_string ().c_str ());
409
408
ScopeGuard cleanup (
@@ -445,11 +444,6 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
445
444
return ;
446
445
}
447
446
448
- // Mod directory name (removing the ".zip" fom the archive name)
449
- name = modPath.filename ().string ();
450
- name = name.substr (0 , name.length () - 4 );
451
- modDirectory = GetRemoteModFolderPath () / name;
452
-
453
447
for (int i = 0 ; i < gi.number_entry ; i++)
454
448
{
455
449
char zipFilename[256 ];
@@ -459,7 +453,7 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
459
453
// Extract file
460
454
{
461
455
std::error_code ec;
462
- fs::path fileDestination = modDirectory / zipFilename;
456
+ fs::path fileDestination = destinationPath / zipFilename;
463
457
spdlog::info (" => {}" , fileDestination.generic_string ());
464
458
465
459
// Create parent directory if needed
@@ -589,6 +583,9 @@ void ModDownloader::ExtractMod(fs::path modPath, VerifiedModPlatform platform)
589
583
}
590
584
}
591
585
}
586
+
587
+ // Mod extraction went fine
588
+ modState.state = DONE;
592
589
}
593
590
594
591
void ModDownloader::DownloadMod (std::string modName, std::string modVersion)
@@ -603,11 +600,14 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
603
600
std::thread requestThread (
604
601
[this , modName, modVersion]()
605
602
{
603
+ std::string name;
606
604
fs::path archiveLocation;
605
+ fs::path modDirectory;
607
606
608
607
ScopeGuard cleanup (
609
608
[&]
610
609
{
610
+ // Remove downloaded archive
611
611
try
612
612
{
613
613
remove (archiveLocation);
@@ -617,14 +617,31 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
617
617
spdlog::error (" Error while removing downloaded archive: {}" , a.what ());
618
618
}
619
619
620
+ // Remove mod if auto-download process failed
621
+ if (modState.state != DONE)
622
+ {
623
+ try
624
+ {
625
+ remove_all (modDirectory);
626
+ }
627
+ catch (const std::exception & e)
628
+ {
629
+ spdlog::error (" Error while removing downloaded mod: {}" , e.what ());
630
+ }
631
+ }
632
+
620
633
spdlog::info (" Done cleaning after downloading {}." , modName);
621
634
});
622
635
623
636
// Download mod archive
624
637
VerifiedModVersion fullVersion = verifiedMods[modName].versions [modVersion];
625
638
std::string expectedHash = fullVersion.checksum ;
626
- std::optional<fs::path> fetchingResult = FetchModFromDistantStore (std::string_view (modName), fullVersion);
627
- if (!fetchingResult.has_value ())
639
+
640
+ const std::tuple<fs::path, bool > downloadResult = FetchModFromDistantStore (std::string_view (modName), fullVersion);
641
+ archiveLocation = get<0 >(downloadResult);
642
+ bool downloadSuccessful = get<1 >(downloadResult);
643
+
644
+ if (!downloadSuccessful)
628
645
{
629
646
spdlog::error (" Something went wrong while fetching archive, aborting." );
630
647
if (modState.state != ABORTED)
@@ -633,17 +650,21 @@ void ModDownloader::DownloadMod(std::string modName, std::string modVersion)
633
650
}
634
651
return ;
635
652
}
636
- archiveLocation = fetchingResult. value ();
653
+
637
654
if (!IsModLegit (archiveLocation, std::string_view (expectedHash)))
638
655
{
639
656
spdlog::warn (" Archive hash does not match expected checksum, aborting." );
640
657
modState.state = MOD_CORRUPTED;
641
658
return ;
642
659
}
643
660
661
+ // Mod directory name (removing the ".zip" fom the archive name)
662
+ name = archiveLocation.filename ().string ();
663
+ name = name.substr (0 , name.length () - 4 );
664
+ modDirectory = GetRemoteModFolderPath () / name;
665
+
644
666
// Extract downloaded mod archive
645
- ExtractMod (archiveLocation, fullVersion.platform );
646
- modState.state = DONE;
667
+ ExtractMod (archiveLocation, modDirectory, fullVersion.platform );
647
668
});
648
669
649
670
requestThread.detach ();
0 commit comments