From 8cedeecceccfb4fac31fc15ede56bbbac460e959 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 19 Nov 2023 13:53:34 -0800 Subject: [PATCH 01/32] Self patching Mac application --- CMakeLists.txt | 1 + Sources/Plasma/Apps/plClient/CMakeLists.txt | 1 + .../Apps/plClient/Mac-Cocoa/PLSPatcher.h | 3 +- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 126 +++++++++++++++++- .../Plasma/Apps/plClient/Mac-Cocoa/main.mm | 24 +++- Sources/Plasma/CoreLib/plFileSystem.cpp | 4 + .../Plasma/FeatureLib/pfPatcher/pfPatcher.cpp | 56 ++++++-- .../FeatureLib/pfPatcher/plManifests.cpp | 16 +++ cmake/Findlibarchive.cmake | 43 ++++++ vcpkg.json | 4 + 10 files changed, 264 insertions(+), 14 deletions(-) create mode 100644 cmake/Findlibarchive.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e7f806e3bf..d45d0067d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ find_package(ZLIB REQUIRED) if(APPLE) find_package(Security) find_package(Metal) + find_package(libarchive REQUIRED) elseif(UNIX) find_package(LIBSECRET) find_package(Uuid REQUIRED) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index bd42ba35e5..5cd3918767 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -246,6 +246,7 @@ target_link_libraries( CURL::libcurl "$<$:-framework Cocoa>" "$<$:-framework QuartzCore>" + "$<$:archive>" ) target_include_directories(plClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h index 43fa529572..08cf3d6770 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h @@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)patcher:(PLSPatcher*)patcher beganDownloadOfFile:(NSString*)file; - (void)patcher:(PLSPatcher*)patcher updatedProgress:(NSString*)progressMessage withBytes:(NSUInteger)bytes outOf:(uint64_t)totalBytes; -- (void)patcherCompleted:(PLSPatcher*)patcher; +- (void)patcherCompleted:(PLSPatcher*)patcher didSelfPatch:(BOOL)selfPatched; - (void)patcherCompletedWithError:(PLSPatcher*)patcher error:(NSError*)error; @end @@ -60,6 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @property(weak) id delegate; @property(readonly) BOOL selfPatched; +- (NSURL *)completeSelfPatch; - (void)start; @end diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 552df1776e..7416bf42eb 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -43,6 +43,8 @@ #import "PLSPatcher.h" #import "NSString+StringTheory.h" +#include +#include #include #include @@ -61,6 +63,7 @@ void IOnPatchComplete(ENetError result, const ST::string& msg); void IOnProgressTick(uint64_t curBytes, uint64_t totalBytes, const ST::string& status); void IOnDownloadBegin(const plFileName& file); + void ISelfPatch(const plFileName& file); }; @interface PLSPatcher () @@ -68,6 +71,7 @@ @interface PLSPatcher () @property pfPatcher* patcher; @property NSTimer* networkPumpTimer; @property Patcher cppPatcher; +@property NSURL* updatedClientURL; @end @implementation PLSPatcher @@ -88,6 +92,7 @@ - (id)init _patcher->OnCompletion(std::bind(&Patcher::IOnPatchComplete, _cppPatcher, std::placeholders::_1, std::placeholders::_2)); _patcher->OnFileDownloadDesired(IApproveDownload); + _patcher->OnSelfPatch(std::bind(&Patcher::ISelfPatch, _cppPatcher, std::placeholders::_1)); self.networkPumpTimer = [NSTimer timerWithTimeInterval:1.0 / 1000.0 repeats:true @@ -106,6 +111,35 @@ - (void)start self.patcher->Start(); } +- (NSURL *)completeSelfPatch +{ + NSString* destinationPath = [NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]; + NSURL *destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; + + if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { + // need to swap + + char originalPath[PATH_MAX] = {0}; + [self.updatedClientURL.path getFileSystemRepresentation:originalPath maxLength:sizeof(originalPath)]; + + char newPath[PATH_MAX] = {0}; + [destinationURL.path getFileSystemRepresentation:newPath maxLength:sizeof(newPath)]; + + renamex_np(newPath, originalPath, RENAME_SWAP); + + // delete the old version - this is very likely us + // we want to terminate after. Our bundle will no longer be valid. + [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; + return destinationURL; + } else { + // no executable already present! Just move things into place. + [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:nil]; + return destinationURL; + } + + return nil; +} + void Patcher::IOnDownloadBegin(const plFileName& file) { NSString* fileName = [NSString stringWithSTString:file.AsString()]; @@ -139,13 +173,103 @@ bool IApproveDownload(const plFileName& file) return extExcludeList.find(file.GetFileExt()) == extExcludeList.end(); } +static la_ssize_t copy_data(struct archive *ar, struct archive *aw) +{ + la_ssize_t r; + const void *buff; + size_t size; + la_int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r < ARCHIVE_OK) + return (r); + r = archive_write_data_block(aw, buff, size, offset); + if (r < ARCHIVE_OK) { + fprintf(stderr, "%s\n", archive_error_string(aw)); + return (r); + } + } +} + +void Patcher::ISelfPatch(const plFileName& file) +{ + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int flags; + la_ssize_t r; + + /* Select which attributes we want to restore. */ + flags = ARCHIVE_EXTRACT_TIME; + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + + a = archive_read_new(); + archive_read_support_format_all(a); + archive_read_support_filter_all(a); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); + archive_write_disk_set_standard_lookup(ext); + if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) + exit(1); + + plFileSystem::Unlink(plManifest::PatcherExecutable()); + + NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:nil]; + NSURL *outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; + [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:nil]; + ST::string outputPath = [outputURL.path STString]; + + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r < ARCHIVE_OK) + fprintf(stderr, "%s\n", archive_error_string(a)); + if (r < ARCHIVE_WARN) + exit(1); + const char* currentFile = archive_entry_pathname(entry); + auto fullOutputPath = outputPath + "/" + currentFile; + archive_entry_set_pathname(entry, fullOutputPath.c_str()); + r = archive_write_header(ext, entry); + if (r < ARCHIVE_OK) + fprintf(stderr, "%s\n", archive_error_string(ext)); + else if (archive_entry_size(entry) > 0) { + r = copy_data(a, ext); + if (r < ARCHIVE_OK) + fprintf(stderr, "%s\n", archive_error_string(ext)); + if (r < ARCHIVE_WARN) + exit(1); + } + r = archive_write_finish_entry(ext); + if (r < ARCHIVE_OK) + fprintf(stderr, "%s\n", archive_error_string(ext)); + if (r < ARCHIVE_WARN) + exit(1); + } + archive_read_close(a); + archive_read_free(a); + archive_write_close(ext); + archive_write_free(ext); + + plFileSystem::Unlink(file); + + PLSPatcher* patcher = parent; + parent.updatedClientURL = outputURL; +} + void Patcher::IOnPatchComplete(ENetError result, const ST::string& msg) { [parent.networkPumpTimer invalidate]; if (IS_NET_SUCCESS(result)) { PLSPatcher* patcher = parent; dispatch_async(dispatch_get_main_queue(), ^{ - [patcher.delegate patcherCompleted:patcher]; + [patcher.delegate patcherCompleted:patcher + didSelfPatch:(patcher.updatedClientURL != nil)]; }); } else { NSString* msgString = [NSString stringWithSTString:msg]; diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index 0101728f20..347c559eca 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -152,7 +152,8 @@ @interface AppDelegate : NSWindowController Date: Mon, 8 Jan 2024 21:28:37 -0800 Subject: [PATCH 02/32] Feedback from code review --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 32 +++++++++---------- .../Plasma/Apps/plClient/Mac-Cocoa/main.mm | 4 +-- .../Plasma/FeatureLib/pfPatcher/pfPatcher.cpp | 2 +- .../FeatureLib/pfPatcher/plManifests.cpp | 12 +++---- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 7416bf42eb..d8a114af31 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -175,23 +175,23 @@ bool IApproveDownload(const plFileName& file) static la_ssize_t copy_data(struct archive *ar, struct archive *aw) { - la_ssize_t r; - const void *buff; - size_t size; - la_int64_t offset; - - for (;;) { - r = archive_read_data_block(ar, &buff, &size, &offset); - if (r == ARCHIVE_EOF) - return (ARCHIVE_OK); - if (r < ARCHIVE_OK) - return (r); - r = archive_write_data_block(aw, buff, size, offset); - if (r < ARCHIVE_OK) { - fprintf(stderr, "%s\n", archive_error_string(aw)); - return (r); + la_ssize_t r; + const void *buff; + size_t size; + la_int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return (ARCHIVE_OK); + if (r < ARCHIVE_OK) + return (r); + r = archive_write_data_block(aw, buff, size, offset); + if (r < ARCHIVE_OK) { + fprintf(stderr, "%s\n", archive_error_string(aw)); + return (r); + } } - } } void Patcher::ISelfPatch(const plFileName& file) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index 347c559eca..37fc214ebb 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -355,8 +355,8 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notification NetCommConnect(); [[PLSServerStatus sharedStatus] loadServerStatus]; - BOOL didPatch = cmdParser.IsSpecified(kArgNoSelfPatch); - if (gDataServerLocal || didPatch) { + BOOL skipPatch = cmdParser.IsSpecified(kArgNoSelfPatch); + if (gDataServerLocal || skipPatch) { [self initializeClient]; } else { [self prepatch]; diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp index 42bbb062f5..ad5dfc956d 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp @@ -573,7 +573,7 @@ void pfPatcherWorker::IHashFile(pfPatcherQueuedFile& file) // Check to see if ours matches if (file.fFlags & kBundle) { -#if HS_BUILD_FOR_MACOS +#ifdef HS_BUILD_FOR_MACOS // If this is a Mac app bundle, MD5 the executable. The executable will hold the // code signing hash - and thus unique the entire bundle. diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp index a27defc259..5b3ff1afe1 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp @@ -54,7 +54,7 @@ Mead, WA 99021 plFileName plManifest::ClientExecutable() { -#if HS_BUILD_FOR_MACOS +#ifdef HS_BUILD_FOR_MACOS return MANIFEST("plClient.app", "UruExplorer.app"); #else return MANIFEST("plClient.exe", "UruExplorer.exe"); @@ -63,7 +63,7 @@ plFileName plManifest::ClientExecutable() plFileName plManifest::PatcherExecutable() { -#if HS_BUILD_FOR_MACOS +#ifdef HS_BUILD_FOR_MACOS return MANIFEST("plClient.app", "UruExplorer.app"); #else return MANIFEST("plUruLauncher.exe", "UruLauncher.exe"); @@ -72,8 +72,8 @@ plFileName plManifest::PatcherExecutable() ST::string plManifest::ClientManifest() { -#if HS_BUILD_FOR_MACOS - return MANIFEST("MacThinInternal", "MacThinExternal"); +#ifdef HS_BUILD_FOR_MACOS + return MANIFEST("macThinInternal", "macThinExternal"); #else return MANIFEST("ThinInternal", "ThinExternal"); #endif @@ -81,8 +81,8 @@ ST::string plManifest::ClientManifest() ST::string plManifest::ClientImageManifest() { -#if HS_BUILD_FOR_MACOS - return MANIFEST("MacInternal", "MacExternal"); +#ifdef HS_BUILD_FOR_MACOS + return MANIFEST("macInternal", "macExternal"); #else return MANIFEST("Internal", "External"); #endif From eb840092c05039e83a18fa65c8f0f57fa25d1da6 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Fri, 26 Jan 2024 22:04:09 -0800 Subject: [PATCH 03/32] Externalizing Mac bundle executable finding --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 22 +++++++ .../Plasma/FeatureLib/pfPatcher/pfPatcher.cpp | 60 ++++++------------- .../Plasma/FeatureLib/pfPatcher/pfPatcher.h | 13 ++++ 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index d8a114af31..e4249b4afd 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -49,6 +49,7 @@ #include #include "HeadSpin.h" +#include "hsDarwin.h" #include "hsTimer.h" #include "pfPatcher/pfPatcher.h" @@ -64,6 +65,7 @@ void IOnProgressTick(uint64_t curBytes, uint64_t totalBytes, const ST::string& status); void IOnDownloadBegin(const plFileName& file); void ISelfPatch(const plFileName& file); + plFileName IFindBundleExe(const plFileName& file); }; @interface PLSPatcher () @@ -93,6 +95,7 @@ - (id)init std::placeholders::_2)); _patcher->OnFileDownloadDesired(IApproveDownload); _patcher->OnSelfPatch(std::bind(&Patcher::ISelfPatch, _cppPatcher, std::placeholders::_1)); + _patcher->OnFindBundleExe(std::bind(&Patcher::IFindBundleExe, _cppPatcher, std::placeholders::_1)); self.networkPumpTimer = [NSTimer timerWithTimeInterval:1.0 / 1000.0 repeats:true @@ -286,4 +289,23 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) } } +plFileName Patcher::IFindBundleExe(const plFileName& clientPath) +{ + // If this is a Mac app bundle, MD5 the executable. The executable will hold the + // code signing hash - and thus unique the entire bundle. + + @autoreleasepool { + NSURL* bundleURL = [NSURL fileURLWithPath:[NSString stringWithSTString:clientPath.AsString()]]; + NSBundle* bundle = [NSBundle bundleWithURL:bundleURL]; + NSURL* executableURL = [bundle executableURL]; + + if (executableURL) { + NSString* executablePath = [executableURL path]; + return plFileName([[executableURL path] STString]); + } + + return clientPath; + } +} + @end diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp index ad5dfc956d..f44d5a2534 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp @@ -48,7 +48,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "HeadSpin.h" #include "plFileSystem.h" -#include "hsDarwin.h" #include "hsStream.h" #include "hsThread.h" #include "hsTimer.h" @@ -170,6 +169,7 @@ struct pfPatcherWorker : public hsThread hsSemaphore fFileSignal; pfPatcher::CompletionFunc fOnComplete; + pfPatcher::FindBundleExeFunc fFindBundleExe; pfPatcher::FileDownloadFunc fFileBeginDownload; pfPatcher::FileDesiredFunc fFileDownloadDesired; pfPatcher::FileDownloadFunc fFileDownloaded; @@ -572,50 +572,19 @@ void pfPatcherWorker::IHashFile(pfPatcherQueuedFile& file) } // Check to see if ours matches + plFileName clientPathForComparison = file.fClientPath; if (file.fFlags & kBundle) { -#ifdef HS_BUILD_FOR_MACOS - // If this is a Mac app bundle, MD5 the executable. The executable will hold the - // code signing hash - and thus unique the entire bundle. - - CFURLRef bundleURL = CFURLCreateWithFileSystemPath(nullptr, CFStringCreateWithSTString(file.fClientPath.AsString()), kCFURLPOSIXPathStyle, true); - CFBundleRef bundle = CFBundleCreate(nullptr, bundleURL); - CFAutorelease(bundleURL); - - if (bundle) { - CFAutorelease(bundle); - - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - - if (executableURL) { - // Ugh, CFBundleCopyExecutableURL returns a relative path from inside the app bundle. - // Sanitize. - CFURLRef fullExecutableURL = CFURLCreateFilePathURL(nullptr, executableURL, nullptr); - CFStringRef executablePath = CFURLCopyFileSystemPath(fullExecutableURL, kCFURLPOSIXPathStyle); - - plFileName path(STStringFromCFString(executablePath)); - plMD5Checksum cliMD5(path); - - CFRelease(executablePath); - CFRelease(executableURL); - - if (cliMD5 == file.fChecksum) { - WhitelistFile(file.fClientPath, false); - return; - } - } + bool whitelistBundle = true; + if (fFindBundleExe) { + clientPathForComparison = fFindBundleExe(clientPathForComparison); } -#else - WhitelistFile(file.fClientPath, false); - return; -#endif - } else { - plFileInfo mine(file.fClientPath); - if (mine.FileSize() == file.fFileSize) { - plMD5Checksum cliMD5(file.fClientPath); - if (cliMD5 == file.fChecksum) { - WhitelistFile(file.fClientPath, false); - return; - } + } + plFileInfo mine(clientPathForComparison); + if (mine.FileSize() == file.fFileSize) { + plMD5Checksum cliMD5(clientPathForComparison); + if (cliMD5 == file.fChecksum) { + WhitelistFile(file.fClientPath, false); + return; } } @@ -733,6 +702,11 @@ pfPatcher::~pfPatcher() { } // =================================================== +void pfPatcher::OnFindBundleExe(FindBundleExeFunc vb) +{ + fWorker->fFindBundleExe = std::move(vb); +} + void pfPatcher::OnCompletion(CompletionFunc cb) { fWorker->fOnComplete = std::move(cb); diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h index 602091ea2a..0863033dab 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h @@ -50,6 +50,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnNetBase/pnNbError.h" class plFileName; +class plFilePath; +class plMD5Checksum; class plStatusLog; class hsStream; @@ -84,9 +86,20 @@ class pfPatcher /** Represents a function that takes (bytesDLed, totalBytes, statsStr) as a progress indicator. */ typedef std::function ProgressTickFunc; + + /** Represents a function that takes (const plFileName&, hsStream*) on game code discovery. + * You are responsible for closing and deleting the provided stream. + */ + typedef std::function FindBundleExeFunc; pfPatcher(); ~pfPatcher(); + + /** Set a callback that will be fired when the patcher downloads an updated redistributable. Such as + * the Visual C++ runtime (vcredist_x86.exe). You are responsible for installing it. + * \remarks This will be called from the network thread. + */ + void OnFindBundleExe(FindBundleExeFunc cb); /** Set a callback that will be fired when the patcher finishes its dirty work. * \remarks This may be called from any thread, so make sure your callback is From 0367fa7b154e165da2c0decd748cde4ae858981f Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 3 Feb 2024 18:17:25 -0800 Subject: [PATCH 04/32] Apply suggestions from code review Co-authored-by: dgelessus --- .../Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h | 2 +- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 17 ++++------------- .../Plasma/FeatureLib/pfPatcher/pfPatcher.cpp | 1 - 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h index 08cf3d6770..fb6c956512 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h @@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @property(weak) id delegate; @property(readonly) BOOL selfPatched; -- (NSURL *)completeSelfPatch; +- (NSURL*)completeSelfPatch; - (void)start; @end diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index e4249b4afd..ac506f1145 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -117,30 +117,21 @@ - (void)start - (NSURL *)completeSelfPatch { NSString* destinationPath = [NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]; - NSURL *destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; + NSURL* destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { // need to swap - - char originalPath[PATH_MAX] = {0}; - [self.updatedClientURL.path getFileSystemRepresentation:originalPath maxLength:sizeof(originalPath)]; - - char newPath[PATH_MAX] = {0}; - [destinationURL.path getFileSystemRepresentation:newPath maxLength:sizeof(newPath)]; - - renamex_np(newPath, originalPath, RENAME_SWAP); + renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); // delete the old version - this is very likely us // we want to terminate after. Our bundle will no longer be valid. [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; - return destinationURL; } else { // no executable already present! Just move things into place. [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:nil]; - return destinationURL; } - return nil; + return destinationURL; } void Patcher::IOnDownloadBegin(const plFileName& file) @@ -227,7 +218,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:nil]; ST::string outputPath = [outputURL.path STString]; - for (;;) { + while (true) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp index f44d5a2534..20702a0dfd 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp @@ -574,7 +574,6 @@ void pfPatcherWorker::IHashFile(pfPatcherQueuedFile& file) // Check to see if ours matches plFileName clientPathForComparison = file.fClientPath; if (file.fFlags & kBundle) { - bool whitelistBundle = true; if (fFindBundleExe) { clientPathForComparison = fFindBundleExe(clientPathForComparison); } From 76f6e52bc4dd6ce6b134ebf5d1563f9e951259ff Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 15:40:46 -0800 Subject: [PATCH 05/32] Handling self patch copy errors --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.h | 2 +- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 29 ++++++++++++++----- .../Plasma/Apps/plClient/Mac-Cocoa/main.mm | 14 ++++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h index fb6c956512..6e18ecffa2 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h @@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @property(weak) id delegate; @property(readonly) BOOL selfPatched; -- (NSURL*)completeSelfPatch; +- (NSURL*)completeSelfPatch:(NSError **)error; - (void)start; @end diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index ac506f1145..2138b7b5d5 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -114,21 +114,36 @@ - (void)start self.patcher->Start(); } -- (NSURL *)completeSelfPatch +- (NSURL *)completeSelfPatch:(NSError **)error; { NSString* destinationPath = [NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]; NSURL* destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; + NSError* errorInScope; + if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { // need to swap - renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); - - // delete the old version - this is very likely us - // we want to terminate after. Our bundle will no longer be valid. - [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; + int swapError = renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); + if (swapError == 0) { + // delete the old version - this is very likely us + // we want to terminate after. Our bundle will no longer be valid. + [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:&errorInScope]; + } else { + // abort and return an error + errorInScope = [NSError errorWithDomain:NSPOSIXErrorDomain code:swapError userInfo:nil]; + } } else { // no executable already present! Just move things into place. - [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:nil]; + [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:&errorInScope]; + } + + if (errorInScope) { + // Try to clean up if there was an error + [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; + if (error) { + *error = errorInScope; + } + return nil; } return destinationURL; diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index 37fc214ebb..bdac9f5115 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -427,7 +427,19 @@ - (void)patcherCompleted:(PLSPatcher *)patcher didSelfPatch:(BOOL)selfPatched [NSApp endModalSession:self.currentModalSession]; [self.patcherWindow.window close]; if (selfPatched) { - NSURL* finalURL = [patcher completeSelfPatch]; + NSError *error; + NSURL* finalURL = [patcher completeSelfPatch:&error]; + + if (error) { + // uh oh, we couldn't self patch, present the error and bail + // this should be very rare and could be related to permissions issues + // we expect the game directory to be writable by all + NSAlert *errorAlert = [NSAlert alertWithError:error]; + [errorAlert runModal]; + [NSApp terminate:self]; + // return just in case we ever reach here + return; + } // Pass the "we've already patched" argument NSArray* applicationArguments = [[[NSProcessInfo processInfo] arguments] arrayByAddingObject:@"-NoSelfPatch"]; From dfb47507a07e745f28d5f50fea5dac75ecf72e53 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 15:59:35 -0800 Subject: [PATCH 06/32] Cleaning up exit calls in decompression function --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 2138b7b5d5..b3ba3d1174 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -121,6 +121,17 @@ - (NSURL *)completeSelfPatch:(NSError **)error; NSError* errorInScope; + if (!self.updatedClientURL) { + // uh oh - this implies we weren't able to decompress the client + if (error) + { + // Handle as a generic could not read file error. + // Bad compression on the server will require correction on the server end. + *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadNoSuchFileError userInfo:nil]; + } + return; + } + if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { // need to swap int swapError = renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); @@ -205,6 +216,16 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) void Patcher::ISelfPatch(const plFileName& file) { + /* + Note on errors: + This function does not return errors, but a self patch + without a populated updatedClientURL will imply something + went wrong during decompress. + */ + + PLSPatcher* patcher = parent; + patcher.selfPatched = true; + struct archive *a; struct archive *ext; struct archive_entry *entry; @@ -223,8 +244,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); - if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) - exit(1); + if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) { + // couldn't read + return; + } plFileSystem::Unlink(plManifest::PatcherExecutable()); @@ -233,14 +256,18 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:nil]; ST::string outputPath = [outputURL.path STString]; + bool succeeded = true; + while (true) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(a)); - if (r < ARCHIVE_WARN) - exit(1); + if (r < ARCHIVE_WARN) { + succeeded = false; + break; + } const char* currentFile = archive_entry_pathname(entry); auto fullOutputPath = outputPath + "/" + currentFile; archive_entry_set_pathname(entry, fullOutputPath.c_str()); @@ -251,14 +278,18 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) r = copy_data(a, ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); - if (r < ARCHIVE_WARN) - exit(1); + if (r < ARCHIVE_WARN) { + succeeded = false; + break; + } } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) fprintf(stderr, "%s\n", archive_error_string(ext)); - if (r < ARCHIVE_WARN) - exit(1); + if (r < ARCHIVE_WARN) { + succeeded = false; + break; + } } archive_read_close(a); archive_read_free(a); @@ -267,8 +298,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) plFileSystem::Unlink(file); - PLSPatcher* patcher = parent; - parent.updatedClientURL = outputURL; + if (succeeded) + { + parent.updatedClientURL = outputURL; + } } void Patcher::IOnPatchComplete(ENetError result, const ST::string& msg) @@ -278,7 +311,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) PLSPatcher* patcher = parent; dispatch_async(dispatch_get_main_queue(), ^{ [patcher.delegate patcherCompleted:patcher - didSelfPatch:(patcher.updatedClientURL != nil)]; + didSelfPatch:patcher.selfPatched]; }); } else { NSString* msgString = [NSString stringWithSTString:msg]; From 6afdf956f0d340a6cf33fd02069fd3b0465254ea Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 16:02:01 -0800 Subject: [PATCH 07/32] Apply suggestions from code review Co-authored-by: dgelessus --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 2 +- Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index b3ba3d1174..6c9bfd44fa 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -200,7 +200,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) size_t size; la_int64_t offset; - for (;;) { + while (true) { r = archive_read_data_block(ar, &buff, &size, &offset); if (r == ARCHIVE_EOF) return (ARCHIVE_OK); diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index bdac9f5115..a5272f348a 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -421,7 +421,7 @@ - (void)patcher:(PLSPatcher*)patcher beganDownloadOfFile:(NSString*)file [self.patcherWindow patcher:patcher beganDownloadOfFile:file]; } -- (void)patcherCompleted:(PLSPatcher *)patcher didSelfPatch:(BOOL)selfPatched +- (void)patcherCompleted:(PLSPatcher*)patcher didSelfPatch:(BOOL)selfPatched { self.patcher = nil; [NSApp endModalSession:self.currentModalSession]; From 783df85a6071e282a9ba0dcc523f858f21a4a30b Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 16:23:05 -0800 Subject: [PATCH 08/32] Constraining archive types to tar/gzip/bzip --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 6c9bfd44fa..ec08bad9ed 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -239,9 +239,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) flags |= ARCHIVE_EXTRACT_FFLAGS; a = archive_read_new(); - archive_read_support_format_all(a); - archive_read_support_filter_all(a); ext = archive_write_disk_new(); + archive_read_support_format_tar(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_bzip2(a); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) { From 4a3cdac0616212c7c89d68b5b3ea39dd6f5b12c5 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 16:27:57 -0800 Subject: [PATCH 09/32] Code cleanup in Mac client patching --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 22 +++++++++++++------ .../Plasma/FeatureLib/pfPatcher/pfPatcher.h | 10 ++++----- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index ec08bad9ed..04f7e1737e 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -226,9 +226,6 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) PLSPatcher* patcher = parent; patcher.selfPatched = true; - struct archive *a; - struct archive *ext; - struct archive_entry *entry; int flags; la_ssize_t r; @@ -238,11 +235,11 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; - a = archive_read_new(); - ext = archive_write_disk_new(); + struct archive *a = archive_read_new(); archive_read_support_format_tar(a); archive_read_support_filter_gzip(a); archive_read_support_filter_bzip2(a); + struct archive *ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) { @@ -252,13 +249,24 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) plFileSystem::Unlink(plManifest::PatcherExecutable()); - NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:nil]; + NSError *error; + NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; NSURL *outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; - [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:nil]; + [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; + + if (error) { + // Not sure why things would go wrong, we should be able to + // get a writable temp directory. But if we could not, bail. + // Not populating the patched client path will be caught + // later. + return; + } + ST::string outputPath = [outputURL.path STString]; bool succeeded = true; + struct archive_entry *entry; while (true) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h index 0863033dab..348442b78e 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.h @@ -87,17 +87,17 @@ class pfPatcher /** Represents a function that takes (bytesDLed, totalBytes, statsStr) as a progress indicator. */ typedef std::function ProgressTickFunc; - /** Represents a function that takes (const plFileName&, hsStream*) on game code discovery. - * You are responsible for closing and deleting the provided stream. + /** Represents a function that takes (const plFileName&) and returns the executable inside the + * macOS application bundle at that path. */ typedef std::function FindBundleExeFunc; pfPatcher(); ~pfPatcher(); - /** Set a callback that will be fired when the patcher downloads an updated redistributable. Such as - * the Visual C++ runtime (vcredist_x86.exe). You are responsible for installing it. - * \remarks This will be called from the network thread. + /** Set a callback that will be fired when the patcher needs to find an executable file + * within an executable bundle. This only occurs on the macOS client and is + * specific to macOS executable application bundles. */ void OnFindBundleExe(FindBundleExeFunc cb); From 29cf9fd58f7da48195bf6938662a55876a007629 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 16:47:34 -0800 Subject: [PATCH 10/32] Fixing renamex_np error handling --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 04f7e1737e..dada51c2a4 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -134,14 +134,14 @@ - (NSURL *)completeSelfPatch:(NSError **)error; if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { // need to swap - int swapError = renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); - if (swapError == 0) { + BOOL swapSucceeded = renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP) == 0; + if (swapSucceeded) { // delete the old version - this is very likely us // we want to terminate after. Our bundle will no longer be valid. [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:&errorInScope]; } else { // abort and return an error - errorInScope = [NSError errorWithDomain:NSPOSIXErrorDomain code:swapError userInfo:nil]; + errorInScope = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]; } } else { // no executable already present! Just move things into place. From 418c28d812400996078c0111b206a2cd52ecf119 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 18:37:11 -0800 Subject: [PATCH 11/32] Apply suggestions from code review Co-authored-by: dgelessus --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index dada51c2a4..7955eadb0c 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -242,7 +242,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) struct archive *ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); - if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240))) { + if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240)) != ARCHIVE_OK) { // couldn't read return; } @@ -272,7 +272,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) if (r == ARCHIVE_EOF) break; if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(a)); + pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to read bundle archive: {}", archive_error_string(a)); if (r < ARCHIVE_WARN) { succeeded = false; break; @@ -282,11 +282,11 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) archive_entry_set_pathname(entry, fullOutputPath.c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(ext)); + pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext)); else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(ext)); + pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext)); if (r < ARCHIVE_WARN) { succeeded = false; break; @@ -294,7 +294,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(ext)); + pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext)); if (r < ARCHIVE_WARN) { succeeded = false; break; From 9593e8f7a073beb39247e815ba4e15c2d318fea2 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 18:54:35 -0800 Subject: [PATCH 12/32] Adding feedback from code review Co-authored-by: dgelessus --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 7955eadb0c..f5401b1d57 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -129,7 +129,7 @@ - (NSURL *)completeSelfPatch:(NSError **)error; // Bad compression on the server will require correction on the server end. *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadNoSuchFileError userInfo:nil]; } - return; + return nil; } if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { From 0ac9d8dc4ea43fd2ec48de3acf267c60d0911423 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 21:31:39 -0800 Subject: [PATCH 13/32] Adding missing import --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index f5401b1d57..5cca6633d5 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -56,6 +56,7 @@ #include "pfPatcher/plManifests.h" #include "plFileSystem.h" #include "plNetGameLib/plNetGameLib.h" +#include "plStatusLog/plStatusLog.h" class Patcher { From 2a216e2ba68b7b463ca5fc56355c825a5f29f401 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 21:50:00 -0800 Subject: [PATCH 14/32] Adding guard against temp directory create failure createDirectoryAtURL technically is not supposed to take a nil value - guard against this. --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 5cca6633d5..954b92a104 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -252,8 +252,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) NSError *error; NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; - NSURL *outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; - [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; + if (tempDirectory) { + NSURL *outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; + [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; + } if (error) { // Not sure why things would go wrong, we should be able to From 857f05653d7e08c7a4a46ada523337b1bca8b02c Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 22:00:19 -0800 Subject: [PATCH 15/32] Moving variables into while loop --- .../Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 954b92a104..48ce9f1e52 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -196,12 +196,12 @@ bool IApproveDownload(const plFileName& file) static la_ssize_t copy_data(struct archive *ar, struct archive *aw) { - la_ssize_t r; - const void *buff; - size_t size; - la_int64_t offset; - while (true) { + la_ssize_t r; + const void *buff; + size_t size; + la_int64_t offset; + r = archive_read_data_block(ar, &buff, &size, &offset); if (r == ARCHIVE_EOF) return (ARCHIVE_OK); @@ -252,8 +252,9 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) NSError *error; NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; + NSURL *outputURL; if (tempDirectory) { - NSURL *outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; + outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; } From ab84e40df0b23fbb5c2f2bf609983f1bf3b9eb5b Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 17 Feb 2024 22:49:20 -0800 Subject: [PATCH 16/32] Adding error handling for libarchive options --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 48ce9f1e52..d3cb0bf87f 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -237,12 +237,23 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) flags |= ARCHIVE_EXTRACT_FFLAGS; struct archive *a = archive_read_new(); - archive_read_support_format_tar(a); - archive_read_support_filter_gzip(a); - archive_read_support_filter_bzip2(a); struct archive *ext = archive_write_disk_new(); - archive_write_disk_set_options(ext, flags); - archive_write_disk_set_standard_lookup(ext); + + { + int error; + error = archive_read_support_format_tar(a); + hsAssert(error == ARCHIVE_OK, "Unable to set tar format option"); + error = archive_read_support_filter_gzip(a); + hsAssert(error == ARCHIVE_OK, "Unable to set gzip filter"); + error = archive_read_support_filter_bzip2(a); + hsAssert(error == ARCHIVE_OK, "Unable to set bzip filter"); + + error = archive_write_disk_set_options(ext, flags); + hsAssert(error == ARCHIVE_OK, "Unable to set write options"); + error = archive_write_disk_set_standard_lookup(ext); + hsAssert(error == ARCHIVE_OK, "Unable to set write standard lookup"); + } + if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240)) != ARCHIVE_OK) { // couldn't read return; From 6d45c88bbde7d01129b42711b67def1053c9bb05 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 17 Mar 2024 21:21:17 -0700 Subject: [PATCH 17/32] Updating permissions for Mac patcher Removing ARCHIVE_EXTRACT_PERM, adding ARCHIVE_EXTRACT_OWNER, adding ARCHIVE_EXTRACT_XATTR --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index d3cb0bf87f..c88cbc1e6d 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -232,9 +232,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME; - flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_FFLAGS; + flags |= ARCHIVE_EXTRACT_OWNER; + flags |= ARCHIVE_EXTRACT_XATTR; struct archive *a = archive_read_new(); struct archive *ext = archive_write_disk_new(); From 666df0274735390535b6cc7d211f2743d8dd544d Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 17 Mar 2024 21:32:46 -0700 Subject: [PATCH 18/32] Updating xib deployment target It was not set to match the project --- .../plClient/Mac-Cocoa/PLSLoginWindowController.xib | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSLoginWindowController.xib b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSLoginWindowController.xib index ca19b0be2f..beb1a6ea1a 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSLoginWindowController.xib +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSLoginWindowController.xib @@ -1,8 +1,8 @@ - + - - + + @@ -23,7 +23,7 @@ - + @@ -288,7 +288,7 @@ DQ - + @@ -335,6 +335,6 @@ Gw - + From 5d111b994425ca11b5caaf8a9e4137571e46f597 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 17 Mar 2024 21:36:18 -0700 Subject: [PATCH 19/32] Fixing delegate conformance Patcher window controller is a second level delegate - but the signature changed on the completed handler. --- .../Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm index 6889834fd8..95e6382c2f 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm @@ -81,16 +81,17 @@ - (void)patcher:(PLSPatcher*)patcher [NSString stringWithFormat:@"%@/%@", bytesString, totalBytesString]; } -- (void)patcherCompleted:(nonnull PLSPatcher*)patcher +- (void)patcherCompletedWithError:(nonnull PLSPatcher*)patcher error:(nonnull NSError*)error { // intercepted by the application } -- (void)patcherCompletedWithError:(nonnull PLSPatcher*)patcher error:(nonnull NSError*)error +- (void)patcherCompleted:(nonnull PLSPatcher *)patcher didSelfPatch:(BOOL)selfPatched { // intercepted by the application } + - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change From d36917d5bac61732788d3b541c1fb9d5beb380ab Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 16 Jun 2024 21:29:53 -0700 Subject: [PATCH 20/32] Reducing required flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the WoW client’s lead - going to allow files to inherit owner of the user running the application - but the file permissions should be maintained. Could manually 777 everything - but for now we’ll let the tarfile set that. Technically this could cause issues as the permissions of what the installer wrote and what is on disk may diverge - but that won’t effect functionality - only “repair permissions” scans. --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index c88cbc1e6d..fb847e823c 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -232,10 +232,6 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME; - flags |= ARCHIVE_EXTRACT_ACL; - flags |= ARCHIVE_EXTRACT_FFLAGS; - flags |= ARCHIVE_EXTRACT_OWNER; - flags |= ARCHIVE_EXTRACT_XATTR; struct archive *a = archive_read_new(); struct archive *ext = archive_write_disk_new(); From f73413837ff396a83643c7313db53ff7e9e3da7f Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Mon, 17 Jun 2024 22:42:06 -0700 Subject: [PATCH 21/32] Update Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp Co-authored-by: Darryl Pogue --- Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp index 20702a0dfd..9b21746520 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/pfPatcher.cpp @@ -573,10 +573,8 @@ void pfPatcherWorker::IHashFile(pfPatcherQueuedFile& file) // Check to see if ours matches plFileName clientPathForComparison = file.fClientPath; - if (file.fFlags & kBundle) { - if (fFindBundleExe) { - clientPathForComparison = fFindBundleExe(clientPathForComparison); - } + if ((file.fFlags & kBundle) && fFindBundleExe) { + clientPathForComparison = fFindBundleExe(clientPathForComparison); } plFileInfo mine(clientPathForComparison); if (mine.FileSize() == file.fFileSize) { From 50f7d3d08caa8d5244562afc5f3a6c0acb954fde Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Mon, 17 Jun 2024 22:33:18 -0700 Subject: [PATCH 22/32] Updating libarchive target include --- Sources/Plasma/Apps/plClient/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index 5cd3918767..ca17ad37c3 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -246,7 +246,7 @@ target_link_libraries( CURL::libcurl "$<$:-framework Cocoa>" "$<$:-framework QuartzCore>" - "$<$:archive>" + $<$:libarchive::libarchive> ) target_include_directories(plClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") From 5d83030ae228a7f554747c5e70d7a0f4feea60e9 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 23 Jun 2024 20:18:03 -0700 Subject: [PATCH 23/32] Fixing client not terminating on patch error --- Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index a5272f348a..efd8082da1 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -459,9 +459,8 @@ - (void)patcherCompletedWithError:(PLSPatcher*)patcher error:(NSError*)error NSAlert* failureAlert = [NSAlert alertWithError:error]; [failureAlert beginSheetModalForWindow:self.patcherWindow.window completionHandler:^(NSModalResponse returnCode){ - + [NSApp terminate:self]; }]; - [NSApp terminate:self]; } - (void)patcher:(PLSPatcher*)patcher From b0ef2182bddf95d9b282412512dfe703a1df08b4 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 23 Jun 2024 20:51:34 -0700 Subject: [PATCH 24/32] Passing error string through to NSError --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index fb847e823c..5ce38d11b5 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -338,12 +338,15 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) NSString* msgString = [NSString stringWithSTString:msg]; dispatch_async(dispatch_get_main_queue(), ^{ + ST::string errorString = ST::string::from_wchar(NetErrorToString(result)); + NSString* errorNSString = [NSString stringWithSTString:errorString]; [parent.delegate patcherCompletedWithError:parent error:[NSError errorWithDomain:@"PLSPatchErrors" code:result userInfo:@{ - NSLocalizedFailureErrorKey : msgString + NSLocalizedFailureErrorKey : errorNSString, + NSLocalizedFailureReasonErrorKey: msgString }]]; }); } From ab6d0b41629bdf94dc5315e2017e798459971c68 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 30 Jun 2024 22:44:50 -0700 Subject: [PATCH 25/32] Adding executable suffix --- .../Plasma/FeatureLib/pfPatcher/plManifests.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp index 5b3ff1afe1..7e0563ea00 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp @@ -52,21 +52,27 @@ Mead, WA 99021 # define MANIFEST(in, ex) in #endif // PLASMA_EXTERNAL_RELEASE +#if HS_BUILD_FOR_MACOS +# define PL_EXECUTABLE_SUFFIX ".app" +#else +# define PL_EXECUTABLE_SUFFIX ".exe" +#endif + plFileName plManifest::ClientExecutable() { #ifdef HS_BUILD_FOR_MACOS - return MANIFEST("plClient.app", "UruExplorer.app"); + return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); #else - return MANIFEST("plClient.exe", "UruExplorer.exe"); + return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); #endif } plFileName plManifest::PatcherExecutable() { #ifdef HS_BUILD_FOR_MACOS - return MANIFEST("plClient.app", "UruExplorer.app"); + return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); #else - return MANIFEST("plUruLauncher.exe", "UruLauncher.exe"); + return MANIFEST("plUruLauncher" PL_EXECUTABLE_SUFFIX, "UruLauncher" PL_EXECUTABLE_SUFFIX); #endif } From ea2c595273a621a8219254ec868f8b4d8dcc0587 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 30 Jun 2024 22:45:37 -0700 Subject: [PATCH 26/32] Fixes for self patch Deleting entire temporary directory. Also removing redundant unlink - it was causing problems because the unlinked app was getting swapped into the temporary directory. --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 5ce38d11b5..812582fbf7 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -75,6 +75,7 @@ @interface PLSPatcher () @property NSTimer* networkPumpTimer; @property Patcher cppPatcher; @property NSURL* updatedClientURL; +@property NSURL* temporaryDirectory; @end @implementation PLSPatcher @@ -118,7 +119,7 @@ - (void)start - (NSURL *)completeSelfPatch:(NSError **)error; { NSString* destinationPath = [NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]; - NSURL* destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; + NSURL* destinationURL = [NSURL fileURLWithPath:destinationPath]; NSError* errorInScope; @@ -139,7 +140,9 @@ - (NSURL *)completeSelfPatch:(NSError **)error; if (swapSucceeded) { // delete the old version - this is very likely us // we want to terminate after. Our bundle will no longer be valid. - [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:&errorInScope]; + if (self.temporaryDirectory) { + [NSFileManager.defaultManager removeItemAtURL:self.temporaryDirectory error:&errorInScope]; + } } else { // abort and return an error errorInScope = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]; @@ -231,7 +234,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) la_ssize_t r; /* Select which attributes we want to restore. */ - flags = ARCHIVE_EXTRACT_TIME; + flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM; struct archive *a = archive_read_new(); struct archive *ext = archive_write_disk_new(); @@ -256,13 +259,11 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) return; } - plFileSystem::Unlink(plManifest::PatcherExecutable()); - NSError *error; - NSURL *tempDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; + patcher.temporaryDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; NSURL *outputURL; - if (tempDirectory) { - outputURL = [tempDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; + if (patcher.temporaryDirectory) { + outputURL = [patcher.temporaryDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; } From f82cf3198eb4e9ab5e5ff5816fcff5b706dea6ea Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Mon, 1 Jul 2024 00:39:43 -0700 Subject: [PATCH 27/32] Cleaning up executable suffix code --- Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp index 7e0563ea00..1b34683b4e 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp @@ -52,19 +52,17 @@ Mead, WA 99021 # define MANIFEST(in, ex) in #endif // PLASMA_EXTERNAL_RELEASE -#if HS_BUILD_FOR_MACOS +#if HS_BUILD_FOR_APPLE # define PL_EXECUTABLE_SUFFIX ".app" -#else +#elif HS_BUILD_FOR_WIN32 # define PL_EXECUTABLE_SUFFIX ".exe" +#else +# define PL_EXECUTABLE_SUFFIX "" #endif plFileName plManifest::ClientExecutable() { -#ifdef HS_BUILD_FOR_MACOS return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); -#else - return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); -#endif } plFileName plManifest::PatcherExecutable() From 9d5e76ffc508d19e5d8990fd19314bd303dec1ea Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Mon, 8 Jul 2024 21:20:46 -0700 Subject: [PATCH 28/32] Style cleanup --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 37 +++++++++++-------- .../Mac-Cocoa/PLSPatcherWindowController.mm | 1 - Sources/Plasma/CoreLib/plFileSystem.cpp | 3 +- .../FeatureLib/pfPatcher/plManifests.cpp | 16 ++++---- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 812582fbf7..bcde123750 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -125,8 +125,7 @@ - (NSURL *)completeSelfPatch:(NSError **)error; if (!self.updatedClientURL) { // uh oh - this implies we weren't able to decompress the client - if (error) - { + if (error) { // Handle as a generic could not read file error. // Bad compression on the server will require correction on the server end. *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadNoSuchFileError userInfo:nil]; @@ -197,11 +196,11 @@ bool IApproveDownload(const plFileName& file) return extExcludeList.find(file.GetFileExt()) == extExcludeList.end(); } -static la_ssize_t copy_data(struct archive *ar, struct archive *aw) +static la_ssize_t copy_data(struct archive* ar, struct archive* aw) { while (true) { la_ssize_t r; - const void *buff; + const void* buff; size_t size; la_int64_t offset; @@ -212,7 +211,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) return (r); r = archive_write_data_block(aw, buff, size, offset); if (r < ARCHIVE_OK) { - fprintf(stderr, "%s\n", archive_error_string(aw)); + plStatusLog::AddLineSF("%s\n", archive_error_string(aw)); return (r); } } @@ -236,8 +235,8 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) /* Select which attributes we want to restore. */ flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM; - struct archive *a = archive_read_new(); - struct archive *ext = archive_write_disk_new(); + struct archive* a = archive_read_new(); + struct archive* ext = archive_write_disk_new(); { int error; @@ -259,9 +258,14 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) return; } - NSError *error; - patcher.temporaryDirectory = [NSFileManager.defaultManager URLForDirectory:NSItemReplacementDirectory inDomain:NSUserDomainMask appropriateForURL:[NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath] create:YES error:&error]; - NSURL *outputURL; + NSError* error; + NSURL* currentDirectory = [NSURL fileURLWithPath:NSFileManager.defaultManager.currentDirectoryPath]; + patcher.temporaryDirectory = [NSFileManager.defaultManager + URLForDirectory:NSItemReplacementDirectory + inDomain:NSUserDomainMask + appropriateForURL:currentDirectory + create:YES error:&error]; + NSURL* outputURL; if (patcher.temporaryDirectory) { outputURL = [patcher.temporaryDirectory URLByAppendingPathComponent:[NSString stringWithSTString:plManifest::PatcherExecutable().GetFileName()]]; [NSFileManager.defaultManager createDirectoryAtURL:outputURL withIntermediateDirectories:false attributes:nil error:&error]; @@ -272,6 +276,10 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) // get a writable temp directory. But if we could not, bail. // Not populating the patched client path will be caught // later. + archive_read_close(a); + archive_read_free(a); + archive_write_close(ext); + archive_write_free(ext); return; } @@ -279,7 +287,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) bool succeeded = true; - struct archive_entry *entry; + struct archive_entry* entry; while (true) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_EOF) @@ -291,8 +299,8 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) break; } const char* currentFile = archive_entry_pathname(entry); - auto fullOutputPath = outputPath + "/" + currentFile; - archive_entry_set_pathname(entry, fullOutputPath.c_str()); + auto fullOutputPath = plFileName::Join(plFileName(outputPath), plFileName(currentFile)); + archive_entry_set_pathname(entry, fullOutputPath.AsString().c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext)); @@ -320,8 +328,7 @@ static la_ssize_t copy_data(struct archive *ar, struct archive *aw) plFileSystem::Unlink(file); - if (succeeded) - { + if (succeeded) { parent.updatedClientURL = outputURL; } } diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm index 95e6382c2f..d6675e06ec 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcherWindowController.mm @@ -91,7 +91,6 @@ - (void)patcherCompleted:(nonnull PLSPatcher *)patcher didSelfPatch:(BOOL)selfPa // intercepted by the application } - - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change diff --git a/Sources/Plasma/CoreLib/plFileSystem.cpp b/Sources/Plasma/CoreLib/plFileSystem.cpp index d3de746b0d..15b38ba723 100644 --- a/Sources/Plasma/CoreLib/plFileSystem.cpp +++ b/Sources/Plasma/CoreLib/plFileSystem.cpp @@ -84,8 +84,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com ST::string plFileName::GetFileName() const { - if(fName.ends_with("/")) - { + if (fName.ends_with("/")) { return plFileName(fName.before_last('/')).GetFileName(); } ST_ssize_t end = fName.find_last('/'); diff --git a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp index 1b34683b4e..fde7be5e67 100644 --- a/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp +++ b/Sources/Plasma/FeatureLib/pfPatcher/plManifests.cpp @@ -52,25 +52,25 @@ Mead, WA 99021 # define MANIFEST(in, ex) in #endif // PLASMA_EXTERNAL_RELEASE -#if HS_BUILD_FOR_APPLE -# define PL_EXECUTABLE_SUFFIX ".app" -#elif HS_BUILD_FOR_WIN32 -# define PL_EXECUTABLE_SUFFIX ".exe" +#if defined(HS_BUILD_FOR_APPLE) +# define EXECUTABLE_SUFFIX ".app" +#elif defined(HS_BUILD_FOR_WIN32) +# define EXECUTABLE_SUFFIX ".exe" #else -# define PL_EXECUTABLE_SUFFIX "" +# define EXECUTABLE_SUFFIX "" #endif plFileName plManifest::ClientExecutable() { - return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); + return MANIFEST("plClient" EXECUTABLE_SUFFIX, "UruExplorer" EXECUTABLE_SUFFIX); } plFileName plManifest::PatcherExecutable() { #ifdef HS_BUILD_FOR_MACOS - return MANIFEST("plClient" PL_EXECUTABLE_SUFFIX, "UruExplorer" PL_EXECUTABLE_SUFFIX); + return MANIFEST("plClient" EXECUTABLE_SUFFIX, "UruExplorer" EXECUTABLE_SUFFIX); #else - return MANIFEST("plUruLauncher" PL_EXECUTABLE_SUFFIX, "UruLauncher" PL_EXECUTABLE_SUFFIX); + return MANIFEST("plUruLauncher" EXECUTABLE_SUFFIX, "UruLauncher" EXECUTABLE_SUFFIX); #endif } From 6045bf8e446a66c400b5c8e48f3970b3afddf1ec Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Mon, 8 Jul 2024 21:11:41 -0700 Subject: [PATCH 29/32] Removing custom LibArchive check --- CMakeLists.txt | 2 +- Sources/Plasma/Apps/plClient/CMakeLists.txt | 2 +- cmake/Findlibarchive.cmake | 43 --------------------- 3 files changed, 2 insertions(+), 45 deletions(-) delete mode 100644 cmake/Findlibarchive.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d45d0067d4..24f3192654 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,7 @@ find_package(ZLIB REQUIRED) if(APPLE) find_package(Security) find_package(Metal) - find_package(libarchive REQUIRED) + find_package(LibArchive REQUIRED) elseif(UNIX) find_package(LIBSECRET) find_package(Uuid REQUIRED) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index ca17ad37c3..e5f44388df 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -246,7 +246,7 @@ target_link_libraries( CURL::libcurl "$<$:-framework Cocoa>" "$<$:-framework QuartzCore>" - $<$:libarchive::libarchive> + $<$:LibArchive::LibArchive> ) target_include_directories(plClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/cmake/Findlibarchive.cmake b/cmake/Findlibarchive.cmake deleted file mode 100644 index ce4282414c..0000000000 --- a/cmake/Findlibarchive.cmake +++ /dev/null @@ -1,43 +0,0 @@ -include(FindPackageHandleStandardArgs) -include(SelectLibraryConfigurations) - -find_path(libarchive_INCLUDE_DIR - NAMES archive.h -) -find_library(libarchive_LIBRARY_RELEASE NAMES archive libarchive) -find_library(libarchive_LIBRARY_DEBUG NAMES archive libarchive) - -# Cope with vcpkg no longer renaming the debug library. This is needed due to MSVC's STL iterators -# not being ABI compatible from debug to release mode. -if(libwebm_LIBRARY_RELEASE AND NOT libwebm_LIBRARY_DEBUG) - foreach(prefix_path IN LISTS CMAKE_PREFIX_PATH) - if(prefix_path MATCHES "[Dd][Ee][Bb][Uu][Gg]\/?$") - list(APPEND _debug_paths "${prefix_path}") - endif() - if(_debug_paths) - find_library(libarchive_LIBRARY_DEBUG - NAMES archive libarchive archived libarchived - PATHS ${_debug_paths} - PATH_SUFFIXES lib - NO_CMAKE_PATH - ) - endif() - endforeach() -endif() - -select_library_configurations(libarchive) -find_package_handle_standard_args(libarchive REQUIRED_VARS libarchive_INCLUDE_DIR libarchive_LIBRARY) - -if(libarchive_FOUND AND NOT TARGET libarchive::libarchive) - add_library(libarchive::libarchive IMPORTED UNKNOWN) - set_target_properties(libarchive::libarchive PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${libarchive_INCLUDE_DIR}) - if(libarchive_LIBRARY_RELEASE AND libarchive_LIBRARY_DEBUG) - set_target_properties( - libarchive::libarchive PROPERTIES - IMPORTED_LOCATION_DEBUG ${libarchive_LIBRARY_DEBUG} - IMPORTED_LOCATION_RELEASE ${libarchive_LIBRARY_RELEASE} - ) - else() - set_target_properties(libarchive::libarchive PROPERTIES IMPORTED_LOCATION ${libarchive_LIBRARY}) - endif() -endif() From dcd06d9e973e81672924473ef8f06c7d22df5e4e Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Tue, 9 Jul 2024 22:16:05 -0700 Subject: [PATCH 30/32] Apply suggestions from code review Co-authored-by: Adam Johnson --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 4 ++-- Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index bcde123750..0294398388 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -211,7 +211,7 @@ static la_ssize_t copy_data(struct archive* ar, struct archive* aw) return (r); r = archive_write_data_block(aw, buff, size, offset); if (r < ARCHIVE_OK) { - plStatusLog::AddLineSF("%s\n", archive_error_string(aw)); + pfPatcher::GetLog()->AddLine(plStatusLog::kRed, archive_error_string(aw)); return (r); } } @@ -299,7 +299,7 @@ static la_ssize_t copy_data(struct archive* ar, struct archive* aw) break; } const char* currentFile = archive_entry_pathname(entry); - auto fullOutputPath = plFileName::Join(plFileName(outputPath), plFileName(currentFile)); + auto fullOutputPath = plFileName::Join(outputPath, currentFile); archive_entry_set_pathname(entry, fullOutputPath.AsString().c_str()); r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index efd8082da1..2d4e3cb757 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -427,14 +427,14 @@ - (void)patcherCompleted:(PLSPatcher*)patcher didSelfPatch:(BOOL)selfPatched [NSApp endModalSession:self.currentModalSession]; [self.patcherWindow.window close]; if (selfPatched) { - NSError *error; + NSError* error; NSURL* finalURL = [patcher completeSelfPatch:&error]; if (error) { // uh oh, we couldn't self patch, present the error and bail // this should be very rare and could be related to permissions issues // we expect the game directory to be writable by all - NSAlert *errorAlert = [NSAlert alertWithError:error]; + NSAlert* errorAlert = [NSAlert alertWithError:error]; [errorAlert runModal]; [NSApp terminate:self]; // return just in case we ever reach here From 1e4cb16cb5a5a36169cfffb6ba363d3e67a05459 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Tue, 9 Jul 2024 22:29:52 -0700 Subject: [PATCH 31/32] Cleaning up leak on error --- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 0294398388..706bb9f288 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -255,6 +255,9 @@ static la_ssize_t copy_data(struct archive* ar, struct archive* aw) if ((r = archive_read_open_filename(a, file.GetFileName().c_str(), 10240)) != ARCHIVE_OK) { // couldn't read + archive_read_free(a); + archive_write_close(ext); + archive_write_free(ext); return; } From 7dc5c44cd8304af4ac86300f141748cad4edb083 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sat, 13 Jul 2024 20:20:48 -0700 Subject: [PATCH 32/32] Apply suggestions from code review Co-authored-by: Adam Johnson --- Sources/Plasma/Apps/plClient/CMakeLists.txt | 2 +- Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index e5f44388df..8aba861fd3 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -246,7 +246,7 @@ target_link_libraries( CURL::libcurl "$<$:-framework Cocoa>" "$<$:-framework QuartzCore>" - $<$:LibArchive::LibArchive> + $<$:${LibArchive_LIBRARIES}> ) target_include_directories(plClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index 706bb9f288..e6d3011b98 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -305,9 +305,9 @@ static la_ssize_t copy_data(struct archive* ar, struct archive* aw) auto fullOutputPath = plFileName::Join(outputPath, currentFile); archive_entry_set_pathname(entry, fullOutputPath.AsString().c_str()); r = archive_write_header(ext, entry); - if (r < ARCHIVE_OK) + if (r < ARCHIVE_OK) { pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext)); - else if (archive_entry_size(entry) > 0) { + } else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) pfPatcher::GetLog()->AddLineF(plStatusLog::kRed, "Failed to extract file while patching app bundle: {}", archive_error_string(ext));