From 0c171122b28781088f0ea942d4aa6eb5700c1a30 Mon Sep 17 00:00:00 2001 From: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat, 1 Apr 2023 16:02:12 -0700 Subject: [PATCH] refactor minimuxer to use swift-bridge (#321) also add team ID to the end of the bundle ID for Debug builds to mirror SideServer --- AltStore.xcodeproj/project.pbxproj | 62 +++++++--- AltStore/LaunchViewController.swift | 32 ++--- .../Operations/DeactivateAppOperation.swift | 9 +- AltStore/Operations/EnableJITOperation.swift | 16 +-- AltStore/Operations/InstallAppOperation.swift | 21 ++-- AltStore/Operations/OperationError.swift | 94 ++++++++------- AltStore/Operations/RefreshAppOperation.swift | 11 +- AltStore/Operations/RemoveAppOperation.swift | 10 +- AltStore/Operations/ResignAppOperation.swift | 1 + AltStore/Operations/SendAppOperation.swift | 23 ++-- Build.xcconfig | 9 +- Dependencies/fetch-prebuilt.sh | 26 +++- .../minimuxer.xcodeproj/project.pbxproj | 27 ++++- minimuxer/minimuxer.swift | 111 ------------------ 14 files changed, 186 insertions(+), 266 deletions(-) delete mode 100644 minimuxer/minimuxer.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index f1d2c724..8a12bc50 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -11,17 +11,18 @@ 19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF45872B2298D31600BD7491 /* libimobiledevice.a */; }; 19104DB52909C06D00C49C7B /* EmotionalDamage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19104DB42909C06D00C49C7B /* EmotionalDamage.swift */; }; 19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19104DB22909C06C00C49C7B /* libEmotionalDamage.a */; }; - 191E5FAE290A5D92001A3B7C /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FAD290A5D92001A3B7C /* minimuxer.swift */; }; 191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FAB290A5D92001A3B7C /* libminimuxer.a */; }; 191E5FDC290AFA5C001A3B7C /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 191E5FDB290AFA5C001A3B7C /* OpenSSL */; }; 191E607D290B2EA5001A3B7C /* jsmn.c in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FD0290A651D001A3B7C /* jsmn.c */; }; 191E607E290B2EA7001A3B7C /* jplist.c in Sources */ = {isa = PBXBuildFile; fileRef = 191E5FCF290A651D001A3B7C /* jplist.c */; }; - 191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 191E5FB5290A5E1F001A3B7C /* libminimuxer.a */; }; 1920B04F2924AC8300744F60 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1920B04E2924AC8300744F60 /* Settings.bundle */; }; 19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */; }; 4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; }; 4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; }; 99C4EF4D2979132100CB538D /* SemanticVersion in Frameworks */ = {isa = PBXBuildFile; productRef = 99C4EF4C2979132100CB538D /* SemanticVersion */; }; + 99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */; }; + 99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */; }; + 99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F87D1729D8E4C900B40039 /* minimuxer.swift */; }; B3146ED2284F581E00BBC3FD /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; }; B3146ED3284F581E00BBC3FD /* Roxas.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B3146ECD284F580500BBC3FD /* Roxas.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B343F894295F7F9B002B1159 /* libfragmentzip.a */; }; @@ -504,13 +505,14 @@ 19104DB22909C06C00C49C7B /* libEmotionalDamage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libEmotionalDamage.a; sourceTree = BUILT_PRODUCTS_DIR; }; 19104DB42909C06D00C49C7B /* EmotionalDamage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmotionalDamage.swift; sourceTree = ""; }; 191E5FAB290A5D92001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 191E5FAD290A5D92001A3B7C /* minimuxer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = minimuxer.swift; sourceTree = ""; }; - 191E5FB5290A5E1F001A3B7C /* libminimuxer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libminimuxer.a; path = "Dependencies/minimuxer/target/aarch64-apple-ios/debug/libminimuxer.a"; sourceTree = ""; }; 191E5FCF290A651D001A3B7C /* jplist.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jplist.c; path = Dependencies/libplist/src/jplist.c; sourceTree = SOURCE_ROOT; }; 191E5FD0290A651D001A3B7C /* jsmn.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jsmn.c; path = Dependencies/libplist/src/jsmn.c; sourceTree = SOURCE_ROOT; }; 191E5FD1290A651D001A3B7C /* jsmn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = jsmn.h; path = Dependencies/libplist/src/jsmn.h; sourceTree = SOURCE_ROOT; }; 1920B04E2924AC8300744F60 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 19B9B7442845E6DF0076EF69 /* SelectTeamViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectTeamViewController.swift; sourceTree = ""; }; + 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "minimuxer-helpers.swift"; path = "Dependencies/minimuxer/minimuxer-helpers.swift"; sourceTree = SOURCE_ROOT; }; + 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftBridgeCore.swift; path = Dependencies/minimuxer/SwiftBridgeCore.swift; sourceTree = SOURCE_ROOT; }; + 99F87D1729D8E4C900B40039 /* minimuxer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = minimuxer.swift; path = Dependencies/minimuxer/minimuxer.swift; sourceTree = SOURCE_ROOT; }; B3146EC6284F580500BBC3FD /* Roxas.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Roxas.xcodeproj; path = Dependencies/Roxas/Roxas.xcodeproj; sourceTree = ""; }; B33FFBA9295F8F78002259E6 /* preboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preboard.c; path = src/preboard.c; sourceTree = ""; }; B33FFBAB295F8F98002259E6 /* companion_proxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = companion_proxy.c; path = src/companion_proxy.c; sourceTree = ""; }; @@ -914,7 +916,6 @@ buildActionMask = 2147483647; files = ( B33FFBA8295F8E98002259E6 /* libfragmentzip.a in Frameworks */, - 191E6087290C7B50001A3B7C /* libminimuxer.a in Frameworks */, 191E5FB4290A5DA0001A3B7C /* libminimuxer.a in Frameworks */, 19104DBC2909C4E500C49C7B /* libEmotionalDamage.a in Frameworks */, 19104D952909BAEA00C49C7B /* libimobiledevice.a in Frameworks */, @@ -945,8 +946,9 @@ 191E5FAC290A5D92001A3B7C /* minimuxer */ = { isa = PBXGroup; children = ( + 9961EC2D29BE9F2E00AF2C6F /* minimuxer-helpers.swift */, + 99F87D1429D8E3F100B40039 /* Generated */, B343F847295F6321002B1159 /* minimuxer.xcodeproj */, - 191E5FAD290A5D92001A3B7C /* minimuxer.swift */, ); path = minimuxer; sourceTree = ""; @@ -968,6 +970,15 @@ path = "libimobiledevice-glue/src"; sourceTree = ""; }; + 99F87D1429D8E3F100B40039 /* Generated */ = { + isa = PBXGroup; + children = ( + 99F87D1629D8E4C900B40039 /* SwiftBridgeCore.swift */, + 99F87D1729D8E4C900B40039 /* minimuxer.swift */, + ); + name = Generated; + sourceTree = ""; + }; B3146EC7284F580500BBC3FD /* Products */ = { isa = PBXGroup; children = ( @@ -1567,7 +1578,6 @@ isa = PBXGroup; children = ( B343F86C295F759E002B1159 /* libresolv.tbd */, - 191E5FB5290A5E1F001A3B7C /* libminimuxer.a */, B39575F4284F29E20080B4FF /* Roxas.framework */, D533E8B62727841800A9B5DD /* libAppleArchive.tbd */, BF580497246A3D19008AE704 /* UIKit.framework */, @@ -1766,13 +1776,6 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 191E5FD4290A6EE0001A3B7C /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; BF4587272298D31600BD7491 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -1853,7 +1856,6 @@ isa = PBXNativeTarget; buildConfigurationList = 191E5FAF290A5D92001A3B7C /* Build configuration list for PBXNativeTarget "minimuxer" */; buildPhases = ( - 191E5FD4290A6EE0001A3B7C /* Headers */, 191E5FA7290A5D92001A3B7C /* Sources */, 191E5FA8290A5D92001A3B7C /* Frameworks */, ); @@ -1969,6 +1971,7 @@ isa = PBXNativeTarget; buildConfigurationList = BFD2477E2284B9A700981D42 /* Build configuration list for PBXNativeTarget "SideStore" */; buildPhases = ( + 99F87D0629D8B51400B40039 /* ShellScript */, BFD247662284B9A500981D42 /* Sources */, BFD247672284B9A500981D42 /* Frameworks */, BFD247682284B9A500981D42 /* Resources */, @@ -2220,6 +2223,27 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 99F87D0629D8B51400B40039 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + "./Dependencies/minimuxer/minimuxer-helpers.swift", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "bash ./Dependencies/fetch-prebuilt.sh minimuxer\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 19104DAE2909C06C00C49C7B /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -2233,7 +2257,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 191E5FAE290A5D92001A3B7C /* minimuxer.swift in Sources */, + 99F87D1929D8E4C900B40039 /* minimuxer.swift in Sources */, + 99F87D1829D8E4C900B40039 /* SwiftBridgeCore.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2484,6 +2509,7 @@ BFB39B5C252BC10E00D1BE50 /* Managed.swift in Sources */, BF770E5822BC3D0F002A40FE /* RefreshGroup.swift in Sources */, 19B9B7452845E6DF0076EF69 /* SelectTeamViewController.swift in Sources */, + 99F87D0529D8B4E200B40039 /* minimuxer-helpers.swift in Sources */, BF18B0F122E25DF9005C4CF5 /* ToastView.swift in Sources */, BF3D649F22E7B24C00E9056B /* CollapsingTextView.swift in Sources */, BF02419622F2199300129732 /* RefreshAttemptsViewController.swift in Sources */, @@ -2673,7 +2699,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OBJC_BRIDGING_HEADER = Dependencies/minimuxer/minimuxer.h; + SWIFT_OBJC_BRIDGING_HEADER = "Dependencies/minimuxer/minimuxer-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -2695,7 +2721,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_OBJC_BRIDGING_HEADER = Dependencies/minimuxer/minimuxer.h; + SWIFT_OBJC_BRIDGING_HEADER = "Dependencies/minimuxer/minimuxer-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/AltStore/LaunchViewController.swift b/AltStore/LaunchViewController.swift index 0aaf588e..cece54c2 100644 --- a/AltStore/LaunchViewController.swift +++ b/AltStore/LaunchViewController.swift @@ -14,6 +14,8 @@ import minimuxer import AltStoreCore import UniformTypeIdentifiers +let pairingFileName = "ALTPairingFile.mobiledevicepairing" + final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDelegate { private var didFinishLaunching = false @@ -125,14 +127,11 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg } // Save to a file for next launch - let filename = "ALTPairingFile.mobiledevicepairing" - let fm = FileManager.default - let documentsPath = fm.documentsDirectory.appendingPathComponent("/\(filename)") - try pairing_string?.write(to: documentsPath, atomically: true, encoding: String.Encoding.utf8) + let pairingFile = FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)") + try pairing_string?.write(to: pairingFile, atomically: true, encoding: String.Encoding.utf8) // Start minimuxer now that we have a file start_minimuxer_threads(pairing_string!) - } catch { displayError("Unable to read pairing file") } @@ -148,22 +147,15 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg } func start_minimuxer_threads(_ pairing_file: String) { - set_usbmuxd_socket() - #if false // Retries - var res = start_minimuxer(pairing_file: pairing_file) - var attempts = 10 - while (attempts != 0 && res != 0) { - print("start_minimuxer `res` != 0, retry #\(attempts)") - res = start_minimuxer(pairing_file: pairing_file) - attempts -= 1 + target_minimuxer_address() + let documentsDirectory = FileManager.default.documentsDirectory.absoluteString + do { + try start(pairing_file, documentsDirectory) + } catch { + try! FileManager.default.removeItem(at: FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)")) + displayError("minimuxer failed to start, please restart SideStore. \(minimuxerToOperationError(error).failureReason ?? "UNKNOWN ERROR!!!!!! REPORT TO GITHUB ISSUES!")") } - #else - let res = start_minimuxer(pairing_file: pairing_file) - #endif - if res != 0 { - displayError("minimuxer failed to start. Incorrect arguments were passed.") - } - auto_mount_dev_image() + start_auto_mounter(documentsDirectory) } } diff --git a/AltStore/Operations/DeactivateAppOperation.swift b/AltStore/Operations/DeactivateAppOperation.swift index e96d1fee..5742ec87 100644 --- a/AltStore/Operations/DeactivateAppOperation.swift +++ b/AltStore/Operations/DeactivateAppOperation.swift @@ -44,14 +44,9 @@ final class DeactivateAppOperation: ResultOperation for profile in allIdentifiers { do { - let res = try remove_provisioning_profile(id: profile) - if case Uhoh.Bad(let code) = res { - self.finish(.failure(minimuxer_to_operation(code: code))) - } - } catch Uhoh.Bad(let code) { - self.finish(.failure(minimuxer_to_operation(code: code))) + try remove_provisioning_profile(profile) } catch { - self.finish(.failure(ALTServerError(.unknownResponse))) + return self.finish(.failure(minimuxerToOperationError(error))) } } diff --git a/AltStore/Operations/EnableJITOperation.swift b/AltStore/Operations/EnableJITOperation.swift index f89296bf..1848109b 100644 --- a/AltStore/Operations/EnableJITOperation.swift +++ b/AltStore/Operations/EnableJITOperation.swift @@ -45,23 +45,13 @@ final class EnableJITOperation: ResultOperation guard let installedApp = self.context.installedApp else { return self.finish(.failure(OperationError.invalidParameters)) } installedApp.managedObjectContext?.perform { - let v = minimuxer_to_operation(code: 1) - do { - var x = try debug_app(app_id: installedApp.resignedBundleIdentifier) - switch x { - case .Good: - self.finish(.success(())) - case .Bad(let code): - self.finish(.failure(minimuxer_to_operation(code: code))) - } - } catch Uhoh.Bad(let code) { - self.finish(.failure(minimuxer_to_operation(code: code))) + try debug_app(installedApp.resignedBundleIdentifier) } catch { - self.finish(.failure(OperationError.unknown)) + return self.finish(.failure(minimuxerToOperationError(error))) } - + self.finish(.success(())) } } } diff --git a/AltStore/Operations/InstallAppOperation.swift b/AltStore/Operations/InstallAppOperation.swift index f10c1272..c9ef8d50 100644 --- a/AltStore/Operations/InstallAppOperation.swift +++ b/AltStore/Operations/InstallAppOperation.swift @@ -11,6 +11,7 @@ import Network import AltStoreCore import AltSign import Roxas +import minimuxer @objc(InstallAppOperation) final class InstallAppOperation: ResultOperation @@ -148,17 +149,14 @@ final class InstallAppOperation: ResultOperation }) } - let ns_bundle = NSString(string: installedApp.bundleIdentifier) - let ns_bundle_ptr = UnsafeMutablePointer(mutating: ns_bundle.utf8String) - - let res = minimuxer_install_ipa(ns_bundle_ptr) - if res == 0 { - installedApp.refreshedDate = Date() - self.finish(.success(installedApp)) - - } else { - self.finish(.failure(minimuxer_to_operation(code: res))) + do { + try install_ipa(installedApp.bundleIdentifier) + } catch { + return self.finish(.failure(minimuxerToOperationError(error))) } + + installedApp.refreshedDate = Date() + self.finish(.success(installedApp)) } } @@ -174,10 +172,11 @@ final class InstallAppOperation: ResultOperation do { try FileManager.default.removeItem(at: fileURL) + print("Removed refreshed IPA") } catch { - print("Failed to remove refreshed .ipa:", error) + print("Failed to remove refreshed .ipa: \(error)") } } diff --git a/AltStore/Operations/OperationError.swift b/AltStore/Operations/OperationError.swift index 331db175..4e7a86b2 100644 --- a/AltStore/Operations/OperationError.swift +++ b/AltStore/Operations/OperationError.swift @@ -8,6 +8,7 @@ import Foundation import AltSign +import minimuxer enum OperationError: LocalizedError { @@ -42,9 +43,11 @@ enum OperationError: LocalizedError case uninstall case lookupApps case detach + case attach case functionArguments - case profileInstall + case profileManage case noConnection + case invalidPairingFile var failureReason: String? { switch self { @@ -70,9 +73,11 @@ enum OperationError: LocalizedError case .uninstall: return NSLocalizedString("Unable to uninstall the app", comment: "") case .lookupApps: return NSLocalizedString("Unable to fetch apps from the device", comment: "") case .detach: return NSLocalizedString("Unable to detach from the app's process", comment: "") + case .attach: return NSLocalizedString("Unable to attach to the app's process", comment: "") case .functionArguments: return NSLocalizedString("A function was passed invalid arguments", comment: "") - case .profileInstall: return NSLocalizedString("Unable to manage profiles on the device", comment: "") + case .profileManage: return NSLocalizedString("Unable to manage profiles on the device", comment: "") case .noConnection: return NSLocalizedString("Unable to connect to the device, make sure Wireguard is enabled and you're connected to WiFi", comment: "") + case .invalidPairingFile: return NSLocalizedString("Invalid pairing file. Your pairing file either didn't have a UDID, or it wasn't a valid plist. Please use jitterbugpair to generate it", comment: "") } } @@ -118,49 +123,50 @@ enum OperationError: LocalizedError } } -func minimuxer_to_operation(code: Int32) -> OperationError { - switch code { - case 1: +/// crashes if error is not a MinimuxerError +func minimuxerToOperationError(_ error: Error) -> OperationError { + switch error as! MinimuxerError { + case .NoDevice: return OperationError.noDevice - case 2: - return OperationError.createService(name: "debug") - case 3: - return OperationError.createService(name: "instproxy") - case 4: - return OperationError.getFromDevice(name: "installed apps") - case 5: - return OperationError.getFromDevice(name: "path to the app") - case 6: - return OperationError.getFromDevice(name: "bundle path") - case 7: - return OperationError.setArgument(name: "max packet") - case 8: - return OperationError.setArgument(name: "working directory") - case 9: - return OperationError.setArgument(name: "argv") - case 10: - return OperationError.getFromDevice(name: "launch success") - case 11: - return OperationError.detach - case 12: - return OperationError.functionArguments - case 13: - return OperationError.createService(name: "AFC") - case 14: - return OperationError.afc - case 15: - return OperationError.install - case 16: - return OperationError.uninstall - case 17: - return OperationError.createService(name: "misagent") - case 18: - return OperationError.profileInstall - case 19: - return OperationError.profileInstall - case 20: + case .NoConnection: return OperationError.noConnection - default: - return OperationError.unknown + case .PairingFile: + return OperationError.invalidPairingFile + case .CreateDebug: + return OperationError.createService(name: "debug") + case .CreateInstproxy: + return OperationError.createService(name: "instproxy") + case .LookupApps: + return OperationError.getFromDevice(name: "installed apps") + case .FindApp: + return OperationError.getFromDevice(name: "path to the app") + case .BundlePath: + return OperationError.getFromDevice(name: "bundle path") + case .MaxPacket: + return OperationError.setArgument(name: "max packet") + case .WorkingDirectory: + return OperationError.setArgument(name: "working directory") + case .Argv: + return OperationError.setArgument(name: "argv") + case .LaunchSuccess: + return OperationError.getFromDevice(name: "launch success") + case .Detach: + return OperationError.detach + case .Attach: + return OperationError.attach + case .CreateAfc: + return OperationError.createService(name: "AFC") + case .RwAfc: + return OperationError.afc + case .InstallApp: + return OperationError.install + case .UninstallApp: + return OperationError.uninstall + case .CreateMisagent: + return OperationError.createService(name: "misagent") + case .ProfileInstall: + return OperationError.profileManage + case .ProfileRemove: + return OperationError.profileManage } } diff --git a/AltStore/Operations/RefreshAppOperation.swift b/AltStore/Operations/RefreshAppOperation.swift index 084e281c..7747d237 100644 --- a/AltStore/Operations/RefreshAppOperation.swift +++ b/AltStore/Operations/RefreshAppOperation.swift @@ -49,15 +49,12 @@ final class RefreshAppOperation: ResultOperation for p in profiles { do { - let x = try install_provisioning_profile(plist: p.value.data) - if case .Bad(let code) = x { - self.finish(.failure(minimuxer_to_operation(code: code))) - } - } catch Uhoh.Bad(let code) { - self.finish(.failure(minimuxer_to_operation(code: code))) + let bytes = p.value.data.toRustByteSlice() + try install_provisioning_profile(bytes.forRust()) } catch { - self.finish(.failure(OperationError.unknown)) + return self.finish(.failure(minimuxerToOperationError(error))) } + self.progress.completedUnitCount += 1 let predicate = NSPredicate(format: "%K == %@", #keyPath(InstalledApp.bundleIdentifier), app.bundleIdentifier) diff --git a/AltStore/Operations/RemoveAppOperation.swift b/AltStore/Operations/RemoveAppOperation.swift index 6ec3cba4..042828ec 100644 --- a/AltStore/Operations/RemoveAppOperation.swift +++ b/AltStore/Operations/RemoveAppOperation.swift @@ -39,15 +39,11 @@ final class RemoveAppOperation: ResultOperation let resignedBundleIdentifier = installedApp.resignedBundleIdentifier do { - let res = try remove_app(app_id: resignedBundleIdentifier) - if case Uhoh.Bad(let code) = res { - self.finish(.failure(minimuxer_to_operation(code: code))) - } - } catch Uhoh.Bad(let code) { - self.finish(.failure(minimuxer_to_operation(code: code))) + try remove_app(resignedBundleIdentifier) } catch { - self.finish(.failure(ALTServerError(.appDeletionFailed))) + return self.finish(.failure(minimuxerToOperationError(error))) } + DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in self.progress.completedUnitCount += 1 diff --git a/AltStore/Operations/ResignAppOperation.swift b/AltStore/Operations/ResignAppOperation.swift index 8be28221..a6098e00 100644 --- a/AltStore/Operations/ResignAppOperation.swift +++ b/AltStore/Operations/ResignAppOperation.swift @@ -61,6 +61,7 @@ final class ResignAppOperation: ResultOperation { let destinationURL = InstalledApp.refreshedIPAURL(for: app) try FileManager.default.copyItem(at: resignedURL, to: destinationURL, shouldReplace: true) + print("Successfully resigned app to \(destinationURL.absoluteString)") // Use appBundleURL since we need an app bundle, not .ipa. guard let resignedApplication = ALTApplication(fileURL: appBundleURL) else { throw OperationError.invalidApp } diff --git a/AltStore/Operations/SendAppOperation.swift b/AltStore/Operations/SendAppOperation.swift index fb239ba1..dd366968 100644 --- a/AltStore/Operations/SendAppOperation.swift +++ b/AltStore/Operations/SendAppOperation.swift @@ -9,6 +9,7 @@ import Foundation import Network import AltStoreCore +import minimuxer @objc(SendAppOperation) final class SendAppOperation: ResultOperation<()> @@ -44,24 +45,18 @@ final class SendAppOperation: ResultOperation<()> print("AFC App `fileURL`: \(fileURL.absoluteString)") - let ns_bundle = NSString(string: app.bundleIdentifier) - let ns_bundle_ptr = UnsafeMutablePointer(mutating: ns_bundle.utf8String) - if let data = NSData(contentsOf: fileURL) { - let pls = UnsafeMutablePointer.allocate(capacity: data.length) - for (index, data) in data.enumerated() { - pls[index] = data - } - let res = minimuxer_yeet_app_afc(ns_bundle_ptr, pls, UInt(data.length)) - if res == 0 { - print("minimuxer_yeet_app_afc `res` == \(res)") - self.progress.completedUnitCount += 1 - self.finish(.success(())) - } else { - self.finish(.failure(minimuxer_to_operation(code: res))) + do { + let bytes = Data(data).toRustByteSlice() + try yeet_app_afc(app.bundleIdentifier, bytes.forRust()) + } catch { + return self.finish(.failure(minimuxerToOperationError(error))) } + self.progress.completedUnitCount += 1 + self.finish(.success(())) } else { + print("IPA doesn't exist????") self.finish(.failure(ALTServerError(.underlyingError))) } } diff --git a/Build.xcconfig b/Build.xcconfig index 3c049de8..b0686dea 100644 --- a/Build.xcconfig +++ b/Build.xcconfig @@ -14,11 +14,14 @@ ORG_IDENTIFIER = com.SideStore ORG_PREFIX = $(ORG_IDENTIFIER) PRODUCT_NAME = SideStore -EXTENSION_PREFIX = $(ORG_PREFIX).SideStore //PRODUCT_NAME[configuration=Debug] = Prov Debug PRODUCT_BUNDLE_IDENTIFIER = $(ORG_PREFIX).SideStore -//PRODUCT_BUNDLE_IDENTIFIER[configuration=Debug] = $(ORG_PREFIX).$(PROJECT_NAME:lower)-debug +// add team ID to bundle ID for debug builds since these will most likely be installed via Xcode +// SideStore will expect the team ID to be at the end of the bundle ID, but this doesn't happen when we install via Xcode +// we don't want to do this for release since those builds will most likely be installed via SideServer, which adds the team ID +PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = $(ORG_PREFIX).SideStore.$(DEVELOPMENT_TEAM) -APP_GROUP_IDENTIFIER = $(ORG_PREFIX).SideStore +EXTENSION_PREFIX = $(PRODUCT_BUNDLE_IDENTIFIER) +APP_GROUP_IDENTIFIER = $(PRODUCT_BUNDLE_IDENTIFIER) ICLOUD_CONTAINER_IDENTIFIER = iCloud.$(ORG_PREFIX).$(PROJECT_NAME) diff --git a/Dependencies/fetch-prebuilt.sh b/Dependencies/fetch-prebuilt.sh index 0acbfae3..35760b95 100644 --- a/Dependencies/fetch-prebuilt.sh +++ b/Dependencies/fetch-prebuilt.sh @@ -16,8 +16,8 @@ check_for_update() { LAST_FETCH=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $1'` LAST_COMMIT=`cat .last-prebuilt-fetch-$1 | perl -n -e '/([0-9]*),([^ ]*)$/ && print $2'` - # fetch if last fetch was over 6 hours ago - if [[ $LAST_FETCH -lt $(expr $(date +%s) - 21600) ]] || [[ "$2" == "force" ]]; then + # fetch if last fetch was over 1 hour ago + if [[ $LAST_FETCH -lt $(expr $(date +%s) - 3600) ]] || [[ "$2" == "force" ]]; then echo "Checking $1 for update" echo LATEST_COMMIT=`curl https://api.github.com/repos/SideStore/$1/releases/latest | perl -n -e '/Commit: https:\\/\\/github\\.com\\/[^\\/]*\\/[^\\/]*\\/commit\\/([^"]*)/ && print $1'` @@ -27,16 +27,30 @@ check_for_update() { if [[ "$LAST_COMMIT" != "$LATEST_COMMIT" ]]; then echo "Found update, downloading binaries" echo - wget -O "$1/lib$1.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1.a" wget -O "$1/lib$1-sim.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-sim.a" - wget -O "$1/$1.h" "https://github.com/SideStore/$1/releases/latest/download/$1.h" - echo + if [[ "$1" != "minimuxer" ]]; then + wget -O "$1/lib$1.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1.a" + wget -O "$1/$1.h" "https://github.com/SideStore/$1/releases/latest/download/$1.h" + echo + else + wget -O "$1/lib$1-ios.a" "https://github.com/SideStore/$1/releases/latest/download/lib$1-ios.a" + wget -O "$1/generated.zip" "https://github.com/SideStore/$1/releases/latest/download/generated.zip" + echo + echo "Unzipping generated.zip" + cd "$1" + unzip ./generated.zip + mv -v generated/* . + rm generated.zip + rmdir generated/ + cd .. + echo "Done" + fi else echo "Up-to-date" fi echo "$(date +%s),$LATEST_COMMIT" > ".last-prebuilt-fetch-$1" else - echo "It hasn't been 6 hours and force was not specified, skipping update check for $1" + echo "It hasn't been 1 hour and force was not specified, skipping update check for $1" fi } diff --git a/Dependencies/minimuxer.xcodeproj/project.pbxproj b/Dependencies/minimuxer.xcodeproj/project.pbxproj index 062d1729..0eecb844 100644 --- a/Dependencies/minimuxer.xcodeproj/project.pbxproj +++ b/Dependencies/minimuxer.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 9961EC2829BE9C2000AF2C6F /* SwiftBridgeCore.h in Sources */ = {isa = PBXBuildFile; fileRef = 9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */; }; 9987603329A454B500818586 /* minimuxer.h in Sources */ = {isa = PBXBuildFile; fileRef = 9987603229A454B500818586 /* minimuxer.h */; }; /* End PBXBuildFile section */ @@ -28,12 +29,22 @@ /* End PBXBuildRule section */ /* Begin PBXFileReference section */ + 9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SwiftBridgeCore.h; path = minimuxer/SwiftBridgeCore.h; sourceTree = ""; }; 9987603229A454B500818586 /* minimuxer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = minimuxer.h; path = minimuxer/minimuxer.h; sourceTree = ""; }; ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; CA609C732349C7AAD9FA67C4 /* libminimuxer_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libminimuxer_static.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ + 99F87D1529D8E41100B40039 /* Generated */ = { + isa = PBXGroup; + children = ( + 9961EC2729BE9C1200AF2C6F /* SwiftBridgeCore.h */, + 9987603229A454B500818586 /* minimuxer.h */, + ); + name = Generated; + sourceTree = ""; + }; ADDEDBA66A6E2 /* Required for static linking */ = { isa = PBXGroup; children = ( @@ -61,7 +72,7 @@ CA6012A875F9D65BC3C892A8 = { isa = PBXGroup; children = ( - 9987603229A454B500818586 /* minimuxer.h */, + 99F87D1529D8E41100B40039 /* Generated */, CA6012A875F922869D176AE5 /* Products */, CA6012A875F998AF0B5890DB /* Frameworks */, ); @@ -74,7 +85,7 @@ isa = PBXNativeTarget; buildConfigurationList = CA600589A243A560B9642892 /* Build configuration list for PBXNativeTarget "minimuxer-staticlib" */; buildPhases = ( - 9987603629A4611D00818586 /* ShellScript */, + 9987603629A4611D00818586 /* Run Script */, CA600F638141A560B9642892 /* Sources */, CA6012A875F9AF6EBB7F357C /* Universal Binary lipo */, ); @@ -121,7 +132,7 @@ /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - 9987603629A4611D00818586 /* ShellScript */ = { + 9987603629A4611D00818586 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -130,10 +141,15 @@ ); inputPaths = ( ); + name = "Run Script"; outputFileListPaths = ( ); outputPaths = ( ./minimuxer/minimuxer.h, + ./minimuxer/SwiftBridgeCore.h, + ./minimuxer/minimuxer.swift, + ./minimuxer/SwiftBridgeCore.swift, + "./minimuxer/minimuxer-Bridging-Header.h", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -166,6 +182,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9961EC2829BE9C2000AF2C6F /* SwiftBridgeCore.h in Sources */, 9987603329A454B500818586 /* minimuxer.h in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -182,7 +199,7 @@ INSTALL_MODE_FLAG = ""; INSTALL_OWNER = ""; LIB_FILE_NAME = ""; - "LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer; + "LIB_FILE_NAME[sdk=iphoneos*]" = "libminimuxer-ios"; "LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim"; PRODUCT_NAME = minimuxer_static; SKIP_INSTALL = YES; @@ -199,7 +216,7 @@ INSTALL_MODE_FLAG = ""; INSTALL_OWNER = ""; LIB_FILE_NAME = ""; - "LIB_FILE_NAME[sdk=iphoneos*]" = libminimuxer; + "LIB_FILE_NAME[sdk=iphoneos*]" = "libminimuxer-ios"; "LIB_FILE_NAME[sdk=iphonesimulator*]" = "libminimuxer-sim"; PRODUCT_NAME = minimuxer_static; SKIP_INSTALL = YES; diff --git a/minimuxer/minimuxer.swift b/minimuxer/minimuxer.swift deleted file mode 100644 index fb024f63..00000000 --- a/minimuxer/minimuxer.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// minimuxer.swift -// minimuxer -// -// Created by Jackson Coxson on 10/27/22. -// - -import Foundation - -public enum Uhoh: Error { - case Good - case Bad(code: Int32) -} - -public func start_minimuxer(pairing_file: String) -> Int32 { - let pf = NSString(string: pairing_file) - let pf_pointer = UnsafeMutablePointer(mutating: pf.utf8String) - let u = NSString(string: getDocumentsDirectory().absoluteString) - let u_ptr = UnsafeMutablePointer(mutating: u.utf8String) - return minimuxer_c_start(pf_pointer, u_ptr) -} - -public func set_usbmuxd_socket() { - target_minimuxer_address() -} - -public func debug_app(app_id: String) throws -> Uhoh { - let ai = NSString(string: app_id) - let ai_pointer = UnsafeMutablePointer(mutating: ai.utf8String) - #if false // Retries - var res = minimuxer_debug_app(ai_pointer) - var attempts = 10 - while (attempts != 0 && res != 0) { - print("(JIT) ATTEMPTS: \(attempts)") - res = minimuxer_debug_app(ai_pointer) - attempts -= 1 - } - #else - let res = minimuxer_debug_app(ai_pointer) - #endif - if res != 0 { - throw Uhoh.Bad(code: res) - } - return Uhoh.Good -} - -public func install_provisioning_profile(plist: Data) throws -> Uhoh { - let pls = String(decoding: plist, as: UTF8.self) - print(pls) - print(plist) - #if false // Retries - var res = minimuxer_install_provisioning_profile(x, UInt32(plist.count)) - var attempts = 10 - while (attempts != 0 && res != 0) { - print("(INSTALL) ATTEMPTS: \(attempts)") - res = minimuxer_install_provisioning_profile(x, UInt32(plist.count)) - attempts -= 1 - } - #else - let x = plist.withUnsafeBytes { buf in UnsafeMutableRawPointer(mutating: buf) } - #endif - let res = minimuxer_install_provisioning_profile(x, UInt32(plist.count)) - if res != 0 { - throw Uhoh.Bad(code: res) - } - return Uhoh.Good -} - -public func remove_provisioning_profile(id: String) throws -> Uhoh { - let id_ns = NSString(string: id) - let id_pointer = UnsafeMutablePointer(mutating: id_ns.utf8String) - #if false // Retries - var res = minimuxer_remove_provisioning_profile(id_pointer) - var attempts = 10 - while (attempts != 0 && res != 0) { - print("(REMOVE PROFILE) ATTEMPTS: \(attempts)") - res = minimuxer_remove_provisioning_profile(id_pointer) - attempts -= 1 - } - #else - let res = minimuxer_remove_provisioning_profile(id_pointer) - #endif - if res != 0 { - throw Uhoh.Bad(code: res) - } - return Uhoh.Good -} - -public func remove_app(app_id: String) throws -> Uhoh { - let ai = NSString(string: app_id) - let ai_pointer = UnsafeMutablePointer(mutating: ai.utf8String) - let res = minimuxer_remove_app(ai_pointer) - if res != 0 { - throw Uhoh.Bad(code: res) - } - return Uhoh.Good -} - -public func auto_mount_dev_image() { - let u = NSString(string: getDocumentsDirectory().absoluteString) - let u_ptr = UnsafeMutablePointer(mutating: u.utf8String) - minimuxer_auto_mount(u_ptr) -} - -func getDocumentsDirectory() -> URL { - // find all possible documents directories for this user - let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) - - // just send back the first one, which ought to be the only one - return paths[0] -}