mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Assuming the certificate used to originally sign an app is still valid, we can refresh an app simply by installing new provisioning profiles. However, if the signing certificate is no longer valid, we fall back to the old method of resigning + reinstalling.
105 lines
3.3 KiB
Swift
105 lines
3.3 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): completionHandler(.failure(error))
|
|
case .success: completionHandler(.success(()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
completionHandler(.failure(error))
|
|
}
|
|
}
|
|
}
|