From 74114a3af217187b80d588d81c60fbc606fcb832 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Wed, 3 Sep 2014 09:47:40 -0700 Subject: [PATCH] Updated Sparkle framework --- .../Configurations/ConfigBinaryDelta.xcconfig | 1 - .../Configurations/ConfigCommon.xcconfig | 20 ++- .../Configurations/ConfigFramework.xcconfig | 5 +- .../Configurations/ConfigRelaunch.xcconfig | 3 +- .../Configurations/ConfigTestApp.xcconfig | 1 + .../Configurations/ConfigUnitTest.xcconfig | 4 + .../Configurations/make-release-package.sh | 11 +- .../Configurations/set-git-version-info.sh | 28 ++++ Frameworks/Sparkle/LICENSE | 19 ++- Frameworks/Sparkle/Makefile | 4 +- Frameworks/Sparkle/README.markdown | 15 ++ Frameworks/Sparkle/Sparkle.podspec | 10 +- .../Sparkle/Sparkle.xcodeproj/project.pbxproj | 149 ++++++++++++------ .../xcschemes/Distribution.xcscheme | 96 +++++++++++ .../Sparkle/Sparkle/Autoupdate/Autoupdate.m | 74 ++++----- .../Sparkle/Sparkle/Autoupdate/Autoupdate.pch | 16 -- Frameworks/Sparkle/Sparkle/SUAppcast.h | 4 +- Frameworks/Sparkle/Sparkle/SUAppcast.m | 26 ++- Frameworks/Sparkle/Sparkle/SUAppcastItem.h | 4 +- Frameworks/Sparkle/Sparkle/SUAppcastItem.m | 52 +++--- .../Sparkle/Sparkle/SUAutomaticUpdateDriver.m | 2 +- .../Sparkle/Sparkle/SUBasicUpdateDriver.m | 15 +- .../Sparkle/Sparkle/SUBinaryDeltaApply.m | 2 +- .../Sparkle/Sparkle/SUBinaryDeltaCommon.m | 25 +-- .../Sparkle/Sparkle/SUBinaryDeltaTool.m | 28 +++- .../Sparkle/Sparkle/SUCodeSigningVerifier.m | 2 +- Frameworks/Sparkle/Sparkle/SUConstants.h | 82 ++++++---- Frameworks/Sparkle/Sparkle/SUConstants.m | 47 ++++-- Frameworks/Sparkle/Sparkle/SUDSAVerifier.m | 5 +- Frameworks/Sparkle/Sparkle/SUExport.h | 18 +++ Frameworks/Sparkle/Sparkle/SUHost.m | 20 +-- Frameworks/Sparkle/Sparkle/SUInstaller.m | 5 - Frameworks/Sparkle/Sparkle/SULog.m | 6 +- Frameworks/Sparkle/Sparkle/SUPlainInstaller.m | 18 +-- .../Sparkle/SUPlainInstallerInternals.m | 35 ++-- .../Sparkle/SUStandardVersionComparator.h | 4 +- Frameworks/Sparkle/Sparkle/SUSystemProfiler.m | 35 ++-- .../Sparkle/Sparkle/SUUIBasedUpdateDriver.m | 2 +- Frameworks/Sparkle/Sparkle/SUUpdateAlert.m | 2 +- Frameworks/Sparkle/Sparkle/SUUpdater.h | 33 +--- Frameworks/Sparkle/Sparkle/SUUpdater.m | 10 +- .../Sparkle/SUVersionComparisonProtocol.h | 1 + .../Sparkle/SUVersionDisplayProtocol.h | 2 +- Frameworks/Sparkle/Sparkle/Sparkle-Info.plist | 12 +- Frameworks/Sparkle/Sparkle/Sparkle.h | 6 +- Frameworks/Sparkle/Sparkle/Sparkle.pch | 6 +- .../signed-test-file.txt} | 0 .../test-pubkey.pem} | 0 Frameworks/Sparkle/Tests/SUBinaryDeltaTest.m | 28 ++++ Frameworks/Sparkle/Tests/SUDSAVerifierTest.m | 9 +- Frameworks/Sparkle/Vendor/bsdiff/bspatch.c | 2 +- 51 files changed, 647 insertions(+), 357 deletions(-) create mode 100755 Frameworks/Sparkle/Configurations/set-git-version-info.sh create mode 100644 Frameworks/Sparkle/Sparkle.xcodeproj/xcshareddata/xcschemes/Distribution.xcscheme delete mode 100644 Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.pch create mode 100644 Frameworks/Sparkle/Sparkle/SUExport.h rename Frameworks/Sparkle/Tests/{signed_test_file => Resources/signed-test-file.txt} (100%) rename Frameworks/Sparkle/Tests/{test_pubkey => Resources/test-pubkey.pem} (100%) create mode 100644 Frameworks/Sparkle/Tests/SUBinaryDeltaTest.m diff --git a/Frameworks/Sparkle/Configurations/ConfigBinaryDelta.xcconfig b/Frameworks/Sparkle/Configurations/ConfigBinaryDelta.xcconfig index 6d2095245..912b8190b 100644 --- a/Frameworks/Sparkle/Configurations/ConfigBinaryDelta.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigBinaryDelta.xcconfig @@ -1,4 +1,3 @@ // BinaryDelta tool only PRODUCT_NAME = BinaryDelta -GCC_PREFIX_HEADER = diff --git a/Frameworks/Sparkle/Configurations/ConfigCommon.xcconfig b/Frameworks/Sparkle/Configurations/ConfigCommon.xcconfig index a5c5fbfc8..477cf7463 100644 --- a/Frameworks/Sparkle/Configurations/ConfigCommon.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigCommon.xcconfig @@ -1,6 +1,18 @@ // Common -FINISH_INSTALL_TOOL_NAME = Autoupdate +SPARKLE_BUNDLE_IDENTIFIER = org.andymatuschak.Sparkle +SPARKLE_RELAUNCH_TOOL_NAME = Autoupdate + +SPARKLE_APPEND_VERSION_NUMBER = 1 + +// Sparkle usually doesn't allow downgrades as they're usually accidental, but +// if your app has a downgrade function or URL handler, turn this on +SPARKLE_AUTOMATED_DOWNGRADES = 0 + +// If your app file on disk is named "MyApp 1.1b4", Sparkle usually updates it +// in place, giving you an app named 1.1b4 that is actually 1.2. Turn the +// following on to always reset the name back to "MyApp": +SPARKLE_NORMALIZE_INSTALLED_APPLICATION_NAME = 0 SPARKLE_VERSION_MAJOR = 1 SPARKLE_VERSION_MINOR = 8 @@ -10,11 +22,13 @@ SPARKLE_VERSION = $(SPARKLE_VERSION_MAJOR).$(SPARKLE_VERSION_MINOR).$(SPARKLE_VE CURRENT_PROJECT_VERSION = $(SPARKLE_VERSION) ALWAYS_SEARCH_USER_PATHS = NO GCC_PRECOMPILE_PREFIX_HEADER = YES -GCC_PREFIX_HEADER = $(SDKROOT)/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h +GCC_PREFIX_HEADER = Sparkle/Sparkle.pch +GCC_SYMBOLS_PRIVATE_EXTERN = YES +GCC_INLINES_ARE_PRIVATE_EXTERN = YES ARCHS = $(ARCHS_STANDARD) MACOSX_DEPLOYMENT_TARGET = 10.7 -GCC_PREPROCESSOR_DEFINITIONS = FINISH_INSTALL_TOOL_NAME=$(FINISH_INSTALL_TOOL_NAME) +GCC_PREPROCESSOR_DEFINITIONS = SPARKLE_BUNDLE_IDENTIFIER=\"$(SPARKLE_BUNDLE_IDENTIFIER)\" SPARKLE_RELAUNCH_TOOL_NAME=\"$(SPARKLE_RELAUNCH_TOOL_NAME)\" CLANG_ENABLE_OBJC_ARC = YES // Enable warnings diff --git a/Frameworks/Sparkle/Configurations/ConfigFramework.xcconfig b/Frameworks/Sparkle/Configurations/ConfigFramework.xcconfig index a0528768d..a2f4058aa 100644 --- a/Frameworks/Sparkle/Configurations/ConfigFramework.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigFramework.xcconfig @@ -1,12 +1,11 @@ // Framework only -INSTALL_PATH = @loader_path/../Frameworks +DYLIB_INSTALL_NAME_BASE = @rpath DYLIB_COMPATIBILITY_VERSION = 1.6 DYLIB_CURRENT_VERSION = $(SPARKLE_VERSION_MAJOR).$(SPARKLE_VERSION_MINOR).$(SPARKLE_VERSION_PATCH) PRODUCT_NAME = Sparkle WRAPPER_EXTENSION = framework FRAMEWORK_VERSION = A INFOPLIST_FILE = Sparkle/Sparkle-Info.plist -GCC_PREFIX_HEADER = Sparkle/Sparkle.pch -SKIP_INSTALL = YES +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BUILDING_SPARKLE=1 OTHER_LDFLAGS = -Wl,-U,_NSURLQuarantinePropertiesKey diff --git a/Frameworks/Sparkle/Configurations/ConfigRelaunch.xcconfig b/Frameworks/Sparkle/Configurations/ConfigRelaunch.xcconfig index ee339f012..1537a724f 100644 --- a/Frameworks/Sparkle/Configurations/ConfigRelaunch.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigRelaunch.xcconfig @@ -1,8 +1,7 @@ // Relaunch Tool only INFOPLIST_FILE = Sparkle/Autoupdate/Autoupdate-Info.plist -PRODUCT_NAME = $(FINISH_INSTALL_TOOL_NAME) +PRODUCT_NAME = $(SPARKLE_RELAUNCH_TOOL_NAME) SKIP_INSTALL = YES -GCC_PREFIX_HEADER = Sparkle/Autoupdate/Autoupdate.pch ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon OTHER_LDFLAGS = -Wl,-U,_NSURLQuarantinePropertiesKey diff --git a/Frameworks/Sparkle/Configurations/ConfigTestApp.xcconfig b/Frameworks/Sparkle/Configurations/ConfigTestApp.xcconfig index 35e7e5433..db13e9e71 100644 --- a/Frameworks/Sparkle/Configurations/ConfigTestApp.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigTestApp.xcconfig @@ -5,3 +5,4 @@ PRODUCT_NAME = Sparkle Test App WRAPPER_EXTENSION = app ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon CLANG_ENABLE_OBJC_ARC = NO +LD_RUNPATH_SEARCH_PATHS = @executable_path/../Frameworks diff --git a/Frameworks/Sparkle/Configurations/ConfigUnitTest.xcconfig b/Frameworks/Sparkle/Configurations/ConfigUnitTest.xcconfig index baaf48201..73900ecae 100644 --- a/Frameworks/Sparkle/Configurations/ConfigUnitTest.xcconfig +++ b/Frameworks/Sparkle/Configurations/ConfigUnitTest.xcconfig @@ -3,4 +3,8 @@ INFOPLIST_FILE = Tests/SparkleTests-Info.plist PRODUCT_NAME = Sparkle Unit Tests WRAPPER_EXTENSION = xctest +OTHER_CFLAGS = $(inherited) -iframework"$(DEVELOPER_FRAMEWORKS_DIR)" -iframework"$(PLATFORM_DIR)/Developer/Library/Frameworks" +GCC_SYMBOLS_PRIVATE_EXTERN = NO WARNING_CFLAGS = $(inherited) -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments +FRAMEWORK_SEARCH_PATHS = $(inherited) $(DEVELOPER_FRAMEWORKS_DIR) +LD_RUNPATH_SEARCH_PATHS = @loader_path/../Frameworks diff --git a/Frameworks/Sparkle/Configurations/make-release-package.sh b/Frameworks/Sparkle/Configurations/make-release-package.sh index de8001c47..98cdd7b6b 100755 --- a/Frameworks/Sparkle/Configurations/make-release-package.sh +++ b/Frameworks/Sparkle/Configurations/make-release-package.sh @@ -9,11 +9,16 @@ if [ "$ACTION" = "" ] ; then cp "$SRCROOT/CHANGELOG" "$SRCROOT/LICENSE" "$SRCROOT/Resources/SampleAppcast.xml" "$CONFIGURATION_BUILD_DIR/staging" cp -R "$SRCROOT/bin" "$CONFIGURATION_BUILD_DIR/staging" cp "$CONFIGURATION_BUILD_DIR/BinaryDelta" "$CONFIGURATION_BUILD_DIR/staging/bin" - cp -R "$CONFIGURATION_BUILD_DIR/BinaryDelta.dSYM" "$CONFIGURATION_BUILD_DIR/staging/bin" cp -R "$CONFIGURATION_BUILD_DIR/Sparkle Test App.app" "$CONFIGURATION_BUILD_DIR/staging" - cp -R "$CONFIGURATION_BUILD_DIR/Sparkle Test App.app.dSYM" "$CONFIGURATION_BUILD_DIR/staging" cp -R "$CONFIGURATION_BUILD_DIR/Sparkle.framework" "$CONFIGURATION_BUILD_DIR/staging" - cp -R "$CONFIGURATION_BUILD_DIR/Sparkle.framework.dSYM" "$CONFIGURATION_BUILD_DIR/staging" + + # Only copy dSYMs for Release builds, but don't check for the presence of the actual files + # because missing dSYMs in a release build SHOULD trigger a build failure + if [ "$CONFIGURATION" = "Release" ] ; then + cp -R "$CONFIGURATION_BUILD_DIR/BinaryDelta.dSYM" "$CONFIGURATION_BUILD_DIR/staging/bin" + cp -R "$CONFIGURATION_BUILD_DIR/Sparkle Test App.app.dSYM" "$CONFIGURATION_BUILD_DIR/staging" + cp -R "$CONFIGURATION_BUILD_DIR/Sparkle.framework.dSYM" "$CONFIGURATION_BUILD_DIR/staging" + fi cd "$CONFIGURATION_BUILD_DIR/staging" # Sorted file list groups similar files together, which improves tar compression diff --git a/Frameworks/Sparkle/Configurations/set-git-version-info.sh b/Frameworks/Sparkle/Configurations/set-git-version-info.sh new file mode 100755 index 000000000..8a79052c3 --- /dev/null +++ b/Frameworks/Sparkle/Configurations/set-git-version-info.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +if ! which -s git ; then + exit 0 +fi + +if [ -z "$SRCROOT" ] || \ + [ -z "$BUILT_PRODUCTS_DIR" ] || \ + [ -z "$INFOPLIST_PATH" ] || \ + [ -z "$CURRENT_PROJECT_VERSION" ]; then + echo "$0: Must be run from Xcode!" 1>&2 + exit 1 +fi + +# Get the current Git master hash +version=$(cd "$SRCROOT" ; git show-ref --abbrev heads/master | awk '{print $1}') +if [ -z "$version" ] ; then + echo "$0: Can't find a Git hash!" 1>&2 + exit 0 +fi + +version="$CURRENT_PROJECT_VERSION git-$version" + +# and use it to set the CFBundleShortVersionString value +export PATH="$PATH:/usr/libexec" +PlistBuddy -c "Set :CFBundleShortVersionString '$version'" \ + "$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH" diff --git a/Frameworks/Sparkle/LICENSE b/Frameworks/Sparkle/LICENSE index 63f898704..f91fce3df 100644 --- a/Frameworks/Sparkle/LICENSE +++ b/Frameworks/Sparkle/LICENSE @@ -1,9 +1,9 @@ -© 2006-2013 Andy Matuschak -© 2009-2013 Elgato Systems GmbH. -© 2011-2014 Kornel Lesiński -© 2014 C.W. Betts -© 2014 Petroules Corporation, Sparkle Project contributors -© 2014 Big Nerd Ranch +Copyright (c) 2006-2013 Andy Matuschak. +Copyright (c) 2009-2013 Elgato Systems GmbH. +Copyright (c) 2011-2014 Kornel Lesiński. +Copyright (c) 2014 C.W. Betts. +Copyright (c) 2014 Petroules Corporation. +Copyright (c) 2014 Big Nerd Ranch. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -27,8 +27,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. EXTERNAL LICENSES ================= -bspatch.c and bsdiff.c, from bsdiff 4.3 : © 2003-2005 Colin Percival. -SUDSAVerifier.m: © 2011 Mark Hamlin. +bspatch.c and bsdiff.c, from bsdiff 4.3 : + Copyright (c) 2003-2005 Colin Percival. + +SUDSAVerifier.m: + Copyright (c) 2011 Mark Hamlin. All rights reserved. diff --git a/Frameworks/Sparkle/Makefile b/Frameworks/Sparkle/Makefile index 3e85f3958..8dfd43bc9 100644 --- a/Frameworks/Sparkle/Makefile +++ b/Frameworks/Sparkle/Makefile @@ -9,13 +9,13 @@ localizable-strings: rm Sparkle/en.lproj/Localizable.strings release: - xcodebuild -scheme Distribution -configuration Release -derivedDataPath "$(BUILDDIR)" + xcodebuild -scheme Distribution -configuration Release -derivedDataPath "$(BUILDDIR)" build open -R "$(BUILDDIR)/Build/Products/Release/Sparkle-"*.tar.bz2 build: xcodebuild clean build test: - xcodebuild -target 'Sparkle Unit Tests' -scheme 'Sparkle' test + xcodebuild -scheme Distribution -configuration Debug test travis: test diff --git a/Frameworks/Sparkle/README.markdown b/Frameworks/Sparkle/README.markdown index b73d22eba..912b6ee3f 100644 --- a/Frameworks/Sparkle/README.markdown +++ b/Frameworks/Sparkle/README.markdown @@ -28,3 +28,18 @@ is an easy-to-use software update framework for Cocoa developers. * Optionally sends system information to the server when checking for updates. * Supports bundles, preference panes, plugins, and other non-.app software. Can install .pkg files for more complicated products. * Supports branches due to minimum OS version requirements. + +## Developers + +Building Sparkle requires Xcode 5 or above. + +### API + +Sparkle is built with `-fvisibility=hidden -fvisibility-inlines-hidden` which means no symbols are exported by default. +If you are adding a symbol to the public API you must decorate the declaration with the `SU_EXPORT` macro (grep the source code for examples). + +### Building the distribution package + +`cd` to the root of the Sparkle source tree and run `make release`. Sparkle-*VERSION*.tar.bz2 will be created in a temporary directory and revealed in Finder after the build has completed. + +Alternatively, build the Distribution scheme in the Xcode UI. diff --git a/Frameworks/Sparkle/Sparkle.podspec b/Frameworks/Sparkle/Sparkle.podspec index 9b597f242..36c44bdc3 100644 --- a/Frameworks/Sparkle/Sparkle.podspec +++ b/Frameworks/Sparkle/Sparkle.podspec @@ -1,9 +1,9 @@ Pod::Spec.new do |s| s.name = "Sparkle" - s.version = "1.7.1" + s.version = "1.8.0" s.summary = "A software update framework for OS X" s.description = "Sparkle is an easy-to-use software update framework for Cocoa developers." - s.homepage = "https://github.com/sparkle-project/Sparkle" + s.homepage = "http://sparkle-project.org" s.license = { :type => 'MIT', :file => 'LICENSE' @@ -15,12 +15,12 @@ Pod::Spec.new do |s| 'Jake Petroules' => 'jake.petroules@petroules.com', } - s.platform = :osx - s.source = { :http => "https://github.com/sparkle-project/Sparkle/releases/download/#{s.version}/Sparkle-#{s.version}.zip" } + s.platform = :osx, '10.7' + s.source = { :http => "https://github.com/sparkle-project/Sparkle/releases/download/#{s.version}/Sparkle-#{s.version}.tar.bz2" } s.public_header_files = 'Sparkle.framework/Headers/*.h' s.vendored_framework = 'Sparkle.framework' s.resources = 'Sparkle.framework' s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"${PODS_ROOT}/Sparkle"' } - s.requires_arc = false + s.requires_arc = true end diff --git a/Frameworks/Sparkle/Sparkle.xcodeproj/project.pbxproj b/Frameworks/Sparkle/Sparkle.xcodeproj/project.pbxproj index 30f16159e..245d7a365 100644 --- a/Frameworks/Sparkle/Sparkle.xcodeproj/project.pbxproj +++ b/Frameworks/Sparkle/Sparkle.xcodeproj/project.pbxproj @@ -27,6 +27,18 @@ /* Begin PBXBuildFile section */ 1420DF50196247F900203BB0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1420DF4F196247F900203BB0 /* Images.xcassets */; }; 1420DF51196247F900203BB0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1420DF4F196247F900203BB0 /* Images.xcassets */; }; + 142E0E0019A6954400E4312B /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 142E0E0219A6A14700E4312B /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 142E0E0419A6A26F00E4312B /* Autoupdate.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 55C14BB7136EEF1500649790 /* Autoupdate.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 142E0E0919A83AAC00E4312B /* SUBinaryDeltaTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 142E0E0819A83AAC00E4312B /* SUBinaryDeltaTest.m */; }; + 14652F7C19A9725300959E44 /* SUBinaryDeltaCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8E20FD68CC7005AE3F6 /* SUBinaryDeltaCommon.m */; }; + 14652F7D19A9726700959E44 /* SUBinaryDeltaApply.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8E00FD68CC7005AE3F6 /* SUBinaryDeltaApply.m */; }; + 14652F7E19A9728A00959E44 /* bspatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8DC0FD68CB9005AE3F6 /* bspatch.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + 14652F7F19A973F900959E44 /* SUDSAVerifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 61299A2E09CA2DAB00B7442F /* SUDSAVerifier.m */; }; + 14652F8019A9740F00959E44 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61B5F8F609C4CEB300B25A18 /* Security.framework */; }; + 14652F8119A9744200959E44 /* SUBinaryDeltaCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8E20FD68CC7005AE3F6 /* SUBinaryDeltaCommon.m */; }; + 14652F8219A9746000959E44 /* SULog.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C14F05136EF6DB00649790 /* SULog.m */; }; + 14652F8419A978C200959E44 /* SUExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 14652F8319A9759F00959E44 /* SUExport.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14732BC01960F2C200593899 /* test_app_only_dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 14732BBF1960F0AC00593899 /* test_app_only_dsa_pub.pem */; }; 14732BD019610A0D00593899 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; 14732BD119610A1200593899 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; @@ -38,6 +50,8 @@ 14950072195FCE4B00BC5B5B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; 14950073195FCE4E00BC5B5B /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D6A5FE840307C02AAC07 /* AppKit.framework */; }; 14950075195FDF5900BC5B5B /* SUUpdaterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 14950074195FDF5900BC5B5B /* SUUpdaterTest.m */; }; + 14958C6E19AEBC950061B14F /* signed-test-file.txt in Resources */ = {isa = PBXBuildFile; fileRef = 14958C6B19AEBC530061B14F /* signed-test-file.txt */; }; + 14958C6F19AEBC980061B14F /* test-pubkey.pem in Resources */ = {isa = PBXBuildFile; fileRef = 14958C6C19AEBC610061B14F /* test-pubkey.pem */; }; 3772FEA913DE0B6B00F79537 /* SUVersionDisplayProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 3772FEA813DE0B6B00F79537 /* SUVersionDisplayProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 55C14BD4136EEFCE00649790 /* Autoupdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C14BD3136EEFCE00649790 /* Autoupdate.m */; }; 55C14BD9136EF00C00649790 /* SUStatus.xib in Resources */ = {isa = PBXBuildFile; fileRef = 55C14BD8136EF00C00649790 /* SUStatus.xib */; }; @@ -51,7 +65,6 @@ 55C14F08136EF6DB00649790 /* SULog.m in Sources */ = {isa = PBXBuildFile; fileRef = 55C14F05136EF6DB00649790 /* SULog.m */; }; 55C14F0C136EF6EA00649790 /* SUHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 61EF67550E25B58D00F754E0 /* SUHost.m */; }; 55C14F0D136EF6F200649790 /* SUInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5000DAE88B40026945C /* SUInstaller.m */; }; - 55C14F0F136EF73600649790 /* Autoupdate.pch in Headers */ = {isa = PBXBuildFile; fileRef = 55C14F0E136EF73600649790 /* Autoupdate.pch */; }; 55C14F20136EF84300649790 /* SUStatusController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6196CFE409C71ADE000DC222 /* SUStatusController.m */; }; 55C14F21136EF84D00649790 /* SUPlainInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5040DAE8AB80026945C /* SUPlainInstaller.m */; }; 55C14F22136EF86000649790 /* SUStandardVersionComparator.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A225A30D1C4AC000430CCD /* SUStandardVersionComparator.m */; }; @@ -59,12 +72,10 @@ 55C14F24136EF86F00649790 /* SUPackageInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 618FA5210DAE8E8A0026945C /* SUPackageInstaller.m */; }; 55C14F2A136EF9A900649790 /* SUWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61180BC90D64138900B4E0D1 /* SUWindowController.m */; }; 55C14F32136EFC2400649790 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55C14F31136EFC2400649790 /* SystemConfiguration.framework */; }; - 55C14F3B136EFCB300649790 /* Autoupdate.app in Resources */ = {isa = PBXBuildFile; fileRef = 55C14BB7136EEF1500649790 /* Autoupdate.app */; }; 55C14F7E136F005000649790 /* SUPlainInstallerInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = 61B5F8E509C4CE3C00B25A18 /* SUPlainInstallerInternals.m */; }; 55C14F9A136F045400649790 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61B5F8F609C4CEB300B25A18 /* Security.framework */; }; 55C14FC7136F05E100649790 /* Sparkle.strings in Resources */ = {isa = PBXBuildFile; fileRef = 61AAE8220A321A7F00D8810D /* Sparkle.strings */; }; 5AF9DC3C1981DBEE001EA135 /* SUDSAVerifierTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AF9DC3B1981DBEE001EA135 /* SUDSAVerifierTest.m */; }; - 5D06E8D80FD68C8E005AE3F6 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; }; 5D06E8E90FD68CDB005AE3F6 /* bsdiff.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8DB0FD68CB9005AE3F6 /* bsdiff.c */; settings = {COMPILER_FLAGS = "-w"; }; }; 5D06E8EA0FD68CDB005AE3F6 /* SUBinaryDeltaTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8E30FD68CC7005AE3F6 /* SUBinaryDeltaTool.m */; }; 5D06E8EB0FD68CE4005AE3F6 /* bspatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D06E8DC0FD68CB9005AE3F6 /* bspatch.c */; settings = {COMPILER_FLAGS = "-w"; }; }; @@ -106,7 +117,6 @@ 61299B3609CB04E000B7442F /* Sparkle.h in Headers */ = {isa = PBXBuildFile; fileRef = 61299B3509CB04E000B7442F /* Sparkle.h */; settings = {ATTRIBUTES = (Public, ); }; }; 612DCBAF0D488BC60015DBEA /* SUUpdatePermissionPrompt.h in Headers */ = {isa = PBXBuildFile; fileRef = 612DCBAD0D488BC60015DBEA /* SUUpdatePermissionPrompt.h */; settings = {ATTRIBUTES = (); }; }; 612DCBB00D488BC60015DBEA /* SUUpdatePermissionPrompt.m in Sources */ = {isa = PBXBuildFile; fileRef = 612DCBAE0D488BC60015DBEA /* SUUpdatePermissionPrompt.m */; }; - 61407C390A4099050009F71F /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; }; 6158A1C5137904B300487EC1 /* SUUpdater_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6158A1C4137904B300487EC1 /* SUUpdater_Private.h */; }; 615AE3D00D64DC40001CA7BD /* SUModelTranslation.plist in Resources */ = {isa = PBXBuildFile; fileRef = 615AE3CF0D64DC40001CA7BD /* SUModelTranslation.plist */; }; 6160E7E10D3B4A8800E9CD71 /* NTSynchronousTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 610EC1C00CF3914D00AE239E /* NTSynchronousTask.h */; settings = {ATTRIBUTES = (); }; }; @@ -253,13 +263,33 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 142E0E0119A6A13300E4312B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 142E0E0219A6A14700E4312B /* Sparkle.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 142E0E0319A6A24100E4312B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 12; + files = ( + 142E0E0419A6A26F00E4312B /* Autoupdate.app in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 61B5FB4D09C4E9FA00B25A18 /* Copy Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 61407C390A4099050009F71F /* Sparkle.framework in Copy Frameworks */, + 142E0E0019A6954400E4312B /* Sparkle.framework in Copy Frameworks */, ); name = "Copy Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -280,6 +310,10 @@ 1420DF4D196247B500203BB0 /* build-docs.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-docs.sh"; sourceTree = ""; }; 1420DF4E196247B500203BB0 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Doxyfile; sourceTree = ""; }; 1420DF4F196247F900203BB0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 142E0E0819A83AAC00E4312B /* SUBinaryDeltaTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUBinaryDeltaTest.m; sourceTree = ""; }; + 14652F7919A93E5F00959E44 /* set-git-version-info.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "set-git-version-info.sh"; sourceTree = ""; }; + 14652F8319A9759F00959E44 /* SUExport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SUExport.h; sourceTree = ""; }; + 146EC84E19A68CF8004A50C5 /* Sparkle.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Sparkle.podspec; sourceTree = SOURCE_ROOT; }; 14732BB1195FF6B700593899 /* .clang-format */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".clang-format"; sourceTree = SOURCE_ROOT; }; 14732BB91960EEEE00593899 /* SampleAppcast.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = SampleAppcast.xml; sourceTree = ""; }; 14732BBA1960EF7100593899 /* CHANGELOG */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGELOG; sourceTree = SOURCE_ROOT; }; @@ -290,7 +324,9 @@ 14732BC41960F3FF00593899 /* sign_update.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sign_update.sh; sourceTree = ""; }; 14732BC91960F70A00593899 /* make-release-package.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "make-release-package.sh"; sourceTree = ""; }; 14732BD219610A1800593899 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 14950074195FDF5900BC5B5B /* SUUpdaterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SUUpdaterTest.m; path = Tests/SUUpdaterTest.m; sourceTree = ""; usesTabs = 0; }; + 14950074195FDF5900BC5B5B /* SUUpdaterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUUpdaterTest.m; sourceTree = ""; usesTabs = 0; }; + 14958C6B19AEBC530061B14F /* signed-test-file.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "signed-test-file.txt"; sourceTree = ""; }; + 14958C6C19AEBC610061B14F /* test-pubkey.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "test-pubkey.pem"; sourceTree = ""; }; 3772FEA813DE0B6B00F79537 /* SUVersionDisplayProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUVersionDisplayProtocol.h; sourceTree = ""; }; 4607BEA21948443800EF8DA4 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Sparkle.strings; sourceTree = ""; }; 4607BEA31948443800EF8DA4 /* nb */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = nb; path = nb.lproj/SUAutomaticUpdateAlert.xib; sourceTree = ""; }; @@ -361,10 +397,9 @@ 55C14C18136EF2C700649790 /* zh_TW */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = zh_TW; path = zh_TW.lproj/SUUpdatePermissionPrompt.xib; sourceTree = ""; }; 55C14F04136EF6DB00649790 /* SULog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SULog.h; sourceTree = ""; }; 55C14F05136EF6DB00649790 /* SULog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SULog.m; sourceTree = ""; }; - 55C14F0E136EF73600649790 /* Autoupdate.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Autoupdate.pch; sourceTree = ""; }; 55C14F31136EFC2400649790 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 5AEF45D9189D1CC90030D7DC /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Sparkle.strings; sourceTree = ""; }; - 5AF9DC3B1981DBEE001EA135 /* SUDSAVerifierTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SUDSAVerifierTest.m; path = Tests/SUDSAVerifierTest.m; sourceTree = ""; }; + 5AF9DC3B1981DBEE001EA135 /* SUDSAVerifierTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUDSAVerifierTest.m; sourceTree = ""; }; 5D06E8D00FD68C7C005AE3F6 /* BinaryDelta */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BinaryDelta; sourceTree = BUILT_PRODUCTS_DIR; }; 5D06E8DB0FD68CB9005AE3F6 /* bsdiff.c */ = {isa = PBXFileReference; comments = "-Wno-shorten-64-to-32"; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsdiff.c; sourceTree = ""; }; 5D06E8DC0FD68CB9005AE3F6 /* bspatch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bspatch.c; sourceTree = ""; }; @@ -404,8 +439,8 @@ 6120721009CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUAutomaticUpdateAlert.h; sourceTree = ""; }; 6120721109CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUAutomaticUpdateAlert.m; sourceTree = ""; }; 612279D90DB5470200AB99EA /* Sparkle Unit Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Sparkle Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 612279DA0DB5470200AB99EA /* SparkleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "SparkleTests-Info.plist"; path = "Tests/SparkleTests-Info.plist"; sourceTree = ""; }; - 61227A150DB548B800AB99EA /* SUVersionComparisonTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SUVersionComparisonTest.m; path = Tests/SUVersionComparisonTest.m; sourceTree = ""; }; + 612279DA0DB5470200AB99EA /* SparkleTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SparkleTests-Info.plist"; sourceTree = ""; }; + 61227A150DB548B800AB99EA /* SUVersionComparisonTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUVersionComparisonTest.m; sourceTree = ""; }; 6129984309C9E2DA00B7442F /* SUPlainInstallerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUPlainInstallerInternals.h; sourceTree = ""; }; 61299A2D09CA2DAB00B7442F /* SUDSAVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUDSAVerifier.h; sourceTree = ""; }; 61299A2E09CA2DAB00B7442F /* SUDSAVerifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUDSAVerifier.m; sourceTree = ""; }; @@ -535,7 +570,6 @@ 5D1AF58B0FD7678C0065DB48 /* libxar.1.dylib in Frameworks */, 5D1AF5900FD767AD0065DB48 /* libxml2.dylib in Frameworks */, 5D1AF59A0FD767E50065DB48 /* libz.dylib in Frameworks */, - 5D06E8D80FD68C8E005AE3F6 /* Sparkle.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -546,6 +580,7 @@ 14732BD119610A1200593899 /* AppKit.framework in Frameworks */, 14732BD019610A0D00593899 /* Foundation.framework in Frameworks */, 61FA52880E2D9EA400EF58AD /* Sparkle.framework in Frameworks */, + 14652F8019A9740F00959E44 /* Security.framework in Frameworks */, 14732BD319610A1800593899 /* XCTest.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -717,12 +752,20 @@ path = Sparkle; sourceTree = ""; }; + 14958C7019AEBE350061B14F /* Resources */ = { + isa = PBXGroup; + children = ( + 14958C6B19AEBC530061B14F /* signed-test-file.txt */, + 14958C6C19AEBC610061B14F /* test-pubkey.pem */, + ); + path = Resources; + sourceTree = ""; + }; 55C14BD5136EEFD000649790 /* Autoupdate */ = { isa = PBXGroup; children = ( 55C14BB9136EEF1500649790 /* Autoupdate-Info.plist */, 55C14BD3136EEFCE00649790 /* Autoupdate.m */, - 55C14F0E136EF73600649790 /* Autoupdate.pch */, ); path = Autoupdate; sourceTree = ""; @@ -760,11 +803,13 @@ isa = PBXGroup; children = ( 612279DA0DB5470200AB99EA /* SparkleTests-Info.plist */, + 142E0E0819A83AAC00E4312B /* SUBinaryDeltaTest.m */, 5AF9DC3B1981DBEE001EA135 /* SUDSAVerifierTest.m */, 14950074195FDF5900BC5B5B /* SUUpdaterTest.m */, 61227A150DB548B800AB99EA /* SUVersionComparisonTest.m */, + 14958C7019AEBE350061B14F /* Resources */, ); - name = Tests; + path = Tests; sourceTree = ""; }; 61299B3909CB055000B7442F /* Appcast Support */ = { @@ -823,6 +868,7 @@ 61CFB3280E385186007A1735 /* Sparkle.pch */, 61299A5B09CA6D4500B7442F /* SUConstants.h */, 61299A5F09CA6EB100B7442F /* SUConstants.m */, + 14652F8319A9759F00959E44 /* SUExport.h */, 61EF67580E25C5B400F754E0 /* SUHost.h */, 61EF67550E25B58D00F754E0 /* SUHost.m */, 55C14F04136EF6DB00649790 /* SULog.h */, @@ -912,6 +958,8 @@ FA3AAF3A1050B273004B3130 /* ConfigUnitTestDebug.xcconfig */, FA3AAF391050B273004B3130 /* ConfigUnitTestRelease.xcconfig */, 14732BC91960F70A00593899 /* make-release-package.sh */, + 14652F7919A93E5F00959E44 /* set-git-version-info.sh */, + 146EC84E19A68CF8004A50C5 /* Sparkle.podspec */, ); path = Configurations; sourceTree = ""; @@ -923,7 +971,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 55C14F0F136EF73600649790 /* Autoupdate.pch in Headers */, 611142E910FB1BE5009810AA /* bspatch.h in Headers */, 6160E7E10D3B4A8800E9CD71 /* NTSynchronousTask.h in Headers */, 61299B3609CB04E000B7442F /* Sparkle.h in Headers */, @@ -936,6 +983,7 @@ 5D06E9390FD69271005AE3F6 /* SUBinaryDeltaUnarchiver.h in Headers */, 61B078CE15A5FB6100600039 /* SUCodeSigningVerifier.h in Headers */, 61299A5C09CA6D4500B7442F /* SUConstants.h in Headers */, + 14652F8419A978C200959E44 /* SUExport.h in Headers */, 6102FE4A0E07803800F85D09 /* SUDiskImageUnarchiver.h in Headers */, 61299A2F09CA2DAB00B7442F /* SUDSAVerifier.h in Headers */, 61EF67590E25C5B400F754E0 /* SUHost.h in Headers */, @@ -1010,6 +1058,7 @@ 55C14BB3136EEF1500649790 /* Resources */, 55C14BB4136EEF1500649790 /* Sources */, 55C14BB5136EEF1500649790 /* Frameworks */, + 14652F7B19A945D600959E44 /* Run Script: Set Git Version Info */, ); buildRules = ( ); @@ -1026,7 +1075,6 @@ buildPhases = ( 5D06E8CD0FD68C7C005AE3F6 /* Sources */, 5D06E8CE0FD68C7C005AE3F6 /* Frameworks */, - 5D06E90D0FD68DA3005AE3F6 /* Fix Install Name */, ); buildRules = ( ); @@ -1042,9 +1090,10 @@ isa = PBXNativeTarget; buildConfigurationList = 612279DD0DB5470300AB99EA /* Build configuration list for PBXNativeTarget "Sparkle Unit Tests" */; buildPhases = ( - 612279D40DB5470200AB99EA /* Resources */, 612279D50DB5470200AB99EA /* Sources */, 612279D60DB5470200AB99EA /* Frameworks */, + 14958C6D19AEBC890061B14F /* Resources */, + 142E0E0119A6A13300E4312B /* CopyFiles */, 612279D70DB5470200AB99EA /* ShellScript */, ); buildRules = ( @@ -1082,9 +1131,10 @@ buildPhases = ( 8DC2EF500486A6940098B216 /* Headers */, 8DC2EF520486A6940098B216 /* Resources */, + 142E0E0319A6A24100E4312B /* CopyFiles */, 8DC2EF540486A6940098B216 /* Sources */, 8DC2EF560486A6940098B216 /* Frameworks */, - 6131B1910DDCDE32005215F0 /* Run Script: Set git Version Info */, + 6131B1910DDCDE32005215F0 /* Run Script: Set Git Version Info */, 6195D4B40E40505A00D41A50 /* Run Script: Link fr_CA to fr */, 61E31A85103299750051D188 /* Run Script: Link pt to pt_BR */, ); @@ -1179,6 +1229,15 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 14958C6D19AEBC890061B14F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 14958C6F19AEBC980061B14F /* test-pubkey.pem in Resources */, + 14958C6E19AEBC950061B14F /* signed-test-file.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 55C14BB3136EEF1500649790 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1189,13 +1248,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 612279D40DB5470200AB99EA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 61B5F8FE09C4CEE200B25A18 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1211,7 +1263,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 55C14F3B136EFCB300649790 /* Autoupdate.app in Resources */, 61AAE8280A321A7F00D8810D /* Sparkle.strings in Resources */, 55C14BEE136EF20D00649790 /* SUAutomaticUpdateAlert.xib in Resources */, 615AE3D00D64DC40001CA7BD /* SUModelTranslation.plist in Resources */, @@ -1224,20 +1275,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 5D06E90D0FD68DA3005AE3F6 /* Fix Install Name */ = { + 14652F7B19A945D600959E44 /* Run Script: Set Git Version Info */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Fix Install Name"; + name = "Run Script: Set Git Version Info"; outputPaths = ( - "$(CONFIGURATION_BUILD_DIR)/BinaryDelta", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "install_name_tool -change \"@loader_path/../Frameworks/Sparkle.framework/Versions/A/Sparkle\" \"@loader_path/Sparkle.framework/Versions/A/Sparkle\" \"${CONFIGURATION_BUILD_DIR}/BinaryDelta\""; + shellScript = "\"$SRCROOT/Configurations/set-git-version-info.sh\""; + showEnvVarsInLog = 0; }; 612279D70DB5470200AB99EA /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -1253,19 +1304,19 @@ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; showEnvVarsInLog = 0; }; - 6131B1910DDCDE32005215F0 /* Run Script: Set git Version Info */ = { + 6131B1910DDCDE32005215F0 /* Run Script: Set Git Version Info */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 12; files = ( ); inputPaths = ( ); - name = "Run Script: Set git Version Info"; + name = "Run Script: Set Git Version Info"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; - shellPath = "/usr/bin/env ruby"; - shellScript = "# Xcode auto-versioning script for Subversion\n# by Axel Andersson, modified by Daniel Jalkut to add\n# \"--revision HEAD\" to the svn info line, which allows\n# the latest revision to always be used.\n\nif ENV[\"BUILT_PRODUCTS_DIR\"].nil?\n\tSTDERR.print \"#{$0}: Must be run from Xcode!\"\n\texit(1)\nend\n\n# Get the current Git master hash and use it to set the CFBundleVersion value\nENV[\"PATH\"] = \"/bin:/sw/bin:/usr/local/git/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/opt/local/bin\"\nexit(0) if `type git` == \"\"\nrev = `/usr/bin/env git show-ref --abbrev heads/master`\ninfo = \"#{ENV[\"BUILT_PRODUCTS_DIR\"]}/#{ENV[\"WRAPPER_NAME\"]}/Resources/Info.plist\"\nversion = rev.split(\" \")[0]\n\nif version.nil?\n\tSTDERR.print \"#{$0}: Can't find a Git hash!\"\n\texit(0)\nend\n\ninfo_contents = File.read(info)\nif info_contents.nil?\n\tSTDERR.print \"#{$0}: Can't read in the Info.plist file!\"\n\texit(1)\nend\n\ninfo_contents.sub!(/([\\t ]+CFBundleVersion<\\/key>\\n[\\t ]+).*?(<\\/string>)/, '\\1' + version + '\\2')\nSTDERR.print info_contents\nf = File.open(info, \"w\")\nf.write(info_contents)\nf.close"; + shellPath = /bin/sh; + shellScript = "\"$SRCROOT/Configurations/set-git-version-info.sh\""; showEnvVarsInLog = 0; }; 6195D4B40E40505A00D41A50 /* Run Script: Link fr_CA to fr */ = { @@ -1274,15 +1325,15 @@ files = ( ); inputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)/Resources/fr.lproj", + "$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/fr.lproj", ); name = "Run Script: Link fr_CA to fr"; outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)/Resources/fr_CA.lproj", + "$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/fr_CA.lproj", ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/usr/bin/env sh"; - shellScript = "ln -sfh \"fr.lproj\" \"$BUILT_PRODUCTS_DIR/$WRAPPER_NAME/Resources/fr_CA.lproj\""; + shellScript = "ln -sfh \"fr.lproj\" \"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/fr_CA.lproj\""; showEnvVarsInLog = 0; }; 61E31A85103299750051D188 /* Run Script: Link pt to pt_BR */ = { @@ -1291,15 +1342,15 @@ files = ( ); inputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)/Resources/pt_BR.lproj", + "$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/pt_BR.lproj", ); name = "Run Script: Link pt to pt_BR"; outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)/Resources/pt.lproj", + "$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/pt.lproj", ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/usr/bin/env sh"; - shellScript = "ln -sfh \"pt_BR.lproj\" \"$BUILT_PRODUCTS_DIR/$WRAPPER_NAME/Resources/pt.lproj\""; + shellScript = "ln -sfh \"pt_BR.lproj\" \"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/pt.lproj\""; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1329,6 +1380,9 @@ buildActionMask = 2147483647; files = ( 5D06E8E90FD68CDB005AE3F6 /* bsdiff.c in Sources */, + 14652F7E19A9728A00959E44 /* bspatch.c in Sources */, + 14652F7D19A9726700959E44 /* SUBinaryDeltaApply.m in Sources */, + 14652F7C19A9725300959E44 /* SUBinaryDeltaCommon.m in Sources */, 5D06E8EA0FD68CDB005AE3F6 /* SUBinaryDeltaTool.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1337,7 +1391,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 14652F8119A9744200959E44 /* SUBinaryDeltaCommon.m in Sources */, + 14652F7F19A973F900959E44 /* SUDSAVerifier.m in Sources */, + 14652F8219A9746000959E44 /* SULog.m in Sources */, 5AF9DC3C1981DBEE001EA135 /* SUDSAVerifierTest.m in Sources */, + 142E0E0919A83AAC00E4312B /* SUBinaryDeltaTest.m in Sources */, 14950075195FDF5900BC5B5B /* SUUpdaterTest.m in Sources */, 61227A160DB548B800AB99EA /* SUVersionComparisonTest.m in Sources */, ); @@ -1674,7 +1732,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = FA1941CF0D94A70100DD942E /* ConfigCommonDebug.xcconfig */; buildSettings = { - ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -1717,12 +1774,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = FA3AAF3A1050B273004B3130 /* ConfigUnitTestDebug.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sparkle.framework/Versions/A/Sparkle"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Debug; }; @@ -1730,12 +1781,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = FA3AAF391050B273004B3130 /* ConfigUnitTestRelease.xcconfig */; buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Sparkle.framework/Versions/A/Sparkle"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Release; }; diff --git a/Frameworks/Sparkle/Sparkle.xcodeproj/xcshareddata/xcschemes/Distribution.xcscheme b/Frameworks/Sparkle/Sparkle.xcodeproj/xcshareddata/xcschemes/Distribution.xcscheme new file mode 100644 index 000000000..11b73b52e --- /dev/null +++ b/Frameworks/Sparkle/Sparkle.xcodeproj/xcshareddata/xcschemes/Distribution.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.m b/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.m index fa65de138..b2a651ba1 100644 --- a/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.m +++ b/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.m @@ -20,10 +20,10 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; @interface TerminationListener : NSObject -@property (assign) const char *hostpath; -@property (assign) const char *executablepath; +@property (copy) NSString *hostpath; +@property (copy) NSString *executablepath; @property (assign) pid_t parentprocessid; -@property (assign) const char *folderpath; +@property (copy) NSString *folderpath; @property (copy) NSString *selfPath; @property (copy) NSString *installationPath; @@ -58,26 +58,26 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; @synthesize shouldRelaunch; @synthesize shouldShowUI; -- (instancetype)initWithHostPath:(const char *)inhostpath executablePath:(const char *)execpath parentProcessId:(pid_t)ppid folderPath:(const char *)infolderpath shouldRelaunch:(BOOL)relaunch shouldShowUI:(BOOL)showUI selfPath:(NSString *)inSelfPath +- (instancetype)initWithHostPath:(NSString *)inhostpath executablePath:(NSString *)execpath parentProcessId:(pid_t)ppid folderPath:(NSString *)infolderpath shouldRelaunch:(BOOL)relaunch shouldShowUI:(BOOL)showUI selfPath:(NSString *)inSelfPath { if (!(self = [super init])) { return nil; } - hostpath = inhostpath; - executablepath = execpath; - parentprocessid = ppid; - folderpath = infolderpath; - selfPath = inSelfPath; - shouldRelaunch = relaunch; - shouldShowUI = showUI; + self.hostpath = inhostpath; + self.executablepath = execpath; + self.parentprocessid = ppid; + self.folderpath = infolderpath; + self.selfPath = inSelfPath; + self.shouldRelaunch = relaunch; + self.shouldShowUI = showUI; BOOL alreadyTerminated = (getppid() == 1); // ppid is launchd (1) => parent terminated already if (alreadyTerminated) [self parentHasQuit]; else - watchdogTimer = [NSTimer scheduledTimerWithTimeInterval:SUParentQuitCheckInterval target:self selector:@selector(watchdog:) userInfo:nil repeats:YES]; + self.watchdogTimer = [NSTimer scheduledTimerWithTimeInterval:SUParentQuitCheckInterval target:self selector:@selector(watchdog:) userInfo:nil repeats:YES]; return self; } @@ -85,7 +85,7 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; - (void)dealloc { - [longInstallationTimer invalidate]; + [self.longInstallationTimer invalidate]; } @@ -121,8 +121,8 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; if (self.shouldRelaunch) { NSString *appPath = nil; - if (!self.folderpath || strcmp(self.executablepath, self.hostpath) != 0) - appPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:self.executablepath length:strlen(self.executablepath)]; + if (!self.folderpath || ![self.executablepath isEqualToString:self.hostpath]) + appPath = self.executablepath; else appPath = self.installationPath; [[NSWorkspace sharedWorkspace] openFile:appPath]; @@ -142,7 +142,7 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; - (void)install { - NSBundle *theBundle = [NSBundle bundleWithPath:[[NSFileManager defaultManager] stringWithFileSystemRepresentation:self.hostpath length:strlen(self.hostpath)]]; + NSBundle *theBundle = [NSBundle bundleWithPath:self.hostpath]; self.host = [[SUHost alloc] initWithBundle:theBundle]; self.installationPath = [[self.host installationPath] copy]; @@ -154,7 +154,7 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; [statusCtl showWindow:self]; } - [SUInstaller installFromUpdateFolder:[[NSFileManager defaultManager] stringWithFileSystemRepresentation:self.folderpath length:strlen(self.folderpath)] + [SUInstaller installFromUpdateFolder:self.folderpath overHost:self.host installationPath:self.installationPath delegate:self @@ -175,44 +175,28 @@ static const NSTimeInterval SUParentQuitCheckInterval = .25; @end -int main(int argc, const char *argv[]) +int main(int __unused argc, const char __unused *argv[]) { - if (argc < 5 || argc > 7) { - return EXIT_FAILURE; - } - @autoreleasepool { -//ProcessSerialNumber psn = { 0, kCurrentProcess }; -//TransformProcessType( &psn, kProcessTransformToForegroundApplication ); + NSArray *args = [[NSProcessInfo processInfo] arguments]; + if (args.count < 5 || args.count > 7) { + return EXIT_FAILURE; + } -#if 0 // Cmdline tool - NSString* selfPath = nil; - if (argv[0][0] == '/') { - selfPath = [[NSFileManager defaultManager] stringWithFileSystemRepresentation: argv[0] length: strlen(argv[0])]; - } - else - { - selfPath = [[NSFileManager defaultManager] currentDirectoryPath]; - selfPath = [selfPath stringByAppendingPathComponent: [[NSFileManager defaultManager] stringWithFileSystemRepresentation: argv[0] length: strlen(argv[0])]]; - } -#else - NSString *selfPath = [[NSBundle mainBundle] bundlePath]; -#endif - - BOOL shouldShowUI = (argc > 6) ? !!atoi(argv[6]) : YES; + BOOL shouldShowUI = (args.count > 6) ? [args[6] boolValue] : YES; if (shouldShowUI) { [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; } [NSApplication sharedApplication]; - TerminationListener *termListen = [[TerminationListener alloc] initWithHostPath:(argc > 1) ? argv[1] : NULL - executablePath:(argc > 2) ? argv[2] : NULL - parentProcessId:(argc > 3) ? atoi(argv[3]) : 0 - folderPath:(argc > 4) ? argv[4] : NULL - shouldRelaunch:(argc > 5) ? !!atoi(argv[5]) : YES + TerminationListener *termListen = [[TerminationListener alloc] initWithHostPath:args[1] + executablePath:args[2] + parentProcessId:[args[3] intValue] + folderPath:args[4] + shouldRelaunch:(args.count > 5) ? [args[5] boolValue] : YES shouldShowUI:shouldShowUI - selfPath:selfPath]; + selfPath:[[NSBundle mainBundle] bundlePath]]; [termListen class]; [[NSApplication sharedApplication] run]; diff --git a/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.pch b/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.pch deleted file mode 100644 index f29230f16..000000000 --- a/Frameworks/Sparkle/Sparkle/Autoupdate/Autoupdate.pch +++ /dev/null @@ -1,16 +0,0 @@ -// -// Sparkle.pch -// Sparkle -// -// Created by Andy Matuschak on 7/23/08. -// Copyright 2008 Andy Matuschak. All rights reserved. -// - -#define SPARKLE_BUNDLE [NSBundle mainBundle] -#define SULocalizedString(key,comment) NSLocalizedStringFromTableInBundle(key, @"Sparkle", SPARKLE_BUNDLE, comment) -#define SUAbstractFail() NSAssert2(nil, @"Can't call %@ on an instance of %@; this is an abstract method!", __PRETTY_FUNCTION__, [self class]); - -#ifdef __OBJC__ -#import -#import "SUConstants.h" -#endif diff --git a/Frameworks/Sparkle/Sparkle/SUAppcast.h b/Frameworks/Sparkle/Sparkle/SUAppcast.h index 702f549e1..7d455231b 100644 --- a/Frameworks/Sparkle/Sparkle/SUAppcast.h +++ b/Frameworks/Sparkle/Sparkle/SUAppcast.h @@ -9,10 +9,12 @@ #ifndef SUAPPCAST_H #define SUAPPCAST_H +#import "SUExport.h" + @protocol SUAppcastDelegate; @class SUAppcastItem; -@interface SUAppcast : NSObject +SU_EXPORT @interface SUAppcast : NSObject @property (weak) id delegate; @property (copy) NSString *userAgentString; diff --git a/Frameworks/Sparkle/Sparkle/SUAppcast.m b/Frameworks/Sparkle/Sparkle/SUAppcast.m index bc35b40ff..196267fb9 100644 --- a/Frameworks/Sparkle/Sparkle/SUAppcast.m +++ b/Frameworks/Sparkle/Sparkle/SUAppcast.m @@ -145,30 +145,38 @@ for (NSString *name in nodesDict) { node = [self bestNodeInNodes:nodesDict[name]]; - if ([name isEqualToString:@"enclosure"]) + if ([name isEqualToString:SURSSElementEnclosure]) { // enclosure is flattened as a separate dictionary for some reason NSDictionary *encDict = [(NSXMLElement *)node attributesAsDictionary]; - dict[@"enclosure"] = encDict; + dict[name] = encDict; } - else if ([name isEqualToString:@"pubDate"]) + else if ([name isEqualToString:SURSSElementPubDate]) { // pubDate is expected to be an NSDate by SUAppcastItem, but the RSS class was returning an NSString NSDate *date = [NSDate dateWithNaturalLanguageString:[node stringValue]]; if (date) dict[name] = date; } - else if ([name isEqualToString:@"sparkle:deltas"]) + else if ([name isEqualToString:SUAppcastElementDeltas]) { NSMutableArray *deltas = [NSMutableArray array]; NSEnumerator *childEnum = [[node children] objectEnumerator]; for (NSXMLNode *child in childEnum) { - if ([[child name] isEqualToString:@"enclosure"]) + if ([[child name] isEqualToString:SURSSElementEnclosure]) [deltas addObject:[(NSXMLElement *)child attributesAsDictionary]]; } - dict[@"deltas"] = deltas; + dict[name] = deltas; } + else if ([name isEqualToString:SUAppcastElementTags]) { + NSMutableArray *tags = [NSMutableArray array]; + NSEnumerator *childEnum = [[node children] objectEnumerator]; + for (NSXMLNode *child in childEnum) { + [tags addObject:[child name]]; + } + dict[name] = tags; + } else if (name != nil) { // add all other values as strings @@ -196,7 +204,11 @@ if ([appcastItems count]) { - NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wselector" + // @selector(date) is from SUAppcastItem + NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector(@selector(date)) ascending:NO]; +#pragma clang diagnostic pop [appcastItems sortUsingDescriptors:@[sort]]; self.items = appcastItems; } diff --git a/Frameworks/Sparkle/Sparkle/SUAppcastItem.h b/Frameworks/Sparkle/Sparkle/SUAppcastItem.h index 3334a1af3..551d389b1 100644 --- a/Frameworks/Sparkle/Sparkle/SUAppcastItem.h +++ b/Frameworks/Sparkle/Sparkle/SUAppcastItem.h @@ -9,7 +9,9 @@ #ifndef SUAPPCASTITEM_H #define SUAPPCASTITEM_H -@interface SUAppcastItem : NSObject +#include "SUExport.h" + +SU_EXPORT @interface SUAppcastItem : NSObject @property (copy, readonly) NSString *title; @property (copy, readonly) NSDate *date; @property (copy, readonly) NSString *itemDescription; diff --git a/Frameworks/Sparkle/Sparkle/SUAppcastItem.m b/Frameworks/Sparkle/Sparkle/SUAppcastItem.m index fb3dfe44d..0f5b79201 100644 --- a/Frameworks/Sparkle/Sparkle/SUAppcastItem.m +++ b/Frameworks/Sparkle/Sparkle/SUAppcastItem.m @@ -47,12 +47,12 @@ - (BOOL)isDeltaUpdate { - return self.propertiesDictionary[@"enclosure"][@"sparkle:deltaFrom"] != nil; + return self.propertiesDictionary[SURSSElementEnclosure][SUAppcastAttributeDeltaFrom] != nil; } - (BOOL)isCriticalUpdate { - return [self.propertiesDictionary[@"sparkle:tags"] containsObject:@"sparkle:criticalUpdate"]; + return [self.propertiesDictionary[SUAppcastElementTags] containsObject:SUAppcastElementCriticalUpdate]; } - (instancetype)initWithDictionary:(NSDictionary *)dict @@ -64,7 +64,7 @@ { self = [super init]; if (self) { - id enclosure = dict[@"enclosure"]; + id enclosure = dict[SURSSElementEnclosure]; // Try to find a version string. // Finding the new version number from the RSS feed is a little bit hacky. There are two ways: @@ -74,17 +74,17 @@ // underscore and the last period as the version number. So name your packages like this: APPNAME_VERSION.extension. // The big caveat with this is that you can't have underscores in your version strings, as that'll confuse Sparkle. // Feel free to change the separator string to a hyphen or something more suited to your needs if you like. - NSString *newVersion = enclosure[@"sparkle:version"]; + NSString *newVersion = enclosure[SUAppcastAttributeVersion]; if (newVersion == nil) { - newVersion = dict[@"sparkle:version"]; // Get version from the item, in case it's a download-less item (i.e. paid upgrade). + newVersion = dict[SUAppcastAttributeVersion]; // Get version from the item, in case it's a download-less item (i.e. paid upgrade). } if (newVersion == nil) // no sparkle:version attribute anywhere? { - SULog(@"warning: for URL '%@' is missing sparkle:version attribute. Version comparison may be unreliable. Please always specify sparkle:version", enclosure[@"url"]); + SULog(@"warning: <%@> for URL '%@' is missing %@ attribute. Version comparison may be unreliable. Please always specify %@", SURSSElementEnclosure, enclosure[SURSSAttributeURL], SUAppcastAttributeVersion, SUAppcastAttributeVersion); // Separate the url by underscores and take the last component, as that'll be closest to the end, // then we remove the extension. Hopefully, this will be the version. - NSArray *fileComponents = [enclosure[@"url"] componentsSeparatedByString:@"_"]; + NSArray *fileComponents = [enclosure[SURSSAttributeURL] componentsSeparatedByString:@"_"]; if ([fileComponents count] > 1) { newVersion = [[fileComponents lastObject] stringByDeletingPathExtension]; } @@ -92,20 +92,20 @@ if (!newVersion) { if (error) { - *error = @"Feed item lacks sparkle:version attribute, and version couldn't be deduced from file name (would have used last component of a file name like AppName_1.3.4.zip)"; + *error = [NSString stringWithFormat:@"Feed item lacks %@ attribute, and version couldn't be deduced from file name (would have used last component of a file name like AppName_1.3.4.zip)", SUAppcastAttributeVersion]; } return nil; } propertiesDictionary = [[NSMutableDictionary alloc] initWithDictionary:dict]; - self.title = dict[@"title"]; - self.date = dict[@"pubDate"]; - self.itemDescription = dict[@"description"]; + self.title = dict[SURSSElementTitle]; + self.date = dict[SURSSElementPubDate]; + self.itemDescription = dict[SURSSElementDescription]; - NSString *theInfoURL = dict[@"link"]; + NSString *theInfoURL = dict[SURSSElementLink]; if (theInfoURL) { if (![theInfoURL isKindOfClass:[NSString class]]) { - SULog(@"SUAppcastItem -initWithDictionary: Info URL is not of valid type."); + SULog(@"%@ -%@ Info URL is not of valid type.", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); } else { self.infoURL = [NSURL URLWithString:theInfoURL]; } @@ -120,7 +120,7 @@ return nil; } - NSString *enclosureURLString = enclosure[@"url"]; + NSString *enclosureURLString = enclosure[SURSSAttributeURL]; if (!enclosureURLString && !theInfoURL) { if (error) { *error = @"Feed item's enclosure lacks URL"; @@ -133,16 +133,16 @@ self.fileURL = [NSURL URLWithString:fileURLString]; } if (enclosure) { - self.DSASignature = enclosure[@"sparkle:dsaSignature"]; + self.DSASignature = enclosure[SUAppcastAttributeDSASignature]; } self.versionString = newVersion; - self.minimumSystemVersion = dict[@"sparkle:minimumSystemVersion"]; - self.maximumSystemVersion = dict[@"sparkle:maximumSystemVersion"]; + self.minimumSystemVersion = dict[SUAppcastElementMinimumSystemVersion]; + self.maximumSystemVersion = dict[SUAppcastElementMaximumSystemVersion]; - NSString *shortVersionString = enclosure[@"sparkle:shortVersionString"]; + NSString *shortVersionString = enclosure[SUAppcastAttributeShortVersionString]; if (nil == shortVersionString) { - shortVersionString = dict[@"sparkle:shortVersionString"]; // fall back on the + shortVersionString = dict[SUAppcastAttributeShortVersionString]; // fall back on the } if (shortVersionString) { @@ -152,24 +152,24 @@ } // Find the appropriate release notes URL. - if (dict[@"sparkle:releaseNotesLink"]) { - self.releaseNotesURL = [NSURL URLWithString:dict[@"sparkle:releaseNotesLink"]]; + if (dict[SUAppcastElementReleaseNotesLink]) { + self.releaseNotesURL = [NSURL URLWithString:dict[SUAppcastElementReleaseNotesLink]]; } else if ([self.itemDescription hasPrefix:@"http://"] || [self.itemDescription hasPrefix:@"https://"]) { // if the description starts with http:// or https:// use that. self.releaseNotesURL = [NSURL URLWithString:self.itemDescription]; } else { self.releaseNotesURL = nil; } - if (dict[@"deltas"]) { + NSArray *deltaDictionaries = dict[SUAppcastElementDeltas]; + if (deltaDictionaries) { NSMutableDictionary *deltas = [NSMutableDictionary dictionary]; - NSArray *deltaDictionaries = dict[@"deltas"]; for (NSDictionary *deltaDictionary in deltaDictionaries) { NSMutableDictionary *fakeAppCastDict = [dict mutableCopy]; - [fakeAppCastDict removeObjectForKey:@"deltas"]; - fakeAppCastDict[@"enclosure"] = deltaDictionary; + [fakeAppCastDict removeObjectForKey:SUAppcastElementDeltas]; + fakeAppCastDict[SURSSElementEnclosure] = deltaDictionary; SUAppcastItem *deltaItem = [[[self class] alloc] initWithDictionary:fakeAppCastDict]; - deltas[deltaDictionary[@"sparkle:deltaFrom"]] = deltaItem; + deltas[deltaDictionary[SUAppcastAttributeDeltaFrom]] = deltaItem; } self.deltaUpdates = deltas; } diff --git a/Frameworks/Sparkle/Sparkle/SUAutomaticUpdateDriver.m b/Frameworks/Sparkle/Sparkle/SUAutomaticUpdateDriver.m index ff6668a0d..20a0a0658 100644 --- a/Frameworks/Sparkle/Sparkle/SUAutomaticUpdateDriver.m +++ b/Frameworks/Sparkle/Sparkle/SUAutomaticUpdateDriver.m @@ -135,7 +135,7 @@ static const NSTimeInterval SUAutomaticUpdatePromptImpatienceTimer = 60 * 60 * 2 - (void)applicationDidBecomeActive:(NSNotification *)__unused aNotification { [[self.alert window] makeKeyAndOrderFront:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSApplicationDidBecomeActiveNotification" object:NSApp]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp]; } - (void)automaticUpdateAlert:(SUAutomaticUpdateAlert *)__unused aua finishedWithChoice:(SUAutomaticInstallationChoice)choice diff --git a/Frameworks/Sparkle/Sparkle/SUBasicUpdateDriver.m b/Frameworks/Sparkle/Sparkle/SUBasicUpdateDriver.m index 06727ee75..12147df72 100644 --- a/Frameworks/Sparkle/Sparkle/SUBasicUpdateDriver.m +++ b/Frameworks/Sparkle/Sparkle/SUBasicUpdateDriver.m @@ -21,15 +21,6 @@ #import "SUCodeSigningVerifier.h" #import "SUUpdater_Private.h" -#ifdef FINISH_INSTALL_TOOL_NAME -// FINISH_INSTALL_TOOL_NAME expands to unquoted Autoupdate -#define QUOTE_NS_STRING2(str) @"" #str -#define QUOTE_NS_STRING1(str) QUOTE_NS_STRING2(str) -#define FINISH_INSTALL_TOOL_NAME_STRING QUOTE_NS_STRING1(FINISH_INSTALL_TOOL_NAME) -#else -#error FINISH_INSTALL_TOOL_NAME not defined -#endif - @interface SUBasicUpdateDriver () @property (strong) SUAppcastItem *updateItem; @@ -360,11 +351,11 @@ [updaterDelegate updater:self.updater willInstallUpdate:self.updateItem]; } - NSString *const finishInstallToolName = FINISH_INSTALL_TOOL_NAME_STRING; + NSBundle *sparkleBundle = [NSBundle bundleWithIdentifier:SUBundleIdentifier]; // Copy the relauncher into a temporary directory so we can get to it after the new version's installed. // Only the paranoid survive: if there's already a stray copy of relaunch there, we would have problems. - NSString *relaunchPathToCopy = [SPARKLE_BUNDLE pathForResource:finishInstallToolName ofType:@"app"]; + NSString *const relaunchPathToCopy = [sparkleBundle pathForResource:[[sparkleBundle infoDictionary] objectForKey:SURelaunchToolNameKey] ofType:@"app"]; if (relaunchPathToCopy != nil) { NSString *targetPath = [[self.host appSupportPath] stringByAppendingPathComponent:[relaunchPathToCopy lastPathComponent]]; @@ -394,7 +385,7 @@ if ([updaterDelegate respondsToSelector:@selector(pathToRelaunchForUpdater:)]) { pathToRelaunch = [updaterDelegate pathToRelaunchForUpdater:self.updater]; } - NSString *relaunchToolPath = [[self.relaunchPath stringByAppendingPathComponent:@"/Contents/MacOS"] stringByAppendingPathComponent:finishInstallToolName]; + NSString *relaunchToolPath = [[NSBundle bundleWithPath:self.relaunchPath] executablePath]; [NSTask launchedTaskWithLaunchPath:relaunchToolPath arguments:@[[self.host bundlePath], pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], diff --git a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaApply.m b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaApply.m index f19f76f3a..85dbd0cd5 100644 --- a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaApply.m +++ b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaApply.m @@ -10,7 +10,7 @@ #import "SUBinaryDeltaCommon.h" #include #import -#include +#include "bspatch.h" #include #include #include diff --git a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaCommon.m b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaCommon.m index 1caf70192..78ba2606b 100644 --- a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaCommon.m +++ b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaCommon.m @@ -39,23 +39,28 @@ NSString *pathRelativeToDirectory(NSString *directory, NSString *path) } NSString *stringWithFileSystemRepresentation(const char *input) { - NSFileManager *fm = [NSFileManager defaultManager]; - return [fm stringWithFileSystemRepresentation:input length:strlen(input)]; + return [[NSFileManager defaultManager] stringWithFileSystemRepresentation:input length:strlen(input)]; } NSString *temporaryFilename(NSString *base) { NSString *template = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.XXXXXXXXXX", base]]; - const char *fsrepr = [template fileSystemRepresentation]; + NSMutableData *data = [NSMutableData data]; + [data appendBytes:template.fileSystemRepresentation length:strlen(template.fileSystemRepresentation) + 1]; - const size_t buffer_len = strlen(fsrepr) + 1; - char *buffer = (char *)malloc(buffer_len); - strlcpy(buffer, fsrepr, buffer_len); + char *buffer = data.mutableBytes; + int fd = mkstemp(buffer); + if (fd == -1) { + perror("mkstemp"); + return nil; + } - // mkstemp() can't be used, beause it returns a file descriptor, and XAR API requires a filename - NSString *ret = stringWithFileSystemRepresentation(mktemp(buffer)); - free(buffer); - return ret; + if (close(fd) != 0) { + perror("close"); + return nil; + } + + return stringWithFileSystemRepresentation(buffer); } static void _hashOfBuffer(unsigned char *hash, const char* buffer, ssize_t bufferLength) diff --git a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaTool.m b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaTool.m index 8e46ead99..a09d8c6d5 100644 --- a/Frameworks/Sparkle/Sparkle/SUBinaryDeltaTool.m +++ b/Frameworks/Sparkle/Sparkle/SUBinaryDeltaTool.m @@ -114,19 +114,33 @@ static BOOL shouldDeleteThenExtract(NSString * __unused key, NSDictionary* origi return NO; } -int main(int argc, char **argv) +int main(int __unused argc, char __unused *argv[]) { @autoreleasepool { - if (argc != 5) { + NSArray *args = [[NSProcessInfo processInfo] arguments]; + if (args.count != 5) { usage: fprintf(stderr, "Usage: BinaryDelta [create | apply] before-tree after-tree patch-file\n"); - exit(1); + return 1; } - NSString *command = @(argv[1]); - NSString *oldPath = stringWithFileSystemRepresentation(argv[2]); - NSString *newPath = stringWithFileSystemRepresentation(argv[3]); - NSString *patchFile = stringWithFileSystemRepresentation(argv[4]); + NSString *command = args[1]; + NSString *oldPath = args[2]; + NSString *newPath = args[3]; + NSString *patchFile = args[4]; + + BOOL isDirectory; + [[NSFileManager defaultManager] fileExistsAtPath:oldPath isDirectory:&isDirectory]; + if (!isDirectory) { + fprintf(stderr, "Usage: before-tree must be a directory\n"); + return 1; + } + + [[NSFileManager defaultManager] fileExistsAtPath:newPath isDirectory:&isDirectory]; + if (!isDirectory) { + fprintf(stderr, "Usage: after-tree must be a directory\n"); + return 1; + } if ([command isEqualToString:@"apply"]) { int result = applyBinaryDelta(oldPath, newPath, patchFile); diff --git a/Frameworks/Sparkle/Sparkle/SUCodeSigningVerifier.m b/Frameworks/Sparkle/Sparkle/SUCodeSigningVerifier.m index c720d6538..692865928 100644 --- a/Frameworks/Sparkle/Sparkle/SUCodeSigningVerifier.m +++ b/Frameworks/Sparkle/Sparkle/SUCodeSigningVerifier.m @@ -95,7 +95,7 @@ static id valueOrNSNull(id value) { } NSDictionary *infoPlist = signingDict[@"info-plist"]; relevantInfo[@"version"] = valueOrNSNull(infoPlist[@"CFBundleShortVersionString"]); - relevantInfo[@"build"] = valueOrNSNull(infoPlist[@"CFBundleVersion"]); + relevantInfo[@"build"] = valueOrNSNull(infoPlist[(__bridge NSString *)kCFBundleVersionKey]); SULog(@"%@: %@", label, relevantInfo); } } diff --git a/Frameworks/Sparkle/Sparkle/SUConstants.h b/Frameworks/Sparkle/Sparkle/SUConstants.h index c07d9f409..d9d7887bf 100644 --- a/Frameworks/Sparkle/Sparkle/SUConstants.h +++ b/Frameworks/Sparkle/Sparkle/SUConstants.h @@ -11,20 +11,13 @@ #define SUCONSTANTS_H // ----------------------------------------------------------------------------- -// Preprocessor flags: +// Misc: // ----------------------------------------------------------------------------- -// Sparkle usually doesn't allow downgrades as they're usually accidental, but -// if your app has a downgrade function or URL handler, turn this on: -#define PERMIT_AUTOMATED_DOWNGRADES 0 +extern const NSTimeInterval SUMinimumUpdateCheckInterval; +extern const NSTimeInterval SUDefaultUpdateCheckInterval; -// If your app file on disk is named "MyApp 1.1b4", Sparkle usually updates it -// in place, giving you an app named 1.1b4 that is actually 1.2. Turn the -// following on to always reset the name back to "MyApp": -#define NORMALIZE_INSTALLED_APP_NAME 0 - - -#define TRY_TO_APPEND_VERSION_NUMBER 1 +extern NSString *const SUBundleIdentifier; // ----------------------------------------------------------------------------- // Notifications: @@ -57,31 +50,62 @@ extern NSString *const SUKeepDownloadOnFailedInstallKey; extern NSString *const SUDefaultsDomainKey; extern NSString *const SUFixedHTMLDisplaySizeKey __attribute__((deprecated("This key is obsolete and has no effect."))); +extern NSString *const SUAppendVersionNumberKey; +extern NSString *const SUEnableAutomatedDowngradesKey; +extern NSString *const SUNormalizeInstalledApplicationNameKey; +extern NSString *const SURelaunchToolNameKey; + +// ----------------------------------------------------------------------------- +// Appcast keys:: +// ----------------------------------------------------------------------------- + +extern NSString *const SUAppcastAttributeDeltaFrom; +extern NSString *const SUAppcastAttributeDSASignature; +extern NSString *const SUAppcastAttributeShortVersionString; +extern NSString *const SUAppcastAttributeVersion; + +extern NSString *const SUAppcastElementCriticalUpdate; +extern NSString *const SUAppcastElementDeltas; +extern NSString *const SUAppcastElementMinimumSystemVersion; +extern NSString *const SUAppcastElementMaximumSystemVersion; +extern NSString *const SUAppcastElementReleaseNotesLink; +extern NSString *const SUAppcastElementTags; + +extern NSString *const SURSSAttributeURL; + +extern NSString *const SURSSElementDescription; +extern NSString *const SURSSElementEnclosure; +extern NSString *const SURSSElementLink; +extern NSString *const SURSSElementPubDate; +extern NSString *const SURSSElementTitle; + // ----------------------------------------------------------------------------- // Errors: // ----------------------------------------------------------------------------- extern NSString *const SUSparkleErrorDomain; -// Appcast phase errors. -extern OSStatus SUAppcastParseError; -extern OSStatus SUNoUpdateError; -extern OSStatus SUAppcastError; -extern OSStatus SURunningFromDiskImageError; +typedef NS_ENUM(OSStatus, SUError) { + // Appcast phase errors. + SUAppcastParseError = 1000, + SUNoUpdateError = 1001, + SUAppcastError = 1002, + SURunningFromDiskImageError = 1003, -// Downlaod phase errors. -extern OSStatus SUTemporaryDirectoryError; + // Downlaod phase errors. + SUTemporaryDirectoryError = 2000, -// Extraction phase errors. -extern OSStatus SUUnarchivingError; -extern OSStatus SUSignatureError; + // Extraction phase errors. + SUUnarchivingError = 3000, + SUSignatureError = 3001, -// Installation phase errors. -extern OSStatus SUFileCopyFailure; -extern OSStatus SUAuthenticationFailure; -extern OSStatus SUMissingUpdateError; -extern OSStatus SUMissingInstallerToolError; -extern OSStatus SURelaunchError; -extern OSStatus SUInstallationError; -extern OSStatus SUDowngradeError; + // Installation phase errors. + SUFileCopyFailure = 4000, + SUAuthenticationFailure = 4001, + SUMissingUpdateError = 4002, + SUMissingInstallerToolError = 4003, + SURelaunchError = 4004, + SUInstallationError = 4005, + SUDowngradeError = 4006 +}; #endif diff --git a/Frameworks/Sparkle/Sparkle/SUConstants.m b/Frameworks/Sparkle/Sparkle/SUConstants.m index 832391efe..31c80ca3d 100644 --- a/Frameworks/Sparkle/Sparkle/SUConstants.m +++ b/Frameworks/Sparkle/Sparkle/SUConstants.m @@ -13,6 +13,16 @@ #import "SUVersionComparisonProtocol.h" #import "SUConstants.h" +#ifndef DEBUG +#define DEBUG 0 +#endif + +// Define some minimum intervals to avoid DoS-like checking attacks +const NSTimeInterval SUMinimumUpdateCheckInterval = DEBUG ? 60 : (60 * 60); +const NSTimeInterval SUDefaultUpdateCheckInterval = DEBUG ? 60 : (60 * 60 * 24); + +NSString *const SUBundleIdentifier = @SPARKLE_BUNDLE_IDENTIFIER; + NSString *const SUTechnicalErrorInformationKey = @"SUTechnicalErrorInformation"; NSString *const SUHasLaunchedBeforeKey = @"SUHasLaunchedBefore"; @@ -35,22 +45,29 @@ NSString *const SUPromptUserOnFirstLaunchKey = @"SUPromptUserOnFirstLaunch"; NSString *const SUFixedHTMLDisplaySizeKey = @"SUFixedHTMLDisplaySize"; NSString *const SUKeepDownloadOnFailedInstallKey = @"SUKeepDownloadOnFailedInstall"; NSString *const SUDefaultsDomainKey = @"SUDefaultsDomain"; - NSString *const SUSparkleErrorDomain = @"SUSparkleErrorDomain"; -OSStatus SUAppcastParseError = 1000; -OSStatus SUNoUpdateError = 1001; -OSStatus SUAppcastError = 1002; -OSStatus SURunningFromDiskImageError = 1003; -OSStatus SUTemporaryDirectoryError = 2000; +NSString *const SUAppendVersionNumberKey = @"SUAppendVersionNumber"; +NSString *const SUEnableAutomatedDowngradesKey = @"SUEnableAutomatedDowngrades"; +NSString *const SUNormalizeInstalledApplicationNameKey = @"SUNormalizeInstalledApplicationName"; +NSString *const SURelaunchToolNameKey = @"SURelaunchToolName"; -OSStatus SUUnarchivingError = 3000; -OSStatus SUSignatureError = 3001; +NSString *const SUAppcastAttributeDeltaFrom = @"sparkle:deltaFrom"; +NSString *const SUAppcastAttributeDSASignature = @"sparkle:dsaSignature"; +NSString *const SUAppcastAttributeShortVersionString = @"sparkle:shortVersionString"; +NSString *const SUAppcastAttributeVersion = @"sparkle:version"; -OSStatus SUFileCopyFailure = 4000; -OSStatus SUAuthenticationFailure = 4001; -OSStatus SUMissingUpdateError = 4002; -OSStatus SUMissingInstallerToolError = 4003; -OSStatus SURelaunchError = 4004; -OSStatus SUInstallationError = 4005; -OSStatus SUDowngradeError = 4006; +NSString *const SUAppcastElementCriticalUpdate = @"sparkle:criticalUpdate"; +NSString *const SUAppcastElementDeltas = @"sparkle:deltas"; +NSString *const SUAppcastElementMinimumSystemVersion = @"sparkle:minimumSystemVersion"; +NSString *const SUAppcastElementMaximumSystemVersion = @"sparkle:maximumSystemVersion"; +NSString *const SUAppcastElementReleaseNotesLink = @"sparkle:releaseNotesLink"; +NSString *const SUAppcastElementTags = @"sparkle:tags"; + +NSString *const SURSSAttributeURL = @"url"; + +NSString *const SURSSElementDescription = @"description"; +NSString *const SURSSElementEnclosure = @"enclosure"; +NSString *const SURSSElementLink = @"link"; +NSString *const SURSSElementPubDate = @"pubDate"; +NSString *const SURSSElementTitle = @"title"; diff --git a/Frameworks/Sparkle/Sparkle/SUDSAVerifier.m b/Frameworks/Sparkle/Sparkle/SUDSAVerifier.m index 36893fee8..4789327e0 100644 --- a/Frameworks/Sparkle/Sparkle/SUDSAVerifier.m +++ b/Frameworks/Sparkle/Sparkle/SUDSAVerifier.m @@ -121,9 +121,12 @@ return cleanup(); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" dataVerifyTransform = SecVerifyTransformCreate(_secKey, (__bridge CFDataRef)signature, &error); +#pragma clang diagnostic pop if (!dataVerifyTransform || error) { - SULog(@"Could not understand format of the sugnature: %@; Signature data: %@", error, signature); + SULog(@"Could not understand format of the signature: %@; Signature data: %@", error, signature); return cleanup(); } diff --git a/Frameworks/Sparkle/Sparkle/SUExport.h b/Frameworks/Sparkle/Sparkle/SUExport.h new file mode 100644 index 000000000..3e3f8a164 --- /dev/null +++ b/Frameworks/Sparkle/Sparkle/SUExport.h @@ -0,0 +1,18 @@ +// +// SUExport.h +// Sparkle +// +// Created by Jake Petroules on 2014-08-23. +// Copyright (c) 2014 Sparkle Project. All rights reserved. +// + +#ifndef SUEXPORT_H +#define SUEXPORT_H + +#ifdef BUILDING_SPARKLE +#define SU_EXPORT __attribute__((visibility("default"))) +#else +#define SU_EXPORT +#endif + +#endif diff --git a/Frameworks/Sparkle/Sparkle/SUHost.m b/Frameworks/Sparkle/Sparkle/SUHost.m index 049b87cae..58c536513 100644 --- a/Frameworks/Sparkle/Sparkle/SUHost.m +++ b/Frameworks/Sparkle/Sparkle/SUHost.m @@ -44,7 +44,7 @@ typedef struct { if (aBundle == nil) aBundle = [NSBundle mainBundle]; self.bundle = aBundle; if (![self.bundle bundleIdentifier]) { - SULog(@"Error: the bundle being updated at %@ has no CFBundleIdentifier! This will cause preference read/write to not work properly.", self.bundle); + SULog(@"Error: the bundle being updated at %@ has no %@! This will cause preference read/write to not work properly.", self.bundle, kCFBundleIdentifierKey); } self.defaultsDomain = [self.bundle objectForInfoDictionaryKey:SUDefaultsDomainKey]; @@ -85,13 +85,13 @@ typedef struct { - (NSString *)installationPath { -#if NORMALIZE_INSTALLED_APP_NAME - // We'll install to "#{CFBundleName}.app", but only if that path doesn't already exist. If we're "Foo 4.2.app," and there's a "Foo.app" in this directory, we don't want to overwrite it! But if there's no "Foo.app," we'll take that name. - NSString *normalizedAppPath = [[[self.bundle bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self.bundle objectForInfoDictionaryKey:@"CFBundleName"], [[self.bundle bundlePath] pathExtension]]]; - if (![[NSFileManager defaultManager] fileExistsAtPath:[[[self.bundle bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self.bundle objectForInfoDictionaryKey:@"CFBundleName"], [[self.bundle bundlePath] pathExtension]]]]) { - return normalizedAppPath; + if ([[[NSBundle bundleWithIdentifier:SUBundleIdentifier] infoDictionary][SUNormalizeInstalledApplicationNameKey] boolValue]) { + // We'll install to "#{CFBundleName}.app", but only if that path doesn't already exist. If we're "Foo 4.2.app," and there's a "Foo.app" in this directory, we don't want to overwrite it! But if there's no "Foo.app," we'll take that name. + NSString *normalizedAppPath = [[[self.bundle bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self.bundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleNameKey], [[self.bundle bundlePath] pathExtension]]]; + if (![[NSFileManager defaultManager] fileExistsAtPath:[[[self.bundle bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self.bundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleNameKey], [[self.bundle bundlePath] pathExtension]]]]) { + return normalizedAppPath; + } } -#endif return [self.bundle bundlePath]; } @@ -100,7 +100,7 @@ typedef struct { NSString *name = [self.bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; if (name) return name; - name = [self objectForInfoDictionaryKey:@"CFBundleName"]; + name = [self objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleNameKey]; if (name) return name; return [[[NSFileManager defaultManager] displayNameAtPath:[self.bundle bundlePath]] stringByDeletingPathExtension]; @@ -108,9 +108,9 @@ typedef struct { - (NSString *)version { - NSString *version = [self.bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + NSString *version = [self.bundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]; if (!version || [version isEqualToString:@""]) - [NSException raise:@"SUNoVersionException" format:@"This host (%@) has no CFBundleVersion! This attribute is required.", [self bundlePath]]; + [NSException raise:@"SUNoVersionException" format:@"This host (%@) has no %@! This attribute is required.", [self bundlePath], (__bridge NSString *)kCFBundleVersionKey]; return version; } diff --git a/Frameworks/Sparkle/Sparkle/SUInstaller.m b/Frameworks/Sparkle/Sparkle/SUInstaller.m index 4960a4e37..6eff13942 100644 --- a/Frameworks/Sparkle/Sparkle/SUInstaller.m +++ b/Frameworks/Sparkle/Sparkle/SUInstaller.m @@ -152,11 +152,6 @@ static NSString *sUpdateFolder = nil; } } - -#define SUNotifyDictHostKey @"SUNotifyDictHost" -#define SUNotifyDictErrorKey @"SUNotifyDictError" -#define SUNotifyDictDelegateKey @"SUNotifyDictDelegate" - + (void)finishInstallationToPath:(NSString *)installationPath withResult:(BOOL)result host:(SUHost *)host error:(NSError *)error delegate:(id)delegate { if (result) diff --git a/Frameworks/Sparkle/Sparkle/SULog.m b/Frameworks/Sparkle/Sparkle/SULog.m index 267e67893..02c3be10c 100644 --- a/Frameworks/Sparkle/Sparkle/SULog.m +++ b/Frameworks/Sparkle/Sparkle/SULog.m @@ -18,7 +18,7 @@ // Constants: // ----------------------------------------------------------------------------- -#define LOG_FILE_PATH @"~/Library/Logs/SparkleUpdateLog.log" +static NSString *const SULogFilePath = @"~/Library/Logs/SparkleUpdateLog.log"; // ----------------------------------------------------------------------------- @@ -38,7 +38,7 @@ void SUClearLog(void) { - FILE *logfile = fopen([[LOG_FILE_PATH stringByExpandingTildeInPath] fileSystemRepresentation], "w"); + FILE *logfile = fopen([[SULogFilePath stringByExpandingTildeInPath] fileSystemRepresentation], "w"); if (logfile) { fclose(logfile); } @@ -62,7 +62,7 @@ void SULog(NSString *format, ...) NSString *theStr = [[NSString alloc] initWithFormat:format arguments:ap]; NSLog(@"Sparkle: %@", theStr); - FILE *logfile = fopen([[LOG_FILE_PATH stringByExpandingTildeInPath] fileSystemRepresentation], "a"); + FILE *logfile = fopen([[SULogFilePath stringByExpandingTildeInPath] fileSystemRepresentation], "a"); if (logfile) { theStr = [NSString stringWithFormat:@"%@: %@\n", [NSDate date], theStr]; NSData *theData = [theStr dataUsingEncoding:NSUTF8StringEncoding]; diff --git a/Frameworks/Sparkle/Sparkle/SUPlainInstaller.m b/Frameworks/Sparkle/Sparkle/SUPlainInstaller.m index 8eb98a3bf..96973d465 100644 --- a/Frameworks/Sparkle/Sparkle/SUPlainInstaller.m +++ b/Frameworks/Sparkle/Sparkle/SUPlainInstaller.m @@ -15,16 +15,16 @@ + (void)performInstallationToPath:(NSString *)installationPath fromPath:(NSString *)path host:(SUHost *)host delegate:(id)delegate versionComparator:(id)comparator { -// Prevent malicious downgrades: -#if !PERMIT_AUTOMATED_DOWNGRADES - if ([comparator compareVersion:[host version] toVersion:[[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedDescending) - { - NSString *errorMessage = [NSString stringWithFormat:@"Sparkle Updater: Possible attack in progress! Attempting to \"upgrade\" from %@ to %@. Aborting update.", [host version], [[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:@"CFBundleVersion"]]; - NSError *error = [NSError errorWithDomain:SUSparkleErrorDomain code:SUDowngradeError userInfo:@{ NSLocalizedDescriptionKey: errorMessage }]; - [self finishInstallationToPath:installationPath withResult:NO host:host error:error delegate:delegate]; - return; + // Prevent malicious downgrades + if (![[[NSBundle bundleWithIdentifier:SUBundleIdentifier] infoDictionary][SUEnableAutomatedDowngradesKey] boolValue]) { + if ([comparator compareVersion:[host version] toVersion:[[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]] == NSOrderedDescending) + { + NSString *errorMessage = [NSString stringWithFormat:@"Sparkle Updater: Possible attack in progress! Attempting to \"upgrade\" from %@ to %@. Aborting update.", [host version], [[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]]; + NSError *error = [NSError errorWithDomain:SUSparkleErrorDomain code:SUDowngradeError userInfo:@{ NSLocalizedDescriptionKey: errorMessage }]; + [self finishInstallationToPath:installationPath withResult:NO host:host error:error delegate:delegate]; + return; + } } -#endif dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSError *error = nil; diff --git a/Frameworks/Sparkle/Sparkle/SUPlainInstallerInternals.m b/Frameworks/Sparkle/Sparkle/SUPlainInstallerInternals.m index aa942d6f9..e06e5bdf7 100644 --- a/Frameworks/Sparkle/Sparkle/SUPlainInstallerInternals.m +++ b/Frameworks/Sparkle/Sparkle/SUPlainInstallerInternals.m @@ -90,7 +90,7 @@ static BOOL AuthorizationExecuteWithPrivilegesAndWait(AuthorizationRef authoriza // Let's try to read the version number so the filename will be more meaningful. NSString *postFix; NSString *version; - if ((version = [[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:@"CFBundleVersion"]) && ![version isEqualToString:@""]) + if ((version = [[NSBundle bundleWithPath:path] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]) && ![version isEqualToString:@""]) { NSMutableCharacterSet *validCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; [validCharacters formUnionWithCharacterSet:[NSCharacterSet characterSetWithCharactersInString:@".-()"]]; @@ -138,23 +138,24 @@ static BOOL AuthorizationExecuteWithPrivilegesAndWait(AuthorizationRef authoriza if (!tempDir) tempDir = [path stringByDeletingLastPathComponent]; -// Let's try to read the version number so the filename will be more meaningful. -#if TRY_TO_APPEND_VERSION_NUMBER - NSString *postFix = nil; - NSString *version = nil; - if ((version = [[NSBundle bundleWithPath: path] objectForInfoDictionaryKey:@"CFBundleVersion"]) && ![version isEqualToString:@""]) - { - NSMutableCharacterSet *validCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; - [validCharacters formUnionWithCharacterSet:[NSCharacterSet characterSetWithCharactersInString:@".-()"]]; - postFix = [version stringByTrimmingCharactersInSet:[validCharacters invertedSet]]; - } - else { - postFix = @"old"; + // Let's try to read the version number so the filename will be more meaningful + NSString *prefix; + if ([[[NSBundle bundleWithIdentifier:SUBundleIdentifier] infoDictionary][SUAppendVersionNumberKey] boolValue]) { + NSString *postFix = nil; + NSString *version = nil; + if ((version = [[NSBundle bundleWithPath: path] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]) && ![version isEqualToString:@""]) + { + NSMutableCharacterSet *validCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; + [validCharacters formUnionWithCharacterSet:[NSCharacterSet characterSetWithCharactersInString:@".-()"]]; + postFix = [version stringByTrimmingCharactersInSet:[validCharacters invertedSet]]; + } + else { + postFix = @"old"; + } + prefix = [NSString stringWithFormat:@"%@ (%@)", [[path lastPathComponent] stringByDeletingPathExtension], postFix]; + } else { + prefix = [[path lastPathComponent] stringByDeletingPathExtension]; } - NSString *prefix = [NSString stringWithFormat:@"%@ (%@)", [[path lastPathComponent] stringByDeletingPathExtension], postFix]; -#else - NSString *prefix = [[path lastPathComponent] stringByDeletingPathExtension]; -#endif NSString *tempName = [prefix stringByAppendingPathExtension:[path pathExtension]]; tempDir = [tempDir stringByAppendingPathComponent:tempName]; diff --git a/Frameworks/Sparkle/Sparkle/SUStandardVersionComparator.h b/Frameworks/Sparkle/Sparkle/SUStandardVersionComparator.h index f40d5715b..73ac968b3 100644 --- a/Frameworks/Sparkle/Sparkle/SUStandardVersionComparator.h +++ b/Frameworks/Sparkle/Sparkle/SUStandardVersionComparator.h @@ -9,7 +9,7 @@ #ifndef SUSTANDARDVERSIONCOMPARATOR_H #define SUSTANDARDVERSIONCOMPARATOR_H - +#import "SUExport.h" #import "SUVersionComparisonProtocol.h" /*! @@ -19,7 +19,7 @@ It's "dumb" in that it does essentially string comparison, in components split by character type. */ -@interface SUStandardVersionComparator : NSObject +SU_EXPORT @interface SUStandardVersionComparator : NSObject /*! Returns a singleton instance of the comparator. diff --git a/Frameworks/Sparkle/Sparkle/SUSystemProfiler.m b/Frameworks/Sparkle/Sparkle/SUSystemProfiler.m index 767438d0c..9176606e9 100644 --- a/Frameworks/Sparkle/Sparkle/SUSystemProfiler.m +++ b/Frameworks/Sparkle/Sparkle/SUSystemProfiler.m @@ -12,6 +12,18 @@ #import "SUHost.h" #include +static NSString *const SUSystemProfilerApplicationNameKey = @"appName"; +static NSString *const SUSystemProfilerApplicationVersionKey = @"appVersion"; +static NSString *const SUSystemProfilerCPU64bitKey = @"cpu64bit"; +static NSString *const SUSystemProfilerCPUCountKey = @"ncpu"; +static NSString *const SUSystemProfilerCPUFrequencyKey = @"cpuFreqMHz"; +static NSString *const SUSystemProfilerCPUTypeKey = @"cputype"; +static NSString *const SUSystemProfilerCPUSubtypeKey = @"cpusubtype"; +static NSString *const SUSystemProfilerHardwareModelKey = @"model"; +static NSString *const SUSystemProfilerMemoryKey = @"ramMB"; +static NSString *const SUSystemProfilerOperatingSystemVersionKey = @"osVersion"; +static NSString *const SUSystemProfilerPreferredLanguageKey = @"lang"; + @implementation SUSystemProfiler + (SUSystemProfiler *)sharedSystemProfiler { @@ -42,7 +54,7 @@ // OS version NSString *currentSystemVersion = [SUHost systemVersionString]; if (currentSystemVersion != nil) { - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"osVersion", @"OS Version", currentSystemVersion, currentSystemVersion] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerOperatingSystemVersionKey, @"OS Version", currentSystemVersion, currentSystemVersion] forKeys:profileDictKeys]]; } // CPU type (decoder info for values found here is in mach/machine.h) @@ -52,11 +64,12 @@ cpuType = value; NSString *visibleCPUType; switch (value) { + case CPU_TYPE_ARM: visibleCPUType = @"ARM"; break; case CPU_TYPE_X86: visibleCPUType = @"Intel"; break; case CPU_TYPE_POWERPC: visibleCPUType = @"PowerPC"; break; default: visibleCPUType = @"Unknown"; break; } - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"cputype", @"CPU Type", @(value), visibleCPUType] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerCPUTypeKey, @"CPU Type", @(value), visibleCPUType] forKeys:profileDictKeys]]; } error = sysctlbyname("hw.cpu64bit_capable", &value, &length, NULL, 0); if (error != 0) { @@ -70,7 +83,7 @@ if (error == 0) { is64bit = value == 1; - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"cpu64bit", @"CPU is 64-Bit?", @(is64bit), is64bit ? @"Yes" : @"No"] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerCPU64bitKey, @"CPU is 64-Bit?", @(is64bit), is64bit ? @"Yes" : @"No"] forKeys:profileDictKeys]]; } error = sysctlbyname("hw.cpusubtype", &value, &length, NULL, 0); if (error == 0) { @@ -90,7 +103,7 @@ } else { visibleCPUSubType = @"Other"; } - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"cpusubtype", @"CPU Subtype", @(value), visibleCPUSubType] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerCPUSubtypeKey, @"CPU Subtype", @(value), visibleCPUSubType] forKeys:profileDictKeys]]; } error = sysctlbyname("hw.model", NULL, &length, NULL, 0); if (error == 0) { @@ -103,7 +116,7 @@ if (visibleModelName == nil) { visibleModelName = rawModelName; } - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"model", @"Mac Model", rawModelName, visibleModelName] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerHardwareModelKey, @"Mac Model", rawModelName, visibleModelName] forKeys:profileDictKeys]]; } free(cpuModel); } @@ -112,24 +125,24 @@ // Number of CPUs error = sysctlbyname("hw.ncpu", &value, &length, NULL, 0); if (error == 0) { - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"ncpu", @"Number of CPUs", @(value), @(value)] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerCPUCountKey, @"Number of CPUs", @(value), @(value)] forKeys:profileDictKeys]]; } // User preferred language NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; NSArray *languages = [defs objectForKey:@"AppleLanguages"]; if ([languages count] > 0) { - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"lang", @"Preferred Language", languages[0], languages[0]] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerPreferredLanguageKey, @"Preferred Language", languages[0], languages[0]] forKeys:profileDictKeys]]; } // Application sending the request NSString *appName = [host name]; if (appName) { - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"appName", @"Application Name", appName, appName] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerApplicationNameKey, @"Application Name", appName, appName] forKeys:profileDictKeys]]; } NSString *appVersion = [host version]; if (appVersion) { - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"appVersion", @"Application Version", appVersion, appVersion] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerApplicationVersionKey, @"Application Version", appVersion, appVersion] forKeys:profileDictKeys]]; } // Number of displays? @@ -139,7 +152,7 @@ size_t hz_size = sizeof(unsigned long); if (sysctlbyname("hw.cpufrequency", &hz, &hz_size, NULL, 0) == 0) { unsigned long mhz = hz / 1000000; - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"cpuFreqMHz", @"CPU Speed (GHz)", @(mhz), @(mhz / 1000.)] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerCPUFrequencyKey, @"CPU Speed (MHz)", @(mhz), @(mhz / 1000.)] forKeys:profileDictKeys]]; } // amount of RAM @@ -147,7 +160,7 @@ size_t bytes_size = sizeof(unsigned long); if (sysctlbyname("hw.memsize", &bytes, &bytes_size, NULL, 0) == 0) { double megabytes = bytes / (1024. * 1024.); - [profileArray addObject:[NSDictionary dictionaryWithObjects:@[@"ramMB", @"Memory (MB)", @(megabytes), @(megabytes)] forKeys:profileDictKeys]]; + [profileArray addObject:[NSDictionary dictionaryWithObjects:@[SUSystemProfilerMemoryKey, @"Memory (MB)", @(megabytes), @(megabytes)] forKeys:profileDictKeys]]; } return profileArray; diff --git a/Frameworks/Sparkle/Sparkle/SUUIBasedUpdateDriver.m b/Frameworks/Sparkle/Sparkle/SUUIBasedUpdateDriver.m index 73237322d..ef631466f 100644 --- a/Frameworks/Sparkle/Sparkle/SUUIBasedUpdateDriver.m +++ b/Frameworks/Sparkle/Sparkle/SUUIBasedUpdateDriver.m @@ -75,7 +75,7 @@ - (void)applicationDidBecomeActive:(NSNotification *)__unused aNotification { [[self.updateAlert window] makeKeyAndOrderFront:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NSApplicationDidBecomeActiveNotification" object:NSApp]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp]; } - (void)updateAlert:(SUUpdateAlert *)__unused alert finishedWithChoice:(SUUpdateAlertChoice)choice diff --git a/Frameworks/Sparkle/Sparkle/SUUpdateAlert.m b/Frameworks/Sparkle/Sparkle/SUUpdateAlert.m index 0eb7e6132..2ca4093be 100644 --- a/Frameworks/Sparkle/Sparkle/SUUpdateAlert.m +++ b/Frameworks/Sparkle/Sparkle/SUUpdateAlert.m @@ -106,7 +106,7 @@ - (void)displayReleaseNotes { // Set the default font - [self.releaseNotesView setPreferencesIdentifier:[SPARKLE_BUNDLE bundleIdentifier]]; + [self.releaseNotesView setPreferencesIdentifier:SUBundleIdentifier]; WebPreferences *prefs = [self.releaseNotesView preferences]; NSString *familyName = [[NSFont systemFontOfSize:8] familyName]; if ([familyName hasPrefix:@"."]) { // 10.9 returns ".Lucida Grande UI", which isn't a valid name for the WebView diff --git a/Frameworks/Sparkle/Sparkle/SUUpdater.h b/Frameworks/Sparkle/Sparkle/SUUpdater.h index 4c8385718..f83fed5bf 100644 --- a/Frameworks/Sparkle/Sparkle/SUUpdater.h +++ b/Frameworks/Sparkle/Sparkle/SUUpdater.h @@ -9,6 +9,7 @@ #ifndef SUUPDATER_H #define SUUPDATER_H +#import "SUExport.h" #import "SUVersionComparisonProtocol.h" #import "SUVersionDisplayProtocol.h" @@ -22,7 +23,7 @@ This class is used to configure the update paramters as well as manually and automatically schedule and control checks for updates. */ -@interface SUUpdater : NSObject +SU_EXPORT @interface SUUpdater : NSObject @property (weak) IBOutlet id delegate; @@ -107,17 +108,17 @@ // SUUpdater Notifications for events that might be interesting to more than just the delegate // The updater will be the notification object // ----------------------------------------------------------------------------- -extern NSString *const SUUpdaterDidFinishLoadingAppCastNotification; -extern NSString *const SUUpdaterDidFindValidUpdateNotification; -extern NSString *const SUUpdaterDidNotFindUpdateNotification; -extern NSString *const SUUpdaterWillRestartNotification; +SU_EXPORT extern NSString *const SUUpdaterDidFinishLoadingAppCastNotification; +SU_EXPORT extern NSString *const SUUpdaterDidFindValidUpdateNotification; +SU_EXPORT extern NSString *const SUUpdaterDidNotFindUpdateNotification; +SU_EXPORT extern NSString *const SUUpdaterWillRestartNotification; #define SUUpdaterWillRelaunchApplicationNotification SUUpdaterWillRestartNotification; #define SUUpdaterWillInstallUpdateNotification SUUpdaterWillRestartNotification; // Key for the SUAppcastItem object in the SUUpdaterDidFindValidUpdateNotification userInfo -extern NSString *const SUUpdaterAppcastItemNotificationKey; +SU_EXPORT extern NSString *const SUUpdaterAppcastItemNotificationKey; // Key for the SUAppcast object in the SUUpdaterDidFinishLoadingAppCastNotification userInfo -extern NSString *const SUUpdaterAppcastNotificationKey; +SU_EXPORT extern NSString *const SUUpdaterAppcastNotificationKey; // ----------------------------------------------------------------------------- // SUUpdater Delegate: @@ -313,22 +314,4 @@ extern NSString *const SUUpdaterAppcastNotificationKey; @end - -// ----------------------------------------------------------------------------- -// Constants: -// ----------------------------------------------------------------------------- - -// Define some minimum intervals to avoid DOS-like checking attacks. These are in seconds. -#if defined(DEBUG) && DEBUG && 0 -#define SU_MIN_CHECK_INTERVAL 60 -#else -#define SU_MIN_CHECK_INTERVAL 60 * 60 -#endif - -#if defined(DEBUG) && DEBUG && 0 -#define SU_DEFAULT_CHECK_INTERVAL 60 -#else -#define SU_DEFAULT_CHECK_INTERVAL 60 * 60 * 24 -#endif - #endif diff --git a/Frameworks/Sparkle/Sparkle/SUUpdater.m b/Frameworks/Sparkle/Sparkle/SUUpdater.m index f8fcfc8b8..7d0e25d52 100644 --- a/Frameworks/Sparkle/Sparkle/SUUpdater.m +++ b/Frameworks/Sparkle/Sparkle/SUUpdater.m @@ -231,8 +231,8 @@ static NSString *const SUUpdaterDefaultsObservationContext = @"SUUpdaterDefaults // Now we want to figure out how long until we check again. NSTimeInterval delayUntilCheck, updateCheckInterval = [self updateCheckInterval]; - if (updateCheckInterval < SU_MIN_CHECK_INTERVAL) - updateCheckInterval = SU_MIN_CHECK_INTERVAL; + if (updateCheckInterval < SUMinimumUpdateCheckInterval) + updateCheckInterval = SUMinimumUpdateCheckInterval; if (intervalSinceCheck < updateCheckInterval) delayUntilCheck = (updateCheckInterval - intervalSinceCheck); // It hasn't been long enough. else @@ -411,7 +411,7 @@ static NSString *const SUUpdaterDefaultsObservationContext = @"SUUpdaterDefaults // Hack to support backwards compatibility with older Sparkle versions, which supported // disabling updates by setting the check interval to 0. if (automaticallyCheckForUpdates && (NSInteger)[self updateCheckInterval] == 0) { - [self setUpdateCheckInterval:SU_DEFAULT_CHECK_INTERVAL]; + [self setUpdateCheckInterval:SUDefaultUpdateCheckInterval]; } [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(resetUpdateCycle) object:nil]; // Provide a small delay in case multiple preferences are being updated simultaneously. @@ -476,7 +476,7 @@ static NSString *const SUUpdaterDefaultsObservationContext = @"SUUpdaterDefaults return customUserAgentString; } - NSString *version = [SPARKLE_BUNDLE objectForInfoDictionaryKey:@"CFBundleVersion"]; + NSString *version = [[NSBundle bundleWithIdentifier:SUBundleIdentifier] objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey]; NSString *userAgent = [NSString stringWithFormat:@"%@/%@ Sparkle/%@", [self.host name], [self.host displayVersion], version ? version : @"?"]; NSData *cleanedAgent = [userAgent dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; return [[NSString alloc] initWithData:cleanedAgent encoding:NSASCIIStringEncoding]; @@ -553,7 +553,7 @@ static NSString *const SUUpdaterDefaultsObservationContext = @"SUUpdaterDefaults if (intervalValue) return [intervalValue doubleValue]; else - return SU_DEFAULT_CHECK_INTERVAL; + return SUDefaultUpdateCheckInterval; } - (void)dealloc diff --git a/Frameworks/Sparkle/Sparkle/SUVersionComparisonProtocol.h b/Frameworks/Sparkle/Sparkle/SUVersionComparisonProtocol.h index d3fb3d2b9..10c426694 100644 --- a/Frameworks/Sparkle/Sparkle/SUVersionComparisonProtocol.h +++ b/Frameworks/Sparkle/Sparkle/SUVersionComparisonProtocol.h @@ -10,6 +10,7 @@ #define SUVERSIONCOMPARISONPROTOCOL_H #import +#import "SUExport.h" /*! Provides version comparison facilities for Sparkle. diff --git a/Frameworks/Sparkle/Sparkle/SUVersionDisplayProtocol.h b/Frameworks/Sparkle/Sparkle/SUVersionDisplayProtocol.h index 697f1a876..97fae4c90 100644 --- a/Frameworks/Sparkle/Sparkle/SUVersionDisplayProtocol.h +++ b/Frameworks/Sparkle/Sparkle/SUVersionDisplayProtocol.h @@ -7,7 +7,7 @@ // #import - +#import "SUExport.h" /*! Applies special display formatting to version numbers. diff --git a/Frameworks/Sparkle/Sparkle/Sparkle-Info.plist b/Frameworks/Sparkle/Sparkle/Sparkle-Info.plist index eeba51315..3d5c7f184 100644 --- a/Frameworks/Sparkle/Sparkle/Sparkle-Info.plist +++ b/Frameworks/Sparkle/Sparkle/Sparkle-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - org.andymatuschak.Sparkle + ${SPARKLE_BUNDLE_IDENTIFIER} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -17,12 +17,20 @@ CFBundlePackageType FMWK CFBundleShortVersionString - ${CURRENT_PROJECT_VERSION} git + ${CURRENT_PROJECT_VERSION} CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} NSPrincipalClass + SUAppendVersionNumber + ${SPARKLE_APPEND_VERSION_NUMBER} + SUEnableAutomatedDowngrades + ${SPARKLE_AUTOMATED_DOWNGRADES} + SUNormalizeInstalledApplicationName + ${SPARKLE_NORMALIZE_INSTALLED_APPLICATION_NAME} + SURelaunchToolName + ${SPARKLE_RELAUNCH_TOOL_NAME} diff --git a/Frameworks/Sparkle/Sparkle/Sparkle.h b/Frameworks/Sparkle/Sparkle/Sparkle.h index 954ca519f..555cb6f64 100644 --- a/Frameworks/Sparkle/Sparkle/Sparkle.h +++ b/Frameworks/Sparkle/Sparkle/Sparkle.h @@ -12,11 +12,11 @@ // This list should include the shared headers. It doesn't matter if some of them aren't shared (unless // there are name-space collisions) so we can list all of them to start with: -#import - #import #import -#import #import +#import +#import +#import #endif diff --git a/Frameworks/Sparkle/Sparkle/Sparkle.pch b/Frameworks/Sparkle/Sparkle/Sparkle.pch index 62f19dfa3..e30bf990c 100644 --- a/Frameworks/Sparkle/Sparkle/Sparkle.pch +++ b/Frameworks/Sparkle/Sparkle/Sparkle.pch @@ -8,11 +8,9 @@ #ifdef __OBJC__ -#define SPARKLE_BUNDLE [NSBundle bundleWithIdentifier:@"org.andymatuschak.Sparkle"] -#define SULocalizedString(key,comment) NSLocalizedStringFromTableInBundle(key, @"Sparkle", SPARKLE_BUNDLE, comment) -#define SUAbstractFail() NSAssert2(nil, @"Can't call %@ on an instance of %@; this is an abstract method!", __PRETTY_FUNCTION__, [self class]); - #import #import "SUConstants.h" +#define SULocalizedString(key, comment) NSLocalizedStringFromTableInBundle(key, @"Sparkle", [NSBundle bundleWithIdentifier:SUBundleIdentifier] ? [NSBundle bundleWithIdentifier:SUBundleIdentifier] : [NSBundle mainBundle], comment) + #endif diff --git a/Frameworks/Sparkle/Tests/signed_test_file b/Frameworks/Sparkle/Tests/Resources/signed-test-file.txt similarity index 100% rename from Frameworks/Sparkle/Tests/signed_test_file rename to Frameworks/Sparkle/Tests/Resources/signed-test-file.txt diff --git a/Frameworks/Sparkle/Tests/test_pubkey b/Frameworks/Sparkle/Tests/Resources/test-pubkey.pem similarity index 100% rename from Frameworks/Sparkle/Tests/test_pubkey rename to Frameworks/Sparkle/Tests/Resources/test-pubkey.pem diff --git a/Frameworks/Sparkle/Tests/SUBinaryDeltaTest.m b/Frameworks/Sparkle/Tests/SUBinaryDeltaTest.m new file mode 100644 index 000000000..c4770f7d3 --- /dev/null +++ b/Frameworks/Sparkle/Tests/SUBinaryDeltaTest.m @@ -0,0 +1,28 @@ +// +// SUBinaryDeltaTest.m +// Sparkle +// +// Created by Jake Petroules on 2014-08-22. +// Copyright (c) 2014 Sparkle Project. All rights reserved. +// + +#import +#import +#import "SUBinaryDeltaCommon.h" + +@interface SUBinaryDeltaTest : XCTestCase + +@end + +@implementation SUBinaryDeltaTest + +- (void)testTemporaryFilename +{ + NSString *tmp1 = temporaryFilename(@"Sparkle"); + NSString *tmp2 = temporaryFilename(@"Sparkle"); + NSLog(@"Temporary filenames: %@, %@", tmp1, tmp2); + XCTAssertNotEqualObjects(tmp1, tmp2); + XCTAssert(YES, @"Pass"); +} + +@end diff --git a/Frameworks/Sparkle/Tests/SUDSAVerifierTest.m b/Frameworks/Sparkle/Tests/SUDSAVerifierTest.m index 728453c67..f9c4b9831 100644 --- a/Frameworks/Sparkle/Tests/SUDSAVerifierTest.m +++ b/Frameworks/Sparkle/Tests/SUDSAVerifierTest.m @@ -11,19 +11,18 @@ #import "SUDSAVerifier.h" @interface SUDSAVerifierTest : XCTestCase -@property NSString *testDir, *testFile, *pubKeyFile; +@property NSString *testFile, *pubKeyFile; @end @implementation SUDSAVerifierTest -@synthesize testDir, testFile, pubKeyFile; +@synthesize testFile, pubKeyFile; - (void)setUp { [super setUp]; - self.testDir = [@"" __FILE__ stringByDeletingLastPathComponent]; - self.testFile = [self.testDir stringByAppendingPathComponent:@"/signed_test_file"]; - self.pubKeyFile = [self.testDir stringByAppendingPathComponent:@"test_pubkey"]; + self.testFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"signed-test-file" ofType:@"txt"]; + self.pubKeyFile = [[NSBundle bundleForClass:[self class]] pathForResource:@"test-pubkey" ofType:@"pem"]; } - (void)testVerifyFileAtPath diff --git a/Frameworks/Sparkle/Vendor/bsdiff/bspatch.c b/Frameworks/Sparkle/Vendor/bsdiff/bspatch.c index d1f8ce943..7c8c238eb 100644 --- a/Frameworks/Sparkle/Vendor/bsdiff/bspatch.c +++ b/Frameworks/Sparkle/Vendor/bsdiff/bspatch.c @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $"); #endif -#include +#include "bspatch.h" #include #include #include