mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Deactivating apps by removing their profiles no longer works on iOS 13.5. Instead, AltStore will now back up the app by temporarily replacing it with AltBackup, then remove the app from the phone.
110 lines
3.5 KiB
Swift
110 lines
3.5 KiB
Swift
//
|
|
// SendAppOperation.swift
|
|
// AltStore
|
|
//
|
|
// Created by Riley Testut on 6/7/19.
|
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import Network
|
|
|
|
import AltKit
|
|
|
|
@objc(SendAppOperation)
|
|
class SendAppOperation: ResultOperation<ServerConnection>
|
|
{
|
|
let context: AppOperationContext
|
|
|
|
private let dispatchQueue = DispatchQueue(label: "com.altstore.SendAppOperation")
|
|
|
|
private var serverConnection: ServerConnection?
|
|
|
|
init(context: AppOperationContext)
|
|
{
|
|
self.context = context
|
|
|
|
super.init()
|
|
|
|
self.progress.totalUnitCount = 1
|
|
}
|
|
|
|
override func main()
|
|
{
|
|
super.main()
|
|
|
|
if let error = self.context.error
|
|
{
|
|
self.finish(.failure(error))
|
|
return
|
|
}
|
|
|
|
guard let app = self.context.app, let server = self.context.server else { return self.finish(.failure(OperationError.invalidParameters)) }
|
|
|
|
// self.context.resignedApp.fileURL points to the app bundle, but we want the .ipa.
|
|
let fileURL = InstalledApp.refreshedIPAURL(for: app)
|
|
|
|
// Connect to server.
|
|
ServerManager.shared.connect(to: server) { (result) in
|
|
switch result
|
|
{
|
|
case .failure(let error): self.finish(.failure(error))
|
|
case .success(let serverConnection):
|
|
self.serverConnection = serverConnection
|
|
|
|
// Send app to server.
|
|
self.sendApp(at: fileURL, via: serverConnection) { (result) in
|
|
switch result
|
|
{
|
|
case .failure(let error): self.finish(.failure(error))
|
|
case .success:
|
|
self.progress.completedUnitCount += 1
|
|
self.finish(.success(serverConnection))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private extension SendAppOperation
|
|
{
|
|
func sendApp(at fileURL: URL, via connection: ServerConnection, completionHandler: @escaping (Result<Void, Error>) -> Void)
|
|
{
|
|
do
|
|
{
|
|
guard let appData = try? Data(contentsOf: fileURL) else { throw OperationError.invalidApp }
|
|
guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else { throw OperationError.unknownUDID }
|
|
|
|
let request = PrepareAppRequest(udid: udid, contentSize: appData.count)
|
|
|
|
print("Sending request \(request)")
|
|
connection.send(request) { (result) in
|
|
switch result
|
|
{
|
|
case .failure(let error): completionHandler(.failure(error))
|
|
case .success:
|
|
|
|
print("Sending app data (\(appData.count) bytes)")
|
|
connection.send(appData, prependSize: false) { (result) in
|
|
switch result
|
|
{
|
|
case .failure(let error):
|
|
print("Failed to send app data (\(appData.count) bytes)")
|
|
completionHandler(.failure(error))
|
|
|
|
case .success:
|
|
print("Successfully sent app data (\(appData.count) bytes)")
|
|
completionHandler(.success(()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
completionHandler(.failure(error))
|
|
}
|
|
}
|
|
}
|