diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index a6add62bb..454f6a90c 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -157,7 +157,7 @@ A24621410C769D0900088E81 /* trevent.h in Headers */ = {isa = PBXBuildFile; fileRef = A24621350C769CF400088E81 /* trevent.h */; }; A24621420C769D0900088E81 /* trevent.cc in Sources */ = {isa = PBXBuildFile; fileRef = A24621360C769CF400088E81 /* trevent.cc */; }; A247A443114C701800547DFC /* InfoViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = A247A442114C701800547DFC /* InfoViewController.h */; }; - A24F19080A3A790800C9C145 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A24F19070A3A790800C9C145 /* Sparkle.framework */; }; + A24F19080A3A790800C9C145 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A24F19070A3A790800C9C145 /* Sparkle.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; A24F19210A3A796800C9C145 /* Sparkle.framework in Copy Files */ = {isa = PBXBuildFile; fileRef = A24F19070A3A790800C9C145 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A250EEB60E2ED87B00A688E6 /* web in Resources */ = {isa = PBXBuildFile; fileRef = A250EE800E2ED87B00A688E6 /* web */; }; A254853C0EB66CD4004539DA /* codelength.h in Headers */ = {isa = PBXBuildFile; fileRef = A25485390EB66CBB004539DA /* codelength.h */; }; @@ -400,6 +400,7 @@ C3D9062727B7E3E800EF2386 /* psl.c in Sources */ = {isa = PBXBuildFile; fileRef = C3D9061827B7E1DE00EF2386 /* psl.c */; }; C3D9062A27B7EAC600EF2386 /* libpsl.h in Headers */ = {isa = PBXBuildFile; fileRef = C3D9061B27B7E31100EF2386 /* libpsl.h */; }; C3D9062F27B7F7E200EF2386 /* libpsl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C3D9062127B7E3C900EF2386 /* libpsl.a */; }; + C86BCD9928228A9600F45599 /* SparkleProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = C86BCD9828228A9600F45599 /* SparkleProxy.mm */; }; C88771AD2803EE7B005C7523 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C88771A92803EE42005C7523 /* libz.tbd */; }; C88771AE2803EE7C005C7523 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C88771A92803EE42005C7523 /* libz.tbd */; }; C88771AF2803EE7D005C7523 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C88771A92803EE42005C7523 /* libz.tbd */; }; @@ -1180,6 +1181,7 @@ C3D9061B27B7E31100EF2386 /* libpsl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libpsl.h; path = include/libpsl.h; sourceTree = ""; }; C3D9062127B7E3C900EF2386 /* libpsl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpsl.a; sourceTree = BUILT_PRODUCTS_DIR; }; C81E411127F5BABD00652F56 /* CocoaCompatibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CocoaCompatibility.h; sourceTree = ""; }; + C86BCD9828228A9600F45599 /* SparkleProxy.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SparkleProxy.mm; sourceTree = ""; }; C88771A92803EE42005C7523 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; C88771AB2803EE53005C7523 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; C887BEC02807FCE900867D3C /* create.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = create.cc; sourceTree = ""; }; @@ -1393,6 +1395,7 @@ children = ( 32CA4F630368D1EE00C91783 /* Transmission_Prefix.pch */, 29B97316FDCFA39411CA2CEA /* main.mm */, + C86BCD9828228A9600F45599 /* SparkleProxy.mm */, 4DF0C5AA0899190500DD8943 /* Controller.h */, 4DF0C5A90899190500DD8943 /* Controller.mm */, 4DFBC2DD09C0970D00D5C571 /* Torrent.h */, @@ -3012,6 +3015,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C86BCD9928228A9600F45599 /* SparkleProxy.mm in Sources */, A225A4C0187E369C00CDE823 /* ShareToolbarItem.mm in Sources */, A2D77453154CC72B00A62B93 /* WebSeedTableView.mm in Sources */, 8D11072D0486CEB800E47090 /* main.mm in Sources */, diff --git a/macosx/SparkleProxy.mm b/macosx/SparkleProxy.mm new file mode 100644 index 000000000..4993e09a9 --- /dev/null +++ b/macosx/SparkleProxy.mm @@ -0,0 +1,30 @@ +// This file Copyright © 2005-2022 Transmission authors and contributors. +// It may be used under the MIT (SPDX: MIT) license. +// License text can be found in the licenses/ folder. + +#import +#import + +void SUUpdater_checkForUpdates(id self, SEL _cmd, ...) +{ + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert* alert = [[NSAlert alloc] init]; + alert.messageText = @"Sparkle not configured"; + alert.informativeText = [NSString + stringWithFormat:@"App needs to be codesigned for Development to support Sparkle with Hardened Runtime. Alternatively, re-codesign without the Hardened Runtime option: `sudo codesign -s - %@`", + NSBundle.mainBundle.bundleURL.lastPathComponent]; + [alert runModal]; + }); +} + +/// Proxy SUUpdater if isn't registered at program startup due to codesigning. +__attribute__((constructor)) static void registerSUUpdater() +{ + if (!objc_getClass("SUUpdater")) + { + NSLog(@"App is not signed for running Sparkle"); + Class SUUpdaterClass = objc_allocateClassPair(objc_getClass("NSObject"), "SUUpdater", 0); + class_addMethod(SUUpdaterClass, sel_getUid("checkForUpdates:"), (IMP)SUUpdater_checkForUpdates, "v@:@"); + objc_registerClassPair(SUUpdaterClass); + } +}