mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
refactor minimuxer to use swift-bridge (#321)
also add team ID to the end of the bundle ID for Debug builds to mirror SideServer
This commit is contained in:
@@ -44,14 +44,9 @@ final class DeactivateAppOperation: ResultOperation<InstalledApp>
|
||||
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,23 +45,13 @@ final class EnableJITOperation<Context: EnableJITContext>: ResultOperation<Void>
|
||||
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(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import Network
|
||||
import AltStoreCore
|
||||
import AltSign
|
||||
import Roxas
|
||||
import minimuxer
|
||||
|
||||
@objc(InstallAppOperation)
|
||||
final class InstallAppOperation: ResultOperation<InstalledApp>
|
||||
@@ -148,17 +149,14 @@ final class InstallAppOperation: ResultOperation<InstalledApp>
|
||||
})
|
||||
}
|
||||
|
||||
let ns_bundle = NSString(string: installedApp.bundleIdentifier)
|
||||
let ns_bundle_ptr = UnsafeMutablePointer<CChar>(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<InstalledApp>
|
||||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,15 +49,12 @@ final class RefreshAppOperation: ResultOperation<InstalledApp>
|
||||
|
||||
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)
|
||||
|
||||
@@ -39,15 +39,11 @@ final class RemoveAppOperation: ResultOperation<InstalledApp>
|
||||
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
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ final class ResignAppOperation: ResultOperation<ALTApplication>
|
||||
{
|
||||
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 }
|
||||
|
||||
@@ -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<CChar>(mutating: ns_bundle.utf8String)
|
||||
|
||||
if let data = NSData(contentsOf: fileURL) {
|
||||
let pls = UnsafeMutablePointer<UInt8>.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)))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user