Merge branch 'update_plugin' of https://github.com/rileytestut/AltStore into develop

This commit is contained in:
Riley Testut
2020-10-06 18:16:09 -07:00
5 changed files with 379 additions and 234 deletions

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
@@ -58,5 +58,9 @@
<string># For mail version 13.0 (3594.4.2) on OS X Version 10.15 (build 19A558d)</string>
<string>6EEA38FB-1A0B-469B-BB35-4C2E0EEA9053</string>
</array>
<key>Supported11.0PluginCompatibilityUUIDs</key>
<array>
<string>D985F0E4-3BBC-4B95-BBA1-12056AC4A531</string>
</array>
</dict>
</plist>

BIN
AltServer/AltPlugin.zip Normal file

Binary file not shown.

View File

@@ -12,32 +12,12 @@ import UserNotifications
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 cancelled
case unknown
case taskError(String)
case taskErrorCode(Int)
var errorDescription: String? {
switch self
{
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))
}
}
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
private let pluginManager = PluginManager()
private var statusItem: NSStatusItem?
private var connectedDevices = [ALTDevice]()
@@ -52,11 +32,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
private weak var authenticationAppleIDTextField: NSTextField?
private weak var authenticationPasswordTextField: NSSecureTextField?
private var isMailPluginInstalled: Bool {
let isMailPluginInstalled = FileManager.default.fileExists(atPath: pluginURL.path)
return isMailPluginInstalled
}
func applicationDidFinishLaunching(_ aNotification: Notification)
{
UserDefaults.standard.registerDefaults()
@@ -89,6 +64,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
UserDefaults.standard.didPresentInitialNotification = true
}
}
if self.pluginManager.isUpdateAvailable
{
self.installMailPlugin()
}
}
func applicationWillTerminate(_ aNotification: Notification)
@@ -191,27 +171,13 @@ private extension AppDelegate
}
}
if !self.isMailPluginInstalled
if !self.pluginManager.isMailPluginInstalled || self.pluginManager.isUpdateAvailable
{
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()
}
case .failure: break
case .success: install()
}
}
}
@@ -228,9 +194,44 @@ private extension AppDelegate
@objc func handleInstallMailPluginMenuItem(_ item: NSMenuItem)
{
if self.isMailPluginInstalled
if !self.pluginManager.isMailPluginInstalled || self.pluginManager.isUpdateAvailable
{
self.uninstallMailPlugin { (result) in
self.installMailPlugin()
}
else
{
self.uninstallMailPlugin()
}
}
private func installMailPlugin(completion: ((Result<Void, Error>) -> Void)? = nil)
{
self.pluginManager.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()
}
completion?(result)
}
}
}
private func uninstallMailPlugin()
{
self.pluginManager.uninstallMailPlugin { (result) in
DispatchQueue.main.async {
switch result
{
@@ -250,194 +251,10 @@ private extension AppDelegate
}
}
}
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()
}
}
}
}
}
func installMailPlugin(completionHandler: @escaping (Result<Void, Error>) -> Void)
{
do
{
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 { throw PluginError.cancelled }
self.downloadPlugin { (result) in
do
{
let fileURL = try result.get()
defer { try? FileManager.default.removeItem(at: fileURL) }
// Ensure plug-in directory exists.
let authorization = try self.runAndKeepAuthorization("mkdir", arguments: ["-p", pluginDirectoryURL.path])
// Unzip AltPlugin to plug-ins directory.
try self.runAndKeepAuthorization("unzip", arguments: ["-o", fileURL.path, "-d", pluginDirectoryURL.path], authorization: authorization)
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))
}
}
}
catch
{
completionHandler(.failure(PluginError.cancelled))
}
}
func downloadPlugin(completionHandler: @escaping (Result<URL, Error>) -> 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, Error>) -> 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)
}
@discardableResult
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()
print("Exit code:", task.terminationStatus)
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
{
func menuWillOpen(_ menu: NSMenu)
{
guard menu == self.appMenu else { return }
@@ -448,7 +265,11 @@ extension AppDelegate: NSMenuDelegate
self.launchAtLoginMenuItem.action = #selector(AppDelegate.toggleLaunchAtLogin(_:))
self.launchAtLoginMenuItem.state = LaunchAtLogin.isEnabled ? .on : .off
if self.isMailPluginInstalled
if self.pluginManager.isUpdateAvailable
{
self.installMailPluginMenuItem.title = NSLocalizedString("Update Mail Plug-in", comment: "")
}
else if self.pluginManager.isMailPluginInstalled
{
self.installMailPluginMenuItem.title = NSLocalizedString("Uninstall Mail Plug-in", comment: "")
}

View File

@@ -0,0 +1,310 @@
//
// PluginManager.swift
// AltServer
//
// Created by Riley Testut on 9/16/20.
// Copyright © 2020 Riley Testut. All rights reserved.
//
import Foundation
import AppKit
import CryptoKit
import STPrivilegedTask
private let pluginDirectoryURL = URL(fileURLWithPath: "/Library/Mail/Bundles", isDirectory: true)
private let pluginURL = pluginDirectoryURL.appendingPathComponent("AltPlugin.mailbundle")
enum PluginError: LocalizedError
{
case cancelled
case unknown
case notFound
case mismatchedHash(hash: String, expectedHash: String)
case taskError(String)
case taskErrorCode(Int)
var errorDescription: String? {
switch self
{
case .cancelled: return NSLocalizedString("Mail plug-in installation was cancelled.", comment: "")
case .unknown: return NSLocalizedString("Failed to install Mail plug-in.", comment: "")
case .notFound: return NSLocalizedString("The Mail plug-in does not exist at the requested URL.", comment: "")
case .mismatchedHash(let hash, let expectedHash): return String(format: NSLocalizedString("The hash of the downloaded Mail plug-in does not match the expected hash.\n\nHash:\n%@\n\nExpected Hash:\n%@", comment: ""), hash, expectedHash)
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))
}
}
}
struct PluginVersion
{
var url: URL
var sha256Hash: String
var version: String
static let v1_0 = PluginVersion(url: URL(string: "https://f000.backblazeb2.com/file/altstore/altserver/altplugin/1_0.zip")!,
sha256Hash: "070e9b7e1f74e7a6474d36253ab5a3623ff93892acc9e1043c3581f2ded12200",
version: "1.0")
static let v1_1 = PluginVersion(url: Bundle.main.url(forResource: "AltPlugin", withExtension: "zip")!,
sha256Hash: "cd1e8c85cbb1935d2874376566671f3c5823101d4933fc6ee63bab8b2a37f800",
version: "1.1")
}
class PluginManager
{
var isMailPluginInstalled: Bool {
let isMailPluginInstalled = FileManager.default.fileExists(atPath: pluginURL.path)
return isMailPluginInstalled
}
var isUpdateAvailable: Bool {
guard let bundle = Bundle(url: pluginURL) else { return false }
// Load Info.plist from disk because Bundle.infoDictionary is cached by system.
let infoDictionaryURL = bundle.bundleURL.appendingPathComponent("Contents/Info.plist")
guard let infoDictionary = NSDictionary(contentsOf: infoDictionaryURL) as? [String: Any],
let version = infoDictionary["CFBundleShortVersionString"] as? String
else { return false }
let isUpdateAvailable = (version != self.preferredVersion.version)
return isUpdateAvailable
}
private var preferredVersion: PluginVersion {
if #available(macOS 11, *)
{
return .v1_1
}
else
{
return .v1_0
}
}
}
extension PluginManager
{
func installMailPlugin(completionHandler: @escaping (Result<Void, Error>) -> Void)
{
do
{
let alert = NSAlert()
if self.isUpdateAvailable
{
alert.messageText = NSLocalizedString("Update Mail Plug-in", comment: "")
alert.informativeText = NSLocalizedString("An update is available for AltServer's Mail plug-in. Please update the plug-in now in order to keep using AltStore.", comment: "")
alert.addButton(withTitle: NSLocalizedString("Update Plug-in", comment: ""))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
}
else
{
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 { throw PluginError.cancelled }
self.downloadPlugin { (result) in
do
{
let fileURL = try result.get()
// Ensure plug-in directory exists.
let authorization = try self.runAndKeepAuthorization("mkdir", arguments: ["-p", pluginDirectoryURL.path])
// Create temporary directory.
let temporaryDirectoryURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
try FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: true, attributes: nil)
defer { try? FileManager.default.removeItem(at: temporaryDirectoryURL) }
// Unzip AltPlugin to temporary directory.
try self.runAndKeepAuthorization("unzip", arguments: ["-o", fileURL.path, "-d", temporaryDirectoryURL.path], authorization: authorization)
if FileManager.default.fileExists(atPath: pluginURL.path)
{
// Delete existing Mail plug-in.
try self.runAndKeepAuthorization("rm", arguments: ["-rf", pluginURL.path], authorization: authorization)
}
// Copy AltPlugin to Mail plug-ins directory.
// Must be separate step than unzip to prevent macOS from considering plug-in corrupted.
let unzippedPluginURL = temporaryDirectoryURL.appendingPathComponent(pluginURL.lastPathComponent)
try self.runAndKeepAuthorization("cp", arguments: ["-R", unzippedPluginURL.path, pluginDirectoryURL.path], authorization: authorization)
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))
}
}
}
catch
{
completionHandler(.failure(PluginError.cancelled))
}
}
func uninstallMailPlugin(completionHandler: @escaping (Result<Void, Error>) -> 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 PluginManager
{
func downloadPlugin(completion: @escaping (Result<URL, Error>) -> Void)
{
let pluginVersion = self.preferredVersion
func finish(_ result: Result<URL, Error>)
{
do
{
let fileURL = try result.get()
if #available(OSX 10.15, *)
{
let data = try Data(contentsOf: fileURL)
let sha256Hash = SHA256.hash(data: data)
let hashString = sha256Hash.compactMap { String(format: "%02x", $0) }.joined()
print("Comparing Mail plug-in hash (\(hashString)) against expected hash (\(pluginVersion.sha256Hash))...")
guard hashString == pluginVersion.sha256Hash else { throw PluginError.mismatchedHash(hash: hashString, expectedHash: pluginVersion.sha256Hash) }
}
completion(.success(fileURL))
}
catch
{
completion(.failure(error))
}
}
if pluginVersion.url.isFileURL
{
finish(.success(pluginVersion.url))
}
else
{
let downloadTask = URLSession.shared.downloadTask(with: pluginVersion.url) { (fileURL, response, error) in
if let response = response as? HTTPURLResponse
{
guard response.statusCode != 404 else { return finish(.failure(PluginError.notFound)) }
}
let result = Result(fileURL, error)
finish(result)
if let fileURL = fileURL
{
try? FileManager.default.removeItem(at: fileURL)
}
}
downloadTask.resume()
}
}
func run(_ program: String, arguments: [String], authorization: AuthorizationRef? = nil) throws
{
_ = try self._run(program, arguments: arguments, authorization: authorization, freeAuthorization: true)
}
@discardableResult
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()
print("Exit code:", task.terminationStatus)
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
}
}

View File

@@ -239,6 +239,7 @@
BFC57A652416C72400EB891E /* DeactivateAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC57A642416C72400EB891E /* DeactivateAppOperation.swift */; };
BFC57A6E2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */; };
BFC57A702416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */; };
BFC712BB2512B9CF00AB5EBE /* PluginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC712BA2512B9CF00AB5EBE /* PluginManager.swift */; };
BFC712C32512D5F100AB5EBE /* XPCConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC712C12512D5F100AB5EBE /* XPCConnection.swift */; };
BFC712C42512D5F100AB5EBE /* XPCConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC712C12512D5F100AB5EBE /* XPCConnection.swift */; };
BFC712C52512D5F100AB5EBE /* XPCConnectionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFC712C22512D5F100AB5EBE /* XPCConnectionHandler.swift */; };
@@ -294,6 +295,7 @@
BFE338DF22F0EADB002E24B9 /* FetchSourceOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE338DE22F0EADB002E24B9 /* FetchSourceOperation.swift */; };
BFE338E822F10E56002E24B9 /* LaunchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE338E722F10E56002E24B9 /* LaunchViewController.swift */; };
BFE48975238007CE003239E0 /* AnisetteDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE48974238007CE003239E0 /* AnisetteDataManager.swift */; };
BFE4FFB6251BF7BA0018CF9B /* AltPlugin.zip in Resources */ = {isa = PBXBuildFile; fileRef = BFE4FFB5251BF7BA0018CF9B /* AltPlugin.zip */; };
BFE60738231ADF49002B0E8E /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFE60737231ADF49002B0E8E /* Settings.storyboard */; };
BFE6073A231ADF82002B0E8E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE60739231ADF82002B0E8E /* SettingsViewController.swift */; };
BFE6073C231AE1E7002B0E8E /* SettingsHeaderFooterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BFE6073B231AE1E7002B0E8E /* SettingsHeaderFooterView.xib */; };
@@ -670,6 +672,7 @@
BFC57A642416C72400EB891E /* DeactivateAppOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeactivateAppOperation.swift; sourceTree = "<group>"; };
BFC57A6D2416FC5D00EB891E /* InstalledAppsCollectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledAppsCollectionHeaderView.swift; sourceTree = "<group>"; };
BFC57A6F2416FC7600EB891E /* InstalledAppsCollectionHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InstalledAppsCollectionHeaderView.xib; sourceTree = "<group>"; };
BFC712BA2512B9CF00AB5EBE /* PluginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginManager.swift; sourceTree = "<group>"; };
BFC712C12512D5F100AB5EBE /* XPCConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XPCConnection.swift; sourceTree = "<group>"; };
BFC712C22512D5F100AB5EBE /* XPCConnectionHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XPCConnectionHandler.swift; sourceTree = "<group>"; };
BFC84A4C2421A19100853474 /* SourcesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourcesViewController.swift; sourceTree = "<group>"; };
@@ -731,6 +734,7 @@
BFE338DE22F0EADB002E24B9 /* FetchSourceOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchSourceOperation.swift; sourceTree = "<group>"; };
BFE338E722F10E56002E24B9 /* LaunchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchViewController.swift; sourceTree = "<group>"; };
BFE48974238007CE003239E0 /* AnisetteDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnisetteDataManager.swift; sourceTree = "<group>"; };
BFE4FFB5251BF7BA0018CF9B /* AltPlugin.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = AltPlugin.zip; sourceTree = "<group>"; };
BFE60737231ADF49002B0E8E /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = "<group>"; };
BFE60739231ADF82002B0E8E /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
BFE6073B231AE1E7002B0E8E /* SettingsHeaderFooterView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsHeaderFooterView.xib; sourceTree = "<group>"; };
@@ -925,6 +929,7 @@
BF45868F229872EA00BD7491 /* AppDelegate.swift */,
BF458695229872EA00BD7491 /* Main.storyboard */,
BFE48974238007CE003239E0 /* AnisetteDataManager.swift */,
BFC712BA2512B9CF00AB5EBE /* PluginManager.swift */,
BF703195229F36FF006E110F /* Devices */,
BFD52BDC22A0A659000B7ED1 /* Connections */,
BF055B4A233B528B0086DEA9 /* Extensions */,
@@ -1256,6 +1261,7 @@
BF703194229F36F6006E110F /* Resources */ = {
isa = PBXGroup;
children = (
BFE4FFB5251BF7BA0018CF9B /* AltPlugin.zip */,
BF458693229872EA00BD7491 /* Assets.xcassets */,
);
name = Resources;
@@ -1934,6 +1940,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BFE4FFB6251BF7BA0018CF9B /* AltPlugin.zip in Resources */,
BF458694229872EA00BD7491 /* Assets.xcassets in Resources */,
BF458697229872EA00BD7491 /* Main.storyboard in Resources */,
);
@@ -2169,6 +2176,7 @@
BFECAC8724FD950B0077C41F /* Bundle+AltStore.swift in Sources */,
BF3F786422CAA41E008FBD20 /* ALTDeviceManager+Installation.swift in Sources */,
BF18BFFD2485A1E400DD5981 /* WiredConnectionHandler.swift in Sources */,
BFC712BB2512B9CF00AB5EBE /* PluginManager.swift in Sources */,
BFECAC8224FD950B0077C41F /* ServerProtocol.swift in Sources */,
BFECAC8124FD950B0077C41F /* ALTServerError+Conveniences.swift in Sources */,
BFECAC7F24FD950B0077C41F /* CodableServerError.swift in Sources */,
@@ -2818,6 +2826,7 @@
"/Users/Riley/Library/Developer/Xcode/DerivedData/AltStore-bhqnkrahfutztzeudtxhcxccgtlo/Build/Products/Debug",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltPlugin;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
@@ -2847,6 +2856,7 @@
"/Users/Riley/Library/Developer/Xcode/DerivedData/AltStore-bhqnkrahfutztzeudtxhcxccgtlo/Build/Products/Debug",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltPlugin;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;