diff --git a/AltKit/NSError+ALTServerError.m b/AltKit/NSError+ALTServerError.m index 7688d52f..463e2fe4 100644 --- a/AltKit/NSError+ALTServerError.m +++ b/AltKit/NSError+ALTServerError.m @@ -72,7 +72,7 @@ NSErrorDomain const AltServerInstallationErrorDomain = @"com.rileytestut.AltServ return NSLocalizedString(@"Invalid anisette data.", @""); case ALTServerErrorPluginNotFound: - return NSLocalizedString(@"Could not connect to Mail plug-in. Please make sure the plug-in is installed and Mail is running, then try again.", @""); + return NSLocalizedString(@"Could not connect to Mail plug-in. Please make sure Mail is running and that you've enabled the plug-in in Mail's preferences, then try again.", @""); } } diff --git a/AltServer/AltPlugin.mailbundle.zip b/AltServer/AltPlugin.mailbundle.zip deleted file mode 100644 index c14abd9a..00000000 Binary files a/AltServer/AltPlugin.mailbundle.zip and /dev/null differ diff --git a/AltServer/AppDelegate.swift b/AltServer/AppDelegate.swift index 094a50fd..c4dcca65 100644 --- a/AltServer/AppDelegate.swift +++ b/AltServer/AppDelegate.swift @@ -14,24 +14,27 @@ import AltSign import LaunchAtLogin import STPrivilegedTask +private let pluginDirectoryURL = URL(fileURLWithPath: "/Library/Mail/Bundles", isDirectory: true) +private let pluginURL = pluginDirectoryURL.appendingPathComponent("AltPlugin.mailbundle") + enum PluginError: LocalizedError { - case installationScriptNotFound - case failedToRun(Int) - case scriptError(String) + case cancelled + case unknown + case taskError(String) + case taskErrorCode(Int) var errorDescription: String? { switch self { - case .installationScriptNotFound: return NSLocalizedString("The installation script could not be found.", comment: "") - case .failedToRun(let errorCode): return String(format: NSLocalizedString("The installation script could not be run. (%@)", comment: ""), NSNumber(value: errorCode)) - case .scriptError(let output): return output + case .cancelled: return NSLocalizedString("Mail plug-in installation was cancelled.", comment: "") + case .unknown: return NSLocalizedString("Failed to install Mail plug-in.", comment: "") + case .taskError(let output): return output + case .taskErrorCode(let errorCode): return String(format: NSLocalizedString("There was an error installing the Mail plug-in. (Error Code: %@)", comment: ""), NSNumber(value: errorCode)) } } } -private let pluginURL = URL(fileURLWithPath: "/Library/Mail/Bundles/AltPlugin.mailbundle") - @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { @@ -108,7 +111,7 @@ private extension AppDelegate self.launchAtLoginMenuItem.state = LaunchAtLogin.isEnabled ? .on : .off self.launchAtLoginMenuItem.action = #selector(AppDelegate.toggleLaunchAtLogin(_:)) - if FileManager.default.fileExists(atPath: pluginURL.path) + if self.isMailPluginInstalled { self.installMailPluginMenuItem.title = NSLocalizedString("Uninstall Mail Plug-in", comment: "") } @@ -182,47 +185,73 @@ private extension AppDelegate let device = self.connectedDevices[index] - if !self.isMailPluginInstalled + func install() { - let result = self.installMailPlugin() - guard result else { return } + ALTDeviceManager.shared.installAltStore(to: device, appleID: username, password: password) { (result) in + switch result + { + case .success: + let content = UNMutableNotificationContent() + content.title = NSLocalizedString("Installation Succeeded", comment: "") + content.body = String(format: NSLocalizedString("AltStore was successfully installed on %@.", comment: ""), device.name) + + let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) + UNUserNotificationCenter.current().add(request) + + case .failure(InstallError.cancelled), .failure(ALTAppleAPIError.requiresTwoFactorAuthentication): + // Ignore + break + + case .failure(let error as NSError): + + let alert = NSAlert() + alert.alertStyle = .critical + alert.messageText = NSLocalizedString("Installation Failed", comment: "") + + if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? Error + { + alert.informativeText = underlyingError.localizedDescription + } + else + { + alert.informativeText = error.localizedDescription + } + + NSRunningApplication.current.activate(options: .activateIgnoringOtherApps) + + alert.runModal() + } + } } - ALTDeviceManager.shared.installAltStore(to: device, appleID: username, password: password) { (result) in - switch result - { - case .success: - let content = UNMutableNotificationContent() - content.title = NSLocalizedString("Installation Succeeded", comment: "") - content.body = String(format: NSLocalizedString("AltStore was successfully installed on %@.", comment: ""), device.name) - - let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) - UNUserNotificationCenter.current().add(request) - - case .failure(InstallError.cancelled), .failure(ALTAppleAPIError.requiresTwoFactorAuthentication): - // Ignore - break - - case .failure(let error as NSError): - - let alert = NSAlert() - alert.alertStyle = .critical - alert.messageText = NSLocalizedString("Installation Failed", comment: "") - - if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? Error - { - alert.informativeText = underlyingError.localizedDescription + if !self.isMailPluginInstalled + { + self.installMailPlugin { (result) in + DispatchQueue.main.async { + switch result + { + case .failure(PluginError.cancelled): break + case .failure(let error): + let alert = NSAlert() + alert.messageText = NSLocalizedString("Failed to Install Mail Plug-in", comment: "") + alert.informativeText = error.localizedDescription + alert.runModal() + + case .success: + let alert = NSAlert() + alert.messageText = NSLocalizedString("Mail Plug-in Installed", comment: "") + alert.informativeText = NSLocalizedString("Please restart Mail and enable AltPlugin in Mail's Preferences. Mail must be running when installing or refreshing apps with AltServer.", comment: "") + alert.runModal() + + install() + } } - else - { - alert.informativeText = error.localizedDescription - } - - NSRunningApplication.current.activate(options: .activateIgnoringOtherApps) - - alert.runModal() } } + else + { + install() + } } @objc func toggleLaunchAtLogin(_ item: NSMenuItem) @@ -241,71 +270,205 @@ private extension AppDelegate @objc func handleInstallMailPluginMenuItem(_ item: NSMenuItem) { - installMailPlugin() + if self.isMailPluginInstalled + { + self.uninstallMailPlugin { (result) in + DispatchQueue.main.async { + switch result + { + case .failure(PluginError.cancelled): break + case .failure(let error): + let alert = NSAlert() + alert.messageText = NSLocalizedString("Failed to Uninstall Mail Plug-in", comment: "") + alert.informativeText = error.localizedDescription + alert.runModal() + + case .success: + let alert = NSAlert() + alert.messageText = NSLocalizedString("Mail Plug-in Uninstalled", comment: "") + alert.informativeText = NSLocalizedString("Please restart Mail for changes to take effect. You will not be able to use AltServer until the plug-in is reinstalled.", comment: "") + alert.runModal() + } + } + } + } + else + { + self.installMailPlugin { (result) in + DispatchQueue.main.async { + switch result + { + case .failure(PluginError.cancelled): break + case .failure(let error): + let alert = NSAlert() + alert.messageText = NSLocalizedString("Failed to Install Mail Plug-in", comment: "") + alert.informativeText = error.localizedDescription + alert.runModal() + + case .success: + let alert = NSAlert() + alert.messageText = NSLocalizedString("Mail Plug-in Installed", comment: "") + alert.informativeText = NSLocalizedString("Please restart Mail and enable AltPlugin in Mail's Preferences. Mail must be running when installing or refreshing apps with AltServer.", comment: "") + alert.runModal() + } + } + } + } } - @discardableResult - func installMailPlugin() -> Bool + func installMailPlugin(completionHandler: @escaping (Result) -> Void) { do { - let previouslyInstalled = self.isMailPluginInstalled + let alert = NSAlert() + alert.messageText = NSLocalizedString("Install Mail Plug-in", comment: "") + alert.informativeText = NSLocalizedString("AltServer requires a Mail plug-in in order to retrieve necessary information about your Apple ID. Would you like to install it now?", comment: "") - if !previouslyInstalled - { - let alert = NSAlert() - alert.messageText = NSLocalizedString("Install Mail Plug-in", comment: "") - alert.informativeText = NSLocalizedString("AltServer requires a Mail plug-in in order to retrieve necessary information about your Apple ID. Would you like to install it now?", comment: "") - - alert.addButton(withTitle: NSLocalizedString("Install Plug-in", comment: "")) - alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) - - NSRunningApplication.current.activate(options: .activateIgnoringOtherApps) - - let response = alert.runModal() - guard response == .alertFirstButtonReturn else { return false } + alert.addButton(withTitle: NSLocalizedString("Install Plug-in", comment: "")) + alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) + + NSRunningApplication.current.activate(options: .activateIgnoringOtherApps) + + let response = alert.runModal() + guard response == .alertFirstButtonReturn else { throw PluginError.cancelled } + + self.downloadPlugin { (result) in + do + { + let fileURL = try result.get() + defer { try? FileManager.default.removeItem(at: fileURL) } + + // Unzip AltPlugin to plug-ins directory. + let authorization = try self.runAndKeepAuthorization("unzip", arguments: ["-o", fileURL.path, "-d", pluginDirectoryURL.path]) + guard self.isMailPluginInstalled else { throw PluginError.unknown } + + // Enable Mail plug-in preferences. + try self.run("defaults", arguments: ["write", "/Library/Preferences/com.apple.mail", "EnableBundles", "-bool", "YES"], authorization: authorization) + + print("Finished installing Mail plug-in!") + + completionHandler(.success(())) + } + catch + { + completionHandler(.failure(error)) + } } - - guard let scriptURL = Bundle.main.url(forResource: self.isMailPluginInstalled ? "UninstallPlugin" : "InstallPlugin", withExtension: "sh") else { throw PluginError.installationScriptNotFound } - - try FileManager.default.setAttributes([.posixPermissions: 0o777], ofItemAtPath: scriptURL.path) - - let task = STPrivilegedTask() - task.setLaunchPath(scriptURL.path) - task.setCurrentDirectoryPath(scriptURL.deletingLastPathComponent().path) - - let errorCode = task.launch() - guard errorCode == 0 else { throw PluginError.failedToRun(Int(errorCode)) } - - task.waitUntilExit() - - if - let outputData = task.outputFileHandle()?.readDataToEndOfFile(), - let outputString = String(data: outputData, encoding: .utf8), !outputString.isEmpty - { - throw PluginError.scriptError(outputString) - } - - if !previouslyInstalled && self.isMailPluginInstalled - { - let alert = NSAlert() - alert.messageText = NSLocalizedString("Mail Plug-in Installed", comment: "") - alert.informativeText = NSLocalizedString("Please restart Mail and enable AltPlugin in Mail's Preferences. Mail must be running when installing or refreshing apps with AltServer.", comment: "") - alert.runModal() - } - - return true } catch { - let alert = NSAlert() - alert.messageText = self.isMailPluginInstalled ? NSLocalizedString("Failed to Uninstall Mail Plug-in", comment: "") : NSLocalizedString("Failed to Install Mail Plug-in", comment: "") - alert.informativeText = error.localizedDescription - alert.runModal() - - return false + completionHandler(.failure(PluginError.cancelled)) } } + + func downloadPlugin(completionHandler: @escaping (Result) -> Void) + { + let pluginURL = URL(string: "https://f000.backblazeb2.com/file/altstore/altserver/altplugin/1_0.zip")! + + let downloadTask = URLSession.shared.downloadTask(with: pluginURL) { (fileURL, response, error) in + if let fileURL = fileURL + { + print("Downloaded plugin to URL:", fileURL) + completionHandler(.success(fileURL)) + } + else + { + completionHandler(.failure(error ?? PluginError.unknown)) + } + } + + downloadTask.resume() + } + + func uninstallMailPlugin(completionHandler: @escaping (Result) -> Void) + { + let alert = NSAlert() + alert.messageText = NSLocalizedString("Uninstall Mail Plug-in", comment: "") + alert.informativeText = NSLocalizedString("Are you sure you want to uninstall the AltServer Mail plug-in? You will no longer be able to install or refresh apps with AltStore.", comment: "") + + alert.addButton(withTitle: NSLocalizedString("Uninstall Plug-in", comment: "")) + alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) + + NSRunningApplication.current.activate(options: .activateIgnoringOtherApps) + + let response = alert.runModal() + guard response == .alertFirstButtonReturn else { return completionHandler(.failure(PluginError.cancelled)) } + + DispatchQueue.global().async { + do + { + if FileManager.default.fileExists(atPath: pluginURL.path) + { + // Delete Mail plug-in from privileged directory. + try self.run("rm", arguments: ["-rf", pluginURL.path]) + } + + completionHandler(.success(())) + } + catch + { + completionHandler(.failure(error)) + } + } + } +} + +private extension AppDelegate +{ + func run(_ program: String, arguments: [String], authorization: AuthorizationRef? = nil) throws + { + _ = try self._run(program, arguments: arguments, authorization: authorization, freeAuthorization: true) + } + + func runAndKeepAuthorization(_ program: String, arguments: [String], authorization: AuthorizationRef? = nil) throws -> AuthorizationRef + { + return try self._run(program, arguments: arguments, authorization: authorization, freeAuthorization: false) + } + + func _run(_ program: String, arguments: [String], authorization: AuthorizationRef? = nil, freeAuthorization: Bool) throws -> AuthorizationRef + { + var launchPath = "/usr/bin/" + program + if !FileManager.default.fileExists(atPath: launchPath) + { + launchPath = "/bin/" + program + } + + print("Running program:", launchPath) + + let task = STPrivilegedTask() + task.launchPath = launchPath + task.arguments = arguments + task.freeAuthorizationWhenDone = freeAuthorization + + let errorCode: OSStatus + + if let authorization = authorization + { + errorCode = task.launch(withAuthorization: authorization) + } + else + { + errorCode = task.launch() + } + + guard errorCode == 0 else { throw PluginError.taskErrorCode(Int(errorCode)) } + + task.waitUntilExit() + + guard task.terminationStatus == 0 else { + let outputData = task.outputFileHandle.readDataToEndOfFile() + + if let outputString = String(data: outputData, encoding: .utf8), !outputString.isEmpty + { + throw PluginError.taskError(outputString) + } + + throw PluginError.taskErrorCode(Int(task.terminationStatus)) + } + + guard let authorization = task.authorization else { throw PluginError.unknown } + return authorization + } } extension AppDelegate: NSMenuDelegate diff --git a/AltServer/InstallPlugin.sh b/AltServer/InstallPlugin.sh deleted file mode 100644 index 302da4a4..00000000 --- a/AltServer/InstallPlugin.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -# InstallAltPlugin.sh -# AltStore -# -# Created by Riley Testut on 11/16/19. -# Copyright © 2019 Riley Testut. All rights reserved. - -rm -f AltPlugin.mailbundle -unzip AltPlugin.mailbundle.zip 1>/dev/null -mkdir -p /Library/Mail/Bundles -cp -r AltPlugin.mailbundle /Library/Mail/Bundles -defaults write "/Library/Preferences/com.apple.mail" EnableBundles 1 diff --git a/AltServer/UninstallPlugin.sh b/AltServer/UninstallPlugin.sh deleted file mode 100644 index 5d3ab257..00000000 --- a/AltServer/UninstallPlugin.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# UninstallPlugin.sh -# AltStore -# -# Created by Riley Testut on 11/16/19. -# Copyright © 2019 Riley Testut. All rights reserved. - -rm -rf /Library/Mail/Bundles/AltPlugin.mailbundle diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index 8e188abd..ece28c99 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -115,7 +115,6 @@ BF45884B2298D55000BD7491 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = BF4588492298D55000BD7491 /* thread.h */; }; BF4588882298DD3F00BD7491 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = BF4588872298DD3F00BD7491 /* libxml2.tbd */; }; BF4C7F2523801F0800B2556E /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9B63C5229DD44D002F0A62 /* AltSign.framework */; }; - BF4C7F27238086EB00B2556E /* InstallPlugin.sh in Resources */ = {isa = PBXBuildFile; fileRef = BF4C7F26238086EB00B2556E /* InstallPlugin.sh */; }; BF54E8212315EF0D000AE0D8 /* ALTPatreonBenefitType.m in Sources */ = {isa = PBXBuildFile; fileRef = BF54E8202315EF0D000AE0D8 /* ALTPatreonBenefitType.m */; }; BF56D2AA23DF88310006506D /* AppID.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF56D2A923DF88310006506D /* AppID.swift */; }; BF56D2AC23DF8E170006506D /* FetchAppIDsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF56D2AB23DF8E170006506D /* FetchAppIDsOperation.swift */; }; @@ -137,7 +136,6 @@ BF7C627423DBB78C00515A2D /* InstalledAppPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF7C627323DBB78C00515A2D /* InstalledAppPolicy.swift */; }; BF8F69C222E659F700049BA1 /* AppContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8F69C122E659F700049BA1 /* AppContentViewController.swift */; }; BF8F69C422E662D300049BA1 /* AppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8F69C322E662D300049BA1 /* AppViewController.swift */; }; - BF914C262383703800E713BA /* AltPlugin.mailbundle.zip in Resources */ = {isa = PBXBuildFile; fileRef = BF914C252383703800E713BA /* AltPlugin.mailbundle.zip */; }; BF9A03C623C7DD0D000D08DB /* ClientConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9A03C523C7DD0D000D08DB /* ClientConnection.swift */; }; BF9ABA4522DCFF43008935CF /* BrowseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9ABA4422DCFF43008935CF /* BrowseViewController.swift */; }; BF9ABA4722DD0638008935CF /* BrowseCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9ABA4622DD0638008935CF /* BrowseCollectionViewCell.swift */; }; @@ -208,7 +206,6 @@ BFD5D6F4230DDB0A007955AB /* Campaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD5D6F3230DDB0A007955AB /* Campaign.swift */; }; BFD5D6F6230DDB12007955AB /* Tier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD5D6F5230DDB12007955AB /* Tier.swift */; }; BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */; }; - BFD80D572380C0F700B9C227 /* UninstallPlugin.sh in Resources */ = {isa = PBXBuildFile; fileRef = BFD80D562380C0F700B9C227 /* UninstallPlugin.sh */; }; BFDB5B1622EE90D300F74113 /* Date+RelativeDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */; }; BFDB5B2622EFBBEA00F74113 /* BrowseCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BFDB5B2522EFBBEA00F74113 /* BrowseCollectionViewCell.xib */; }; BFDB6A0522A9AFB2007EA6D6 /* Fetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */; }; @@ -422,7 +419,6 @@ BF4588872298DD3F00BD7491 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/lib/libxml2.tbd; sourceTree = DEVELOPER_DIR; }; BF4588962298DE6E00BD7491 /* libzip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = libzip.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BF4713A422976CFC00784A2F /* openssl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = openssl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BF4C7F26238086EB00B2556E /* InstallPlugin.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = InstallPlugin.sh; sourceTree = ""; }; BF54E81F2315EF0D000AE0D8 /* ALTPatreonBenefitType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALTPatreonBenefitType.h; sourceTree = ""; }; BF54E8202315EF0D000AE0D8 /* ALTPatreonBenefitType.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALTPatreonBenefitType.m; sourceTree = ""; }; BF56D2A823DF87570006506D /* AltStore 4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 4.xcdatamodel"; sourceTree = ""; }; @@ -456,7 +452,6 @@ BF7C627323DBB78C00515A2D /* InstalledAppPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledAppPolicy.swift; sourceTree = ""; }; BF8F69C122E659F700049BA1 /* AppContentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppContentViewController.swift; sourceTree = ""; }; BF8F69C322E662D300049BA1 /* AppViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppViewController.swift; sourceTree = ""; }; - BF914C252383703800E713BA /* AltPlugin.mailbundle.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = AltPlugin.mailbundle.zip; sourceTree = ""; }; BF9A03C523C7DD0D000D08DB /* ClientConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConnection.swift; sourceTree = ""; }; BF9ABA4422DCFF43008935CF /* BrowseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseViewController.swift; sourceTree = ""; }; BF9ABA4622DD0638008935CF /* BrowseCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseCollectionViewCell.swift; sourceTree = ""; }; @@ -535,7 +530,6 @@ BFD5D6F3230DDB0A007955AB /* Campaign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Campaign.swift; sourceTree = ""; }; BFD5D6F5230DDB12007955AB /* Tier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tier.swift; sourceTree = ""; }; BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAppsComponents.swift; sourceTree = ""; }; - BFD80D562380C0F700B9C227 /* UninstallPlugin.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = UninstallPlugin.sh; sourceTree = ""; }; BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+RelativeDate.swift"; sourceTree = ""; }; BFDB5B2522EFBBEA00F74113 /* BrowseCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrowseCollectionViewCell.xib; sourceTree = ""; }; BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fetchable.swift; sourceTree = ""; }; @@ -885,9 +879,6 @@ isa = PBXGroup; children = ( BF458693229872EA00BD7491 /* Assets.xcassets */, - BF914C252383703800E713BA /* AltPlugin.mailbundle.zip */, - BF4C7F26238086EB00B2556E /* InstallPlugin.sh */, - BFD80D562380C0F700B9C227 /* UninstallPlugin.sh */, ); name = Resources; sourceTree = ""; @@ -1415,11 +1406,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - BF914C262383703800E713BA /* AltPlugin.mailbundle.zip in Resources */, - BFD80D572380C0F700B9C227 /* UninstallPlugin.sh in Resources */, BF458694229872EA00BD7491 /* Assets.xcassets in Resources */, BF458697229872EA00BD7491 /* Main.storyboard in Resources */, - BF4C7F27238086EB00B2556E /* InstallPlugin.sh in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Podfile b/Podfile index 949f932f..8540553f 100644 --- a/Podfile +++ b/Podfile @@ -19,7 +19,7 @@ target 'AltServer' do use_frameworks! # Pods for AltServer - pod 'STPrivilegedTask' + pod 'STPrivilegedTask', :git => 'https://github.com/rileytestut/STPrivilegedTask.git' pod 'Sparkle' end diff --git a/Podfile.lock b/Podfile.lock index 1e9f8973..139826c2 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -14,7 +14,7 @@ PODS: - Nuke (7.6.3) - Roxas (0.1) - Sparkle (1.21.3) - - STPrivilegedTask (1.0.1) + - STPrivilegedTask (1.0.7) DEPENDENCIES: - AltSign (from `Dependencies/AltSign`) @@ -22,20 +22,26 @@ DEPENDENCIES: - Nuke (~> 7.0) - Roxas (from `Dependencies/Roxas`) - Sparkle - - STPrivilegedTask + - STPrivilegedTask (from `https://github.com/rileytestut/STPrivilegedTask.git`) SPEC REPOS: trunk: - KeychainAccess - Nuke - Sparkle - - STPrivilegedTask EXTERNAL SOURCES: AltSign: :path: Dependencies/AltSign Roxas: :path: Dependencies/Roxas + STPrivilegedTask: + :git: https://github.com/rileytestut/STPrivilegedTask.git + +CHECKOUT OPTIONS: + STPrivilegedTask: + :commit: c8dd3e41b23666d4010c86b052a921a8e5a320d0 + :git: https://github.com/rileytestut/STPrivilegedTask.git SPEC CHECKSUMS: AltSign: c3693fa5a4b6d0ec6bedb74a5d768fe58bd67b87 @@ -43,8 +49,8 @@ SPEC CHECKSUMS: Nuke: 44130e95e09463f8773ae4b96b90de1eba6b3350 Roxas: 1990039f843f5dc284918dc82375feb80020ef62 Sparkle: 3f75576db8b0265adef36c43249d747f22d0b708 - STPrivilegedTask: 103f97827454e786074640cf89d303be344498c7 + STPrivilegedTask: 56c3397238a1ec07720fb877a044898373cd2c68 -PODFILE CHECKSUM: 467b50b42949f001543841f547fa6b427e29dc53 +PODFILE CHECKSUM: 1503b17048964bd0586d5470e6ee1e57917934de COCOAPODS: 1.8.4 diff --git a/Pods/Local Podspecs/STPrivilegedTask.podspec.json b/Pods/Local Podspecs/STPrivilegedTask.podspec.json new file mode 100644 index 00000000..dbc8cc86 --- /dev/null +++ b/Pods/Local Podspecs/STPrivilegedTask.podspec.json @@ -0,0 +1,25 @@ +{ + "name": "STPrivilegedTask", + "version": "1.0.7", + "summary": "An NSTask-like wrapper around Mac OS X Security Framework's AuthorizationExecuteWithPrivileges()", + "description": "An NSTask-like wrapper around AuthorizationExecuteWithPrivileges() in the Security API to run shell commands with root privileges in Mac OS X.", + "homepage": "http://github.com/sveinbjornt/STPrivilegedTask", + "license": { + "type": "BSD" + }, + "authors": { + "Sveinbjorn Thordarson": "sveinbjorn@sveinbjorn.org" + }, + "platforms": { + "osx": "10.8" + }, + "source": { + "git": "https://github.com/sveinbjornt/STPrivilegedTask.git", + "tag": "1.0.7" + }, + "source_files": "STPrivilegedTask.{h,m}", + "exclude_files": "PrivilegedTaskExample", + "public_header_files": "STPrivilegedTask.h", + "frameworks": "Security", + "requires_arc": false +} diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index 1e9f8973..139826c2 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -14,7 +14,7 @@ PODS: - Nuke (7.6.3) - Roxas (0.1) - Sparkle (1.21.3) - - STPrivilegedTask (1.0.1) + - STPrivilegedTask (1.0.7) DEPENDENCIES: - AltSign (from `Dependencies/AltSign`) @@ -22,20 +22,26 @@ DEPENDENCIES: - Nuke (~> 7.0) - Roxas (from `Dependencies/Roxas`) - Sparkle - - STPrivilegedTask + - STPrivilegedTask (from `https://github.com/rileytestut/STPrivilegedTask.git`) SPEC REPOS: trunk: - KeychainAccess - Nuke - Sparkle - - STPrivilegedTask EXTERNAL SOURCES: AltSign: :path: Dependencies/AltSign Roxas: :path: Dependencies/Roxas + STPrivilegedTask: + :git: https://github.com/rileytestut/STPrivilegedTask.git + +CHECKOUT OPTIONS: + STPrivilegedTask: + :commit: c8dd3e41b23666d4010c86b052a921a8e5a320d0 + :git: https://github.com/rileytestut/STPrivilegedTask.git SPEC CHECKSUMS: AltSign: c3693fa5a4b6d0ec6bedb74a5d768fe58bd67b87 @@ -43,8 +49,8 @@ SPEC CHECKSUMS: Nuke: 44130e95e09463f8773ae4b96b90de1eba6b3350 Roxas: 1990039f843f5dc284918dc82375feb80020ef62 Sparkle: 3f75576db8b0265adef36c43249d747f22d0b708 - STPrivilegedTask: 103f97827454e786074640cf89d303be344498c7 + STPrivilegedTask: 56c3397238a1ec07720fb877a044898373cd2c68 -PODFILE CHECKSUM: 467b50b42949f001543841f547fa6b427e29dc53 +PODFILE CHECKSUM: 1503b17048964bd0586d5470e6ee1e57917934de COCOAPODS: 1.8.4 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 20debb76..4c729882 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXAggregateTarget section */ @@ -2211,7 +2211,7 @@ LastUpgradeCheck = 1100; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 9.3"; + compatibilityVersion = "Xcode 10.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -2532,45 +2532,6 @@ }; name = Debug; }; - 01FC26EF7492A83715733D6E82B58E10 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B763A613B013538736809BCA42B6DEF0 /* STPrivilegedTask.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "Target Support Files/STPrivilegedTask/STPrivilegedTask-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.6; - MODULEMAP_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask.modulemap"; - PRODUCT_MODULE_NAME = STPrivilegedTask; - PRODUCT_NAME = STPrivilegedTask; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; 03A826C198089C15D11AC65F5BED730D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3A44D4EBF7CD579B73B275F0F125F846 /* Pods-AltServer.debug.xcconfig */; @@ -2843,45 +2804,6 @@ }; name = Release; }; - 569B2F7FFE1A40245840B5BD14E5075B /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = B763A613B013538736809BCA42B6DEF0 /* STPrivilegedTask.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - GCC_PREFIX_HEADER = "Target Support Files/STPrivilegedTask/STPrivilegedTask-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 10.6; - MODULEMAP_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask.modulemap"; - PRODUCT_MODULE_NAME = STPrivilegedTask; - PRODUCT_NAME = STPrivilegedTask; - SDKROOT = macosx; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; 5AFD67EFA6B3F27B4F0B0F8027C335F7 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5B1BF3395506426B10A06E5307D1EEFA /* Sparkle.xcconfig */; @@ -3044,6 +2966,44 @@ }; name = Debug; }; + DAA2BB16DE5BB8A33D1F4FEBC5F6E540 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B763A613B013538736809BCA42B6DEF0 /* STPrivilegedTask.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_PREFIX_HEADER = "Target Support Files/STPrivilegedTask/STPrivilegedTask-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.8; + MODULEMAP_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask.modulemap"; + PRODUCT_MODULE_NAME = STPrivilegedTask; + PRODUCT_NAME = STPrivilegedTask; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; E8921B3E2DFC77CDA00FEE1D9EA36AA0 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1215053FA027E4CE849DAF4D00697FF1 /* Pods-AltServer.release.xcconfig */; @@ -3085,6 +3045,44 @@ }; name = Release; }; + F53E3123D6E0B1A60F1DFB065889DFD7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B763A613B013538736809BCA42B6DEF0 /* STPrivilegedTask.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_PREFIX_HEADER = "Target Support Files/STPrivilegedTask/STPrivilegedTask-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.8; + MODULEMAP_FILE = "Target Support Files/STPrivilegedTask/STPrivilegedTask.modulemap"; + PRODUCT_MODULE_NAME = STPrivilegedTask; + PRODUCT_NAME = STPrivilegedTask; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -3118,8 +3116,8 @@ 54208ED19403AA500F1198EEF237E880 /* Build configuration list for PBXNativeTarget "STPrivilegedTask" */ = { isa = XCConfigurationList; buildConfigurations = ( - 01FC26EF7492A83715733D6E82B58E10 /* Debug */, - 569B2F7FFE1A40245840B5BD14E5075B /* Release */, + F53E3123D6E0B1A60F1DFB065889DFD7 /* Debug */, + DAA2BB16DE5BB8A33D1F4FEBC5F6E540 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Pods/STPrivilegedTask/LICENSE b/Pods/STPrivilegedTask/LICENSE new file mode 100644 index 00000000..61b39da5 --- /dev/null +++ b/Pods/STPrivilegedTask/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2009, Sveinbjorn Thordarson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Pods/STPrivilegedTask/LICENSE.txt b/Pods/STPrivilegedTask/LICENSE.txt deleted file mode 100644 index 5d6d508b..00000000 --- a/Pods/STPrivilegedTask/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ - # BSD License - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above copyright - # notice, this list of conditions and the following disclaimer in the - # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other - # contributors may be used to endorse or promote products - # derived from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Pods/STPrivilegedTask/README.md b/Pods/STPrivilegedTask/README.md index 46c7d726..2bde9b43 100644 --- a/Pods/STPrivilegedTask/README.md +++ b/Pods/STPrivilegedTask/README.md @@ -1,58 +1,193 @@ # STPrivilegedTask - Objective C class -An NSTask-like wrapper around AuthorizationExecuteWithPrivileges() in the Security API to run shell commands with root privileges in Mac OS X. +An NSTask-like wrapper around [AuthorizationExecuteWithPrivileges()](https://developer.apple.com/library/mac/documentation/Security/Reference/authorization_ref/#//apple_ref/c/func/AuthorizationExecuteWithPrivileges) in the Security API to run shell commands with root privileges in Mac OS X. -Example of usage: +STPrivilegedTask was created a long time ago. It has now been updated to support ARC and is available via CocoaPods. + +## Examples + +### Create and launch task ```objective-c +// Create task STPrivilegedTask *privilegedTask = [[STPrivilegedTask alloc] init]; - [privilegedTask setLaunchPath:@"/usr/bin/touch"]; -NSArray *args = [NSArray arrayWithObject:@"/etc/my_test_file"]; -[privilegedTask setArguments:args]; -[privilegedTask setCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]]; +[privilegedTask setArguments:@[@"/etc/my_test_file"]]; -//set it off +// Setting working directory is optional, defaults to / +// NSString *path = [[NSBundle mainBundle] resourcePath]; +// [privilegedTask setCurrentDirectoryPath:path]; + +// Launch it, user is prompted for password OSStatus err = [privilegedTask launch]; -if (err != errAuthorizationSuccess) { - if (err == errAuthorizationCanceled) { - NSLog(@"User cancelled"); - } else { - NSLog(@"Something went wrong"); - } +if (err == errAuthorizationSuccess) { + NSLog(@"Task successfully launched"); } +else if (err == errAuthorizationCanceled) { + NSLog(@"User cancelled"); +} +else { + NSLog(@"Something went wrong"); +} +``` +See [Authorization.h](http://www.opensource.apple.com/source/libsecurity_authorization/libsecurity_authorization-36329/lib/Authorization.h) for a list of possible error codes. + +### Launch task one-liner + +```objective-c +OSStatus err = [STPrivilegedTask launchedPrivilegedTaskWithLaunchPath:@"/bin/sh" + arguments:@[@"/path/to/script.sh"]]; + + +``` + + +### Getting task output + +```objective-c +// ... launch task + +[privilegedTask waitUntilExit]; // Read output file handle for data -NSFileHandle *readHandle = [privilegedTask outputFileHandle]; -NSData *outputData = [readHandle readDataToEndOfFile]; +NSData *outputData = [[privilegedTask outputFileHandle] readDataToEndOfFile]; NSString *outputString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding]; ``` -# BSD License +### Getting output while task runs in background +```objective-c + +// ... launch task + +NSFileHandle *readHandle = [privilegedTask outputFileHandle]; +[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOutputData:) name:NSFileHandleReadCompletionNotification object:readHandle]; +[readHandle readInBackgroundAndNotify]; + +// ... + +- (void)getOutputData:(NSNotification *)aNotification { + //get data from notification + NSData *data = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem]; + + //make sure there's actual data + if ([data length]) { + // do something with the data + NSString *outputString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSLog(outputString); + + // go read more data in the background + [[aNotification object] readInBackgroundAndNotify]; + } else { + // do something else + } +} ``` - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above copyright - # notice, this list of conditions and the following disclaimer in the - # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other - # contributors may be used to endorse or promote products - # derived from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +### Task termination -``` \ No newline at end of file +You can observe STPrivilegedTaskDidTerminateNotification: + +```objective-c +[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(privilegedTaskFinished:) name:STPrivilegedTaskDidTerminateNotification object:nil]; + +- (void)privilegedTaskFinished:(NSNotification *)aNotification { + // do something +} +``` + +Or alternately, set a termination handler: + +```objective-c +privilegedTask.terminationHandler = ^(STPrivilegedTask *privilegedTask) { + NSLog(@"Terminating task: %@", [privilegedTask description]); +}; +``` + +### Launch using external AuthorizationRef + +```objective-c +// ... Create your own AuthorizationRef + +[STPriviledTask launchedPrivilegedTaskWithLaunchPath:@"/bin/sh" + arguments:@"/path/to/script" + currentDirectory:@"/" + authorization:authRef] +``` + +### AuthorizationExecuteWithPrivileges() is deprecated + +[AuthorizationExecuteWithPrivileges()](https://developer.apple.com/library/mac/documentation/Security/Reference/authorization_ref/#//apple_ref/c/func/AuthorizationExecuteWithPrivileges) is deprecated as of macOS 10.7 but remains available +in 10.14 Mojave. If you want to be future-proof, here's how you check if STPrivilegedTask +works in the running version of macOS: + +```objective-c +OSStatus err = [privilegedTask launch]; +if (err == errAuthorizationFnNoLongerExists) { + NSLog(@"AuthorizationExecuteWithPrivileges not available"); +} +``` + +If you need to check whether STPrivilegedTask works before you launch the task: + +```objective-c +BOOL works = [STPrivilegedTask authorizationFunctionAvailable]; +``` + +## Sample app + +A sample app which makes use of STPrivilegedTask is included in the project. This app runs the following script: + +``` +#!/bin/sh + +echo "/usr/bin/whoami:" +whoami +echo "" +echo "Real User ID:" +echo $UID \($USER\) +echo "" +echo "Effective User ID:" +/usr/bin/id -u +echo "" +echo "Current working directory:" +echo "$PWD" + +exit 5 +``` + +It then presents the output of the script in a window, along with the exit code. + + + + +## BSD License + +Copyright (c) Sveinbjorn Thordarson <sveinbjorn@sveinbjorn.org> +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may +be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Pods/STPrivilegedTask/STPrivilegedTask.h b/Pods/STPrivilegedTask/STPrivilegedTask.h old mode 100644 new mode 100755 index 77932be8..18f4da17 --- a/Pods/STPrivilegedTask/STPrivilegedTask.h +++ b/Pods/STPrivilegedTask/STPrivilegedTask.h @@ -1,7 +1,6 @@ /* - # # STPrivilegedTask - NSTask-like wrapper around AuthorizationExecuteWithPrivileges - # Copyright (C) 2009-2015 Sveinbjorn Thordarson + # Copyright (C) 2009-2017 Sveinbjorn Thordarson # # BSD License # Redistribution and use in source and binary forms, with or without @@ -11,7 +10,7 @@ # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other + # * Neither the name of the copyright holder nor that of any other # contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # @@ -28,54 +27,43 @@ */ #import -#import -#import -#import #define STPrivilegedTaskDidTerminateNotification @"STPrivilegedTaskDidTerminateNotification" -//#define TMP_STDERR_TEMPLATE @".authStderr.XXXXXX" -// Defines error value for when AuthorizationExecuteWithPrivilleges no longer -// exists anyplace. Rather than defining a new enum, we just create a global -// constant +// Defines error value for when AuthorizationExecuteWithPrivileges no longer exists +// Rather than defining a new enum, we just create a global constant extern const OSStatus errAuthorizationFnNoLongerExists; -@interface STPrivilegedTask : NSObject -{ - NSArray *arguments; - NSString *cwd; - NSString *launchPath; - BOOL isRunning; - pid_t pid; - int terminationStatus; - NSFileHandle *outputFileHandle; - NSTimer *checkStatusTimer; -} --(id)initWithLaunchPath:(NSString *)path; --(id)initWithLaunchPath:(NSString *)path arguments: (NSArray *)args; -+(STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path; -+(STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments; --(NSArray *)arguments; --(NSString *)currentDirectoryPath; --(BOOL)isRunning; --(int)launch; --(NSString *)launchPath; --(int)processIdentifier; --(void)setArguments:(NSArray *)arguments; --(void)setCurrentDirectoryPath:(NSString *)path; --(void)setLaunchPath:(NSString *)path; --(NSFileHandle *)outputFileHandle; --(void)terminate; // doesn't work --(int)terminationStatus; --(void)_checkTaskStatus; --(void)waitUntilExit; +@interface STPrivilegedTask : NSObject + +@property (copy) NSArray *arguments; +@property (copy) NSString *currentDirectoryPath; +@property (copy) NSString *launchPath; +@property (assign) BOOL freeAuthorizationWhenDone; + +@property (readonly) NSFileHandle *outputFileHandle; +@property (readonly) BOOL isRunning; +@property (readonly) pid_t processIdentifier; +@property (readonly) int terminationStatus; +@property (readonly) AuthorizationRef authorization; + +@property (copy) void (^terminationHandler)(STPrivilegedTask *); + ++ (BOOL)authorizationFunctionAvailable; + +- (instancetype)initWithLaunchPath:(NSString *)path; +- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args; +- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd; + ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path; ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args; ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd; ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd authorization:(AuthorizationRef)authorization; + +- (OSStatus)launch; +- (OSStatus)launchWithAuthorization:(AuthorizationRef)authorization; +- (void)terminate; // doesn't work +- (void)waitUntilExit; + @end -/*static OSStatus AuthorizationExecuteWithPrivilegesStdErrAndPid ( - AuthorizationRef authorization, - const char *pathToTool, - AuthorizationFlags options, - char * const *arguments, - FILE **communicationsPipe, - FILE **errPipe, - pid_t* processid - );*/ + diff --git a/Pods/STPrivilegedTask/STPrivilegedTask.m b/Pods/STPrivilegedTask/STPrivilegedTask.m old mode 100644 new mode 100755 index c94c2f02..ce326d70 --- a/Pods/STPrivilegedTask/STPrivilegedTask.m +++ b/Pods/STPrivilegedTask/STPrivilegedTask.m @@ -1,7 +1,6 @@ /* - # # STPrivilegedTask - NSTask-like wrapper around AuthorizationExecuteWithPrivileges - # Copyright (C) 2009-2015 Sveinbjorn Thordarson + # Copyright (C) 2009-2017 Sveinbjorn Thordarson # # BSD License # Redistribution and use in source and binary forms, with or without @@ -11,7 +10,7 @@ # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other + # * Neither the name of the copyright holder nor that of any other # contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # @@ -25,192 +24,154 @@ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + */ #import "STPrivilegedTask.h" + +#import +#import #import #import #import -/* New error code denoting that AuthorizationExecuteWithPrivileges no longer exists */ +// New error code denoting that AuthorizationExecuteWithPrivileges no longer exists OSStatus const errAuthorizationFnNoLongerExists = -70001; +// Create fn pointer to AuthorizationExecuteWithPrivileges in case +// it doesn't exist in this version of MacOS +static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const char *pathToTool, AuthorizationFlags options, + char * const *arguments, FILE **communicationsPipe) = NULL; + + @implementation STPrivilegedTask - -- (id)init { - if ((self = [super init])) { - launchPath = @""; - cwd = [[NSString alloc] initWithString:[[NSFileManager defaultManager] currentDirectoryPath]]; - arguments = [[NSArray alloc] init]; - isRunning = NO; - outputFileHandle = nil; + NSTimer *_checkStatusTimer; +} + ++ (void)initialize; +{ + // On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want + // to still use it since there's no good alternative (without requiring + // code signing). We'll look up the function through dyld and fail if + // it is no longer accessible. If Apple removes the function entirely + // this will fail gracefully. If they keep the function and throw some + // sort of exception, this won't fail gracefully, but that's a risk + // we'll have to take for now. + // Pattern by Andy Kim from Potion Factory LLC +#pragma GCC diagnostic ignored "-Wpedantic" // stop the pedantry! +#pragma clang diagnostic push + _AuthExecuteWithPrivsFn = dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges"); +#pragma clang diagnostic pop +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _launchPath = nil; + _arguments = nil; + _freeAuthorizationWhenDone = YES; + _isRunning = NO; + _outputFileHandle = nil; + _terminationHandler = nil; + _authorization = nil; + _currentDirectoryPath = [[NSFileManager defaultManager] currentDirectoryPath]; } return self; } --(void)dealloc +- (instancetype)initWithLaunchPath:(NSString *)path { -#if !__has_feature(objc_arc) - [launchPath release]; - [arguments release]; - [cwd release]; - - if (outputFileHandle != nil) { - [outputFileHandle release]; - } - [super dealloc]; -#endif -} - --(id)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args -{ - if ((self = [self initWithLaunchPath:path])) { - [self setArguments:args]; + self = [self init]; + if (self) { + self.launchPath = path; } return self; } --(id)initWithLaunchPath:(NSString *)path +- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args { - if ((self = [self init])) { - [self setLaunchPath:path]; + self = [self initWithLaunchPath:path]; + if (self) { + self.arguments = args; } return self; } +- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd +{ + self = [self initWithLaunchPath:path arguments:args]; + if (self) { + self.currentDirectoryPath = cwd; + } + return self; +} + +- (void)dealloc +{ + if (_freeAuthorizationWhenDone && _authorization != nil) { + // free the auth ref + AuthorizationFree(_authorization, kAuthorizationFlagDefaults); + } +} + #pragma mark - -+(STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args -{ - STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args]; -#if !__has_feature(objc_arc) - [task autorelease]; -#endif - - [task launch]; - [task waitUntilExit]; - return task; -} - -+(STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path { STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path]; -#if !__has_feature(objc_arc) - [task autorelease]; -#endif [task launch]; [task waitUntilExit]; return task; } -#pragma mark - - -- (NSArray *)arguments ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args { - return arguments; + STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args]; + [task launch]; + [task waitUntilExit]; + return task; } -- (NSString *)currentDirectoryPath; ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd { - return cwd; + STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args currentDirectory:cwd]; + [task launch]; + [task waitUntilExit]; + return task; } -- (BOOL)isRunning ++ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd authorization:(AuthorizationRef)authorization { - return isRunning; -} - -- (NSString *)launchPath -{ - return launchPath; -} - -- (int)processIdentifier -{ - return pid; -} - -- (int)terminationStatus -{ - return terminationStatus; -} - -- (NSFileHandle *)outputFileHandle; -{ - return outputFileHandle; -} - -#pragma mark - - --(void)setArguments:(NSArray *)args -{ -#if !__has_feature(objc_arc) - [arguments release]; - [args retain]; -#endif - arguments = args; -} - --(void)setCurrentDirectoryPath:(NSString *)path -{ -#if !__has_feature(objc_arc) - [cwd release]; - [path retain]; -#endif - cwd = path; -} - --(void)setLaunchPath:(NSString *)path -{ -#if !__has_feature(objc_arc) - [launchPath release]; - [path retain]; -#endif - launchPath = path; + STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args currentDirectory:cwd]; + [task launchWithAuthorization:authorization]; + [task waitUntilExit]; + return task; } # pragma mark - // return 0 for success --(int)launch +- (OSStatus)launch { + if (_isRunning) { + NSLog(@"Task already running: %@", [self description]); + return 0; + } + + if ([STPrivilegedTask authorizationFunctionAvailable] == NO) { + NSLog(@"AuthorizationExecuteWithPrivileges() function not available on this system"); + return errAuthorizationFnNoLongerExists; + } + OSStatus err = noErr; - const char *toolPath = [launchPath fileSystemRepresentation]; + const char *toolPath = [self.launchPath fileSystemRepresentation]; AuthorizationRef authorizationRef; - AuthorizationItem myItems = {kAuthorizationRightExecute, strlen(toolPath), &toolPath, 0}; - AuthorizationRights myRights = {1, &myItems}; + AuthorizationItem myItems = { kAuthorizationRightExecute, strlen(toolPath), &toolPath, 0 }; + AuthorizationRights myRights = { 1, &myItems }; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; - NSUInteger numberOfArguments = [arguments count]; - char *args[numberOfArguments + 1]; - FILE *outputFile; - - // Create fn pointer to AuthorizationExecuteWithPrivileges in case it doesn't exist - // in this version of MacOS - static OSStatus (*_AuthExecuteWithPrivsFn)( - AuthorizationRef authorization, const char *pathToTool, AuthorizationFlags options, - char * const *arguments, FILE **communicationsPipe) = NULL; - - // Check to see if we have the correct function in our loaded libraries - if (!_AuthExecuteWithPrivsFn) { - // On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want - // to still use it since there's no good alternative (without requiring - // code signing). We'll look up the function through dyld and fail if - // it is no longer accessible. If Apple removes the function entirely - // this will fail gracefully. If they keep the function and throw some - // sort of exception, this won't fail gracefully, but that's a risk - // we'll have to take for now. - // Pattern by Andy Kim from Potion Factory LLC - _AuthExecuteWithPrivsFn = dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges"); - if (!_AuthExecuteWithPrivsFn) { - // This version of OS X has finally removed this function. Exit with an error. - err = errAuthorizationFnNoLongerExists; - return err; - } - } - // Use Apple's Authentication Manager APIs to get an Authorization Reference // These Apple APIs are quite possibly the most horrible of the Mac OS X APIs @@ -227,24 +188,51 @@ OSStatus const errAuthorizationFnNoLongerExists = -70001; } // OK, at this point we have received authorization for the task. + err = [self launchWithAuthorization:authorizationRef]; + + return err; +} + +- (OSStatus)launchWithAuthorization:(AuthorizationRef)authorization +{ + _authorization = authorization; + + if (_isRunning) { + NSLog(@"Task already running: %@", [self description]); + return 0; + } + + if ([STPrivilegedTask authorizationFunctionAvailable] == NO) { + NSLog(@"AuthorizationExecuteWithPrivileges() function not available on this system"); + return errAuthorizationFnNoLongerExists; + } + + // Assuming the authorization is valid for the task. // Let's prepare to launch it + NSArray *arguments = self.arguments; + NSUInteger numberOfArguments = [arguments count]; + char *args[numberOfArguments + 1]; + FILE *outputFile; + + const char *toolPath = [self.launchPath fileSystemRepresentation]; // first, construct an array of c strings from NSArray w. arguments for (int i = 0; i < numberOfArguments; i++) { NSString *argString = arguments[i]; - NSUInteger stringLength = [argString length]; + const char *fsrep = [argString fileSystemRepresentation]; + NSUInteger stringLength = strlen(fsrep); args[i] = malloc((stringLength + 1) * sizeof(char)); - snprintf(args[i], stringLength + 1, "%s", [argString fileSystemRepresentation]); + snprintf(args[i], stringLength + 1, "%s", fsrep); } args[numberOfArguments] = NULL; // change to the current dir specified char *prevCwd = (char *)getcwd(nil, 0); - chdir([cwd fileSystemRepresentation]); + chdir([self.currentDirectoryPath fileSystemRepresentation]); //use Authorization Reference to execute script with privileges - err = _AuthExecuteWithPrivsFn(authorizationRef, [launchPath fileSystemRepresentation], kAuthorizationFlagDefaults, args, &outputFile); + OSStatus err = _AuthExecuteWithPrivsFn(authorization, toolPath, kAuthorizationFlagDefaults, args, &outputFile); // OK, now we're done executing, let's change back to old dir chdir(prevCwd); @@ -254,208 +242,92 @@ OSStatus const errAuthorizationFnNoLongerExists = -70001; free(args[i]); } - // free the auth ref - AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); - // we return err if execution failed if (err != errAuthorizationSuccess) { return err; } else { - isRunning = YES; + _isRunning = YES; } // get file handle for the command output - outputFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileno(outputFile) closeOnDealloc:YES]; - pid = fcntl(fileno(outputFile), F_GETOWN, 0); + _outputFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileno(outputFile) closeOnDealloc:YES]; + _processIdentifier = fcntl(fileno(outputFile), F_GETOWN, 0); // start monitoring task - checkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.10 target:self selector:@selector(_checkTaskStatus) userInfo:nil repeats:YES]; - + _checkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(checkTaskStatus) userInfo:nil repeats:YES]; + return err; } - (void)terminate { - // This doesn't work without a PID, and we can't get one. Stupid Security API - /* int ret = kill(pid, SIGKILL); - - if (ret != 0) - NSLog(@"Error %d", errno);*/ + // This doesn't work without a PID, and we can't get one. Stupid Security API. +// int ret = kill(pid, SIGKILL); +// +// if (ret != 0) { +// NSLog(@"Error %d", errno); +// } } // hang until task is done - (void)waitUntilExit { - waitpid([self processIdentifier], &terminationStatus, 0); - isRunning = NO; + if (!_isRunning) { + NSLog(@"Task %@ is not running", [super description]); + return; + } + + [_checkStatusTimer invalidate]; + + int status; + pid_t pid = 0; + while ((pid = waitpid(_processIdentifier, &status, WNOHANG)) == 0) { + // do nothing + } + _terminationStatus = WEXITSTATUS(status); + _isRunning = NO; } -#pragma mark - - -// check if privileged task is still running -- (void)_checkTaskStatus -{ - // see if task has terminated - int mypid = waitpid([self processIdentifier], &terminationStatus, WNOHANG); - if (mypid != 0) { - isRunning = NO; +// check if task has terminated +- (void)checkTaskStatus +{ + int status; + pid_t pid = waitpid(_processIdentifier, &status, WNOHANG); + if (pid != 0) { + _isRunning = NO; + _terminationStatus = WEXITSTATUS(status); + [_checkStatusTimer invalidate]; [[NSNotificationCenter defaultCenter] postNotificationName:STPrivilegedTaskDidTerminateNotification object:self]; - [checkStatusTimer invalidate]; + if (_terminationHandler) { + _terminationHandler(self); + } } } #pragma mark - ++ (BOOL)authorizationFunctionAvailable +{ + if (!_AuthExecuteWithPrivsFn) { + // This version of OS X has finally removed this function. Return with an error. + return NO; + } + return YES; +} + +#pragma mark - + +// Nice description for debugging - (NSString *)description { - NSArray *args = [self arguments]; - NSString *cmd = [[self launchPath] copy]; + NSString *commandDescription = [NSString stringWithString:self.launchPath]; - for (int i = 0; i < [args count]; i++) { - cmd = [cmd stringByAppendingFormat:@" %@", args[i]]; + for (NSString *arg in self.arguments) { + commandDescription = [commandDescription stringByAppendingFormat:@" '%@'", arg]; } + [commandDescription stringByAppendingFormat:@" (CWD:%@)", self.currentDirectoryPath]; - return [[super description] stringByAppendingFormat:@" %@", cmd]; + return [[super description] stringByAppendingFormat:@" %@", commandDescription]; } @end - -/* - * - * Add the Standard err Pipe and Pid support to AuthorizationExecuteWithPrivileges() - * method - * - * @Author: Miklós Fazekas - * Modified Aug 10 2010 by Sveinbjorn Thordarson - * - */ - - -/*static OSStatus AuthorizationExecuteWithPrivilegesStdErrAndPid ( - AuthorizationRef authorization, - const char *pathToTool, - AuthorizationFlags options, - char * const *arguments, - FILE **communicationsPipe, - FILE **errPipe, - pid_t* processid - ) -{ - // get the Apple-approved secure temp directory - NSString *tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent: TMP_STDERR_TEMPLATE]; - - // copy it into a C string - const char *tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation]; - char *stderrpath = (char *)malloc(strlen(tempFileTemplateCString) + 1); - strcpy(stderrpath, tempFileTemplateCString); - - printf("%s\n", stderrpath); - - // this is the command, it echoes pid and directs stderr output to pipe before running the tool w. args - const char *commandtemplate = "echo $$; \"$@\" 2>%s"; - - if (communicationsPipe == errPipe) - commandtemplate = "echo $$; \"$@\" 2>1"; - else if (errPipe == 0) - commandtemplate = "echo $$; \"$@\""; - - char command[1024]; - char **args; - OSStatus result; - int argcount = 0; - int i; - int stderrfd = 0; - FILE *commPipe = 0; - - // First, create temporary file for stderr - if (errPipe) - { - // create temp file - stderrfd = mkstemp(stderrpath); - - // close and remove it - close(stderrfd); - unlink(stderrpath); - - // create a pipe on the path of the temp file - if (mkfifo(stderrpath,S_IRWXU | S_IRWXG) != 0) - { - fprintf(stderr,"Error mkfifo:%d\n", errno); - return errAuthorizationInternal; - } - - if (stderrfd < 0) - return errAuthorizationInternal; - } - - // Create command to be executed - for (argcount = 0; arguments[argcount] != 0; ++argcount) {} - args = (char**)malloc (sizeof(char*)*(argcount + 5)); - args[0] = "-c"; - snprintf (command, sizeof (command), commandtemplate, stderrpath); - args[1] = command; - args[2] = ""; - args[3] = (char*)pathToTool; - for (i = 0; i < argcount; ++i) { - args[i+4] = arguments[i]; - } - args[argcount+4] = 0; - - // for debugging: log the executed command - printf ("Exec:\n%s", "/bin/sh"); for (i = 0; args[i] != 0; ++i) { printf (" \"%s\"", args[i]); } printf ("\n"); - - // Execute command - result = AuthorizationExecuteWithPrivileges(authorization, "/bin/sh", options, args, &commPipe ); - if (result != noErr) - { - unlink (stderrpath); - return result; - } - - // Read the first line of stdout => it's the pid - { - int stdoutfd = fileno (commPipe); - char pidnum[1024]; - pid_t pid = 0; - int i = 0; - char ch = 0; - - while ((read(stdoutfd, &ch, sizeof(ch)) == 1) && (ch != '\n') && (i < sizeof(pidnum))) - { - pidnum[i++] = ch; - } - pidnum[i] = 0; - - if (ch != '\n') - { - // we shouldn't get there - unlink (stderrpath); - return errAuthorizationInternal; - } - sscanf(pidnum, "%d", &pid); - if (processid) - { - *processid = pid; - } - NSLog(@"Have PID %d", pid); - } - - // - if (errPipe) { - stderrfd = open(stderrpath, O_RDONLY, 0); - // *errPipe = fdopen(stderrfd, "r"); - //Now it's safe to unlink the stderr file, as the opened handle will be still valid - unlink (stderrpath); - } else { - unlink(stderrpath); - } - - if (communicationsPipe) - *communicationsPipe = commPipe; - else - fclose (commPipe); - - NSLog(@"AuthExecNew function over"); - - return noErr; -}*/ diff --git a/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.markdown b/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.markdown index 02f02f9c..2221e61b 100644 --- a/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.markdown +++ b/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.markdown @@ -3,28 +3,35 @@ This application makes use of the following third party libraries: ## STPrivilegedTask - # BSD License - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above copyright - # notice, this list of conditions and the following disclaimer in the - # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other - # contributors may be used to endorse or promote products - # derived from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +BSD 3-Clause License + +Copyright (c) 2009, Sveinbjorn Thordarson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## Sparkle diff --git a/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.plist b/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.plist index 3a9beb49..417bdcfe 100644 --- a/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-AltServer/Pods-AltServer-acknowledgements.plist @@ -14,28 +14,35 @@ FooterText - # BSD License - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above copyright - # notice, this list of conditions and the following disclaimer in the - # documentation and/or other materials provided with the distribution. - # * Neither the name of Sveinbjorn Thordarson nor that of any other - # contributors may be used to endorse or promote products - # derived from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + BSD 3-Clause License + +Copyright (c) 2009, Sveinbjorn Thordarson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. License BSD diff --git a/Pods/Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist b/Pods/Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist index 3c175b60..1bd6a77a 100644 --- a/Pods/Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist +++ b/Pods/Target Support Files/STPrivilegedTask/STPrivilegedTask-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.1 + 1.0.7 CFBundleSignature ???? CFBundleVersion