diff --git a/AltStore/Operations/Errors/OperationError.swift b/AltStore/Operations/Errors/OperationError.swift index 71755219..e5d8e561 100644 --- a/AltStore/Operations/Errors/OperationError.swift +++ b/AltStore/Operations/Errors/OperationError.swift @@ -300,99 +300,3 @@ struct OperationError: ALTLocalizedError { } } } - -extension MinimuxerError: LocalizedError { - public var failureReason: String? { - switch self { - case .NoDevice: - return NSLocalizedString("Cannot fetch the device from the muxer", comment: "") - case .NoConnection: - return NSLocalizedString("Unable to connect to the device, make sure LocalDevVPN is enabled and you're connected to Wi-Fi. This could mean an invalid pairing.", comment: "") - case .PairingFile: - return NSLocalizedString("Invalid pairing file. Your pairing file either didn't have a UDID, or it wasn't a valid plist. Please use iloader to replace it.", comment: "") - - case .CreateDebug: - return self.createService(name: "debug") - case .LookupApps: - return self.getFromDevice(name: "installed apps") - case .FindApp: - return self.getFromDevice(name: "path to the app") - case .BundlePath: - return self.getFromDevice(name: "bundle path") - case .MaxPacket: - return self.setArgument(name: "max packet") - case .WorkingDirectory: - return self.setArgument(name: "working directory") - case .Argv: - return self.setArgument(name: "argv") - case .LaunchSuccess: - return self.getFromDevice(name: "launch success") - 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 .CreateInstproxy: - return self.createService(name: "instproxy") - case .CreateAfc: - return self.createService(name: "AFC") - case .RwAfc: - return NSLocalizedString("AFC was unable to manage files on the device. Ensure Wi-Fi and LocalDevVPN are connected. If they both are, replace your pairing using iloader.", comment: "") - case .InstallApp(let message): - return NSLocalizedString("Unable to install the app: \(message.toString())", comment: "") - case .UninstallApp: - return NSLocalizedString("Unable to uninstall the app", comment: "") - - case .CreateMisagent: - return self.createService(name: "misagent") - case .ProfileInstall: - return NSLocalizedString("Unable to manage profiles on the device", comment: "") - case .ProfileRemove: - return NSLocalizedString("Unable to manage profiles on the device", comment: "") - case .CreateLockdown: - return NSLocalizedString("Unable to connect to lockdown", comment: "") - case .CreateCoreDevice: - return NSLocalizedString("Unable to connect to core device proxy", comment: "") - case .CreateSoftwareTunnel: - return NSLocalizedString("Unable to create software tunnel", comment: "") - case .CreateRemoteServer: - return NSLocalizedString("Unable to connect to remote server", comment: "") - case .CreateProcessControl: - return NSLocalizedString("Unable to connect to process control", comment: "") - case .GetLockdownValue: - return NSLocalizedString("Unable to get value from lockdown", comment: "") - case .Connect: - return NSLocalizedString("Unable to connect to TCP port", comment: "") - case .Close: - return NSLocalizedString("Unable to close TCP port", comment: "") - case .XpcHandshake: - return NSLocalizedString("Unable to get services from XPC", comment: "") - case .NoService: - return NSLocalizedString("Device did not contain service", comment: "") - case .InvalidProductVersion: - return NSLocalizedString("Service version was in an unexpected format", comment: "") - case .CreateFolder: - return NSLocalizedString("Unable to create DDI folder", comment: "") - case .DownloadImage: - return NSLocalizedString("Unable to download DDI", comment: "") - case .ImageLookup: - return NSLocalizedString("Unable to lookup DDI images", comment: "") - case .ImageRead: - return NSLocalizedString("Unable to read images to memory", comment: "") - case .Mount: - return NSLocalizedString("Mount failed", comment: "") - } - } - - fileprivate func createService(name: String) -> String { - return String(format: NSLocalizedString("Cannot start a %@ server on the device.", comment: ""), name) - } - - fileprivate func getFromDevice(name: String) -> String { - return String(format: NSLocalizedString("Cannot fetch %@ from the device.", comment: ""), name) - } - - fileprivate func setArgument(name: String) -> String { - return String(format: NSLocalizedString("Cannot set %@ on the device.", comment: ""), name) - } -} diff --git a/AltStore/Operations/InstallAppOperation.swift b/AltStore/Operations/InstallAppOperation.swift index 8f153461..547eccec 100644 --- a/AltStore/Operations/InstallAppOperation.swift +++ b/AltStore/Operations/InstallAppOperation.swift @@ -225,7 +225,7 @@ final class InstallAppOperation: ResultOperation } do { - try install_ipa(installedApp.bundleIdentifier) + try installIPA(installedApp.bundleIdentifier) installing = false installedApp.refreshedDate = Date() self.finish(.success(installedApp)) diff --git a/AltStore/Operations/RefreshAppOperation.swift b/AltStore/Operations/RefreshAppOperation.swift index 29483034..edffb911 100644 --- a/AltStore/Operations/RefreshAppOperation.swift +++ b/AltStore/Operations/RefreshAppOperation.swift @@ -46,8 +46,8 @@ final class RefreshAppOperation: ResultOperation for p in profiles { do { - let bytes = p.value.data.toRustByteSlice() - try install_provisioning_profile(bytes.forRust()) + let bytes = + try installProvisioningProfiles(p.value.data) } catch { self.finish(.failure(MinimuxerError.ProfileInstall)) } diff --git a/AltStore/Operations/RemoveAppOperation.swift b/AltStore/Operations/RemoveAppOperation.swift index 2a28f4c8..5afb076c 100644 --- a/AltStore/Operations/RemoveAppOperation.swift +++ b/AltStore/Operations/RemoveAppOperation.swift @@ -41,7 +41,7 @@ final class RemoveAppOperation: ResultOperation let resignedBundleIdentifier = installedApp.resignedBundleIdentifier do { - try remove_app(resignedBundleIdentifier) + try removeApp(resignedBundleIdentifier) } catch { return self.finish(.failure(error)) } diff --git a/AltStore/Operations/ResignAppOperation.swift b/AltStore/Operations/ResignAppOperation.swift index 13776ac1..283a83c5 100644 --- a/AltStore/Operations/ResignAppOperation.swift +++ b/AltStore/Operations/ResignAppOperation.swift @@ -222,7 +222,7 @@ private extension ResignAppOperation // The embedded certificate + certificate identifier are already in app bundle, no need to update them. } } - else if infoDictionary.keys.contains(Bundle.Info.deviceID), let udid = fetch_udid()?.toString() as? String + else if infoDictionary.keys.contains(Bundle.Info.deviceID), let udid = fetchUDID() { // There is an ALTDeviceID entry, so assume the app is using AltKit and replace it with the device's UDID. additionalValues[Bundle.Info.deviceID] = udid diff --git a/AltStore/Operations/SendAppOperation.swift b/AltStore/Operations/SendAppOperation.swift index 5fe1d016..d852630a 100644 --- a/AltStore/Operations/SendAppOperation.swift +++ b/AltStore/Operations/SendAppOperation.swift @@ -46,8 +46,8 @@ final class SendAppOperation: ResultOperation<()> if let data = NSData(contentsOf: fileURL) { do { - let bytes = Data(data).toRustByteSlice() - try yeet_app_afc(app.bundleIdentifier, bytes.forRust()) + let bytes = Data(data) + try yeetAppAFC(app.bundleIdentifier, bytes) self.progress.completedUnitCount += 1 self.finish(.success(())) } catch { diff --git a/SideStore/MinimuxerWrapper.swift b/SideStore/MinimuxerWrapper.swift index 8f1d5c84..8e98017f 100644 --- a/SideStore/MinimuxerWrapper.swift +++ b/SideStore/MinimuxerWrapper.swift @@ -14,6 +14,7 @@ var isMinimuxerReady: Bool { return true #else return minimuxer.ready() + return true #endif } @@ -32,3 +33,146 @@ func targetMinimuxerAddress() { minimuxer.target_minimuxer_address() #endif } + +func installProvisioningProfiles(_ profileData: Data) throws { + #if targetEnvironment(simulator) + print("installProvisioningProfiles(\(profileData)) is no-op on simulator") + #else + minimuxer.install_provisioning_profile(profileData.toRustByteSlice().forRust()) + #endif +} + + +func removeApp(_ bundleId: String) throws { + #if targetEnvironment(simulator) + print("removeApp(\(bundleId)) is no-op on simulator") + #else + minimuxer.remove_app(bundleId) + #endif +} + + +func yeetAppAFC(_ bundleId: String, _ rawBytes: Data) throws { + #if targetEnvironment(simulator) + print("yeetAppAFC(\(bundleId), \(rawBytes)) is no-op on simulator") + #else + minimuxer.yeetAppAFC(bundleId, rawBytes.toRustByteSlice().forRust()) + #endif +} + + +func installIPA(_ bundleId: String) throws { + #if targetEnvironment(simulator) + print("installIPA(\(bundleId), \(rawBytes)) is no-op on simulator") + #else + minimuxer.installIPA(bundleId) + #endif +} + + +func fetchUDID() -> String? { + #if targetEnvironment(simulator) + print("fetchUDID() is no-op on simulator") + return "XXXXX-XXXX-XXXXX-XXXX" + #else + minimuxer.fetchUDID()?.toString() + #endif +} + + + +extension MinimuxerError: LocalizedError { + public var failureReason: String? { + switch self { + case .NoDevice: + return NSLocalizedString("Cannot fetch the device from the muxer", comment: "") + case .NoConnection: + return NSLocalizedString("Unable to connect to the device, make sure LocalDevVPN is enabled and you're connected to Wi-Fi. This could mean an invalid pairing.", comment: "") + case .PairingFile: + return NSLocalizedString("Invalid pairing file. Your pairing file either didn't have a UDID, or it wasn't a valid plist. Please use iloader to replace it.", comment: "") + + case .CreateDebug: + return self.createService(name: "debug") + case .LookupApps: + return self.getFromDevice(name: "installed apps") + case .FindApp: + return self.getFromDevice(name: "path to the app") + case .BundlePath: + return self.getFromDevice(name: "bundle path") + case .MaxPacket: + return self.setArgument(name: "max packet") + case .WorkingDirectory: + return self.setArgument(name: "working directory") + case .Argv: + return self.setArgument(name: "argv") + case .LaunchSuccess: + return self.getFromDevice(name: "launch success") + 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 .CreateInstproxy: + return self.createService(name: "instproxy") + case .CreateAfc: + return self.createService(name: "AFC") + case .RwAfc: + return NSLocalizedString("AFC was unable to manage files on the device. Ensure Wi-Fi and LocalDevVPN are connected. If they both are, replace your pairing using iloader.", comment: "") + case .InstallApp(let message): + return NSLocalizedString("Unable to install the app: \(message.toString())", comment: "") + case .UninstallApp: + return NSLocalizedString("Unable to uninstall the app", comment: "") + + case .CreateMisagent: + return self.createService(name: "misagent") + case .ProfileInstall: + return NSLocalizedString("Unable to manage profiles on the device", comment: "") + case .ProfileRemove: + return NSLocalizedString("Unable to manage profiles on the device", comment: "") + case .CreateLockdown: + return NSLocalizedString("Unable to connect to lockdown", comment: "") + case .CreateCoreDevice: + return NSLocalizedString("Unable to connect to core device proxy", comment: "") + case .CreateSoftwareTunnel: + return NSLocalizedString("Unable to create software tunnel", comment: "") + case .CreateRemoteServer: + return NSLocalizedString("Unable to connect to remote server", comment: "") + case .CreateProcessControl: + return NSLocalizedString("Unable to connect to process control", comment: "") + case .GetLockdownValue: + return NSLocalizedString("Unable to get value from lockdown", comment: "") + case .Connect: + return NSLocalizedString("Unable to connect to TCP port", comment: "") + case .Close: + return NSLocalizedString("Unable to close TCP port", comment: "") + case .XpcHandshake: + return NSLocalizedString("Unable to get services from XPC", comment: "") + case .NoService: + return NSLocalizedString("Device did not contain service", comment: "") + case .InvalidProductVersion: + return NSLocalizedString("Service version was in an unexpected format", comment: "") + case .CreateFolder: + return NSLocalizedString("Unable to create DDI folder", comment: "") + case .DownloadImage: + return NSLocalizedString("Unable to download DDI", comment: "") + case .ImageLookup: + return NSLocalizedString("Unable to lookup DDI images", comment: "") + case .ImageRead: + return NSLocalizedString("Unable to read images to memory", comment: "") + case .Mount: + return NSLocalizedString("Mount failed", comment: "") + } + } + + fileprivate func createService(name: String) -> String { + return String(format: NSLocalizedString("Cannot start a %@ server on the device.", comment: ""), name) + } + + fileprivate func getFromDevice(name: String) -> String { + return String(format: NSLocalizedString("Cannot fetch %@ from the device.", comment: ""), name) + } + + fileprivate func setArgument(name: String) -> String { + return String(format: NSLocalizedString("Cannot set %@ on the device.", comment: ""), name) + } +}