mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Installs apps from AltStore via AltServer
This commit is contained in:
9
AltKit/AltKit.h
Normal file
9
AltKit/AltKit.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// AltKit.h
|
||||||
|
// AltKit
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSError+ALTServerError.h"
|
||||||
17
AltKit/Bundle+AltStore.swift
Normal file
17
AltKit/Bundle+AltStore.swift
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Bundle+AltStore.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public extension Bundle
|
||||||
|
{
|
||||||
|
struct Info
|
||||||
|
{
|
||||||
|
public static let deviceID = "ALTDeviceID"
|
||||||
|
}
|
||||||
|
}
|
||||||
33
AltKit/NSError+ALTServerError.h
Normal file
33
AltKit/NSError+ALTServerError.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// NSError+ALTServerError.h
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
extern NSErrorDomain const AltServerErrorDomain;
|
||||||
|
|
||||||
|
typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
|
||||||
|
{
|
||||||
|
ALTServerErrorUnknown,
|
||||||
|
ALTServerErrorConnectionFailed,
|
||||||
|
ALTServerErrorLostConnection,
|
||||||
|
|
||||||
|
ALTServerErrorDeviceNotFound,
|
||||||
|
ALTServerErrorDeviceWriteFailed,
|
||||||
|
|
||||||
|
ALTServerErrorInvalidRequest,
|
||||||
|
ALTServerErrorInvalidResponse,
|
||||||
|
|
||||||
|
ALTServerErrorInvalidApp,
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface NSError (ALTServerError)
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
14
AltKit/NSError+ALTServerError.m
Normal file
14
AltKit/NSError+ALTServerError.m
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// NSError+ALTServerError.m
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSError+ALTServerError.h"
|
||||||
|
|
||||||
|
NSErrorDomain const AltServerErrorDomain = @"com.rileytestut.AltServer";
|
||||||
|
|
||||||
|
@implementation NSError (ALTServerError)
|
||||||
|
@end
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension Result
|
public extension Result
|
||||||
{
|
{
|
||||||
init(_ value: Success?, _ error: Failure?)
|
init(_ value: Success?, _ error: Failure?)
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,7 @@ extension Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Result where Success == Void
|
public extension Result where Success == Void
|
||||||
{
|
{
|
||||||
init(_ success: Bool, _ error: Failure?)
|
init(_ success: Bool, _ error: Failure?)
|
||||||
{
|
{
|
||||||
48
AltKit/ServerProtocol.swift
Normal file
48
AltKit/ServerProtocol.swift
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// ServerProtocol.swift
|
||||||
|
// AltServer
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/24/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public let ALTServerServiceType = "_altserver._tcp"
|
||||||
|
|
||||||
|
// Can only automatically conform ALTServerError.Code to Codable, not ALTServerError itself
|
||||||
|
extension ALTServerError.Code: Codable {}
|
||||||
|
|
||||||
|
public struct ServerRequest: Codable
|
||||||
|
{
|
||||||
|
public var udid: String
|
||||||
|
public var contentSize: Int
|
||||||
|
|
||||||
|
public init(udid: String, contentSize: Int)
|
||||||
|
{
|
||||||
|
self.udid = udid
|
||||||
|
self.contentSize = contentSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ServerResponse: Codable
|
||||||
|
{
|
||||||
|
public var success: Bool
|
||||||
|
public var error: ALTServerError? {
|
||||||
|
get {
|
||||||
|
guard let code = self.errorCode else { return nil }
|
||||||
|
return ALTServerError(code)
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
self.errorCode = newValue?.code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var errorCode: ALTServerError.Code?
|
||||||
|
|
||||||
|
public init(success: Bool, error: ALTServerError?)
|
||||||
|
{
|
||||||
|
self.success = success
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
}
|
||||||
325
AltServer/Connections/ConnectionManager.swift
Normal file
325
AltServer/Connections/ConnectionManager.swift
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
//
|
||||||
|
// ConnectionManager.swift
|
||||||
|
// AltServer
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/23/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Network
|
||||||
|
|
||||||
|
import AltKit
|
||||||
|
|
||||||
|
extension ALTServerError
|
||||||
|
{
|
||||||
|
init<E: Error>(_ error: E)
|
||||||
|
{
|
||||||
|
switch error
|
||||||
|
{
|
||||||
|
case let error as ALTServerError: self = error
|
||||||
|
case is DecodingError: self = ALTServerError(.invalidRequest)
|
||||||
|
case is EncodingError: self = ALTServerError(.invalidResponse)
|
||||||
|
default:
|
||||||
|
assertionFailure("Caught unknown error type")
|
||||||
|
self = ALTServerError(.unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ConnectionManager
|
||||||
|
{
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
case notRunning
|
||||||
|
case connecting
|
||||||
|
case running(NWListener.Service)
|
||||||
|
case failed(Swift.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConnectionManager
|
||||||
|
{
|
||||||
|
static let shared = ConnectionManager()
|
||||||
|
|
||||||
|
var stateUpdateHandler: ((State) -> Void)?
|
||||||
|
|
||||||
|
private(set) var state: State = .notRunning {
|
||||||
|
didSet {
|
||||||
|
self.stateUpdateHandler?(self.state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var listener = self.makeListener()
|
||||||
|
private let dispatchQueue = DispatchQueue(label: "com.rileytestut.AltServer.connections", qos: .utility)
|
||||||
|
|
||||||
|
private var connections = [NWConnection]()
|
||||||
|
|
||||||
|
private init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
func start()
|
||||||
|
{
|
||||||
|
switch self.state
|
||||||
|
{
|
||||||
|
case .notRunning, .failed: self.listener.start(queue: self.dispatchQueue)
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stop()
|
||||||
|
{
|
||||||
|
switch self.state
|
||||||
|
{
|
||||||
|
case .running: self.listener.cancel()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension ConnectionManager
|
||||||
|
{
|
||||||
|
func makeListener() -> NWListener
|
||||||
|
{
|
||||||
|
let listener = try! NWListener(using: .tcp)
|
||||||
|
listener.service = NWListener.Service(type: ALTServerServiceType)
|
||||||
|
|
||||||
|
listener.serviceRegistrationUpdateHandler = { (serviceChange) in
|
||||||
|
switch serviceChange
|
||||||
|
{
|
||||||
|
case .add(.service(let name, let type, let domain, _)):
|
||||||
|
let service = NWListener.Service(name: name, type: type, domain: domain, txtRecord: nil)
|
||||||
|
self.state = .running(service)
|
||||||
|
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.stateUpdateHandler = { (state) in
|
||||||
|
switch state
|
||||||
|
{
|
||||||
|
case .ready: break
|
||||||
|
case .waiting, .setup: self.state = .connecting
|
||||||
|
case .cancelled: self.state = .notRunning
|
||||||
|
case .failed(let error):
|
||||||
|
self.state = .failed(error)
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
@unknown default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.newConnectionHandler = { [weak self] (connection) in
|
||||||
|
self?.awaitRequest(from: connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
return listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func disconnect(_ connection: NWConnection)
|
||||||
|
{
|
||||||
|
switch connection.state
|
||||||
|
{
|
||||||
|
case .cancelled, .failed:
|
||||||
|
print("Disconnecting from \(connection.endpoint)...")
|
||||||
|
|
||||||
|
if let index = self.connections.firstIndex(where: { $0 === connection })
|
||||||
|
{
|
||||||
|
self.connections.remove(at: index)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// State update handler will call this method again.
|
||||||
|
connection.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(data: Data?, error: NWError?, from connection: NWConnection) throws -> Data
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
guard let data = data else { throw error ?? ALTServerError(.unknown) }
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
catch let error as NWError
|
||||||
|
{
|
||||||
|
print("Error receiving data from connection \(connection)", error)
|
||||||
|
|
||||||
|
throw ALTServerError(.lostConnection)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch let error as ALTServerError
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
preconditionFailure("A non-ALTServerError should never be thrown from this method.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension ConnectionManager
|
||||||
|
{
|
||||||
|
func awaitRequest(from connection: NWConnection)
|
||||||
|
{
|
||||||
|
guard !self.connections.contains(where: { $0 === connection }) else { return }
|
||||||
|
self.connections.append(connection)
|
||||||
|
|
||||||
|
connection.stateUpdateHandler = { [weak self] (state) in
|
||||||
|
switch state
|
||||||
|
{
|
||||||
|
case .setup, .preparing: break
|
||||||
|
|
||||||
|
case .ready:
|
||||||
|
print("Connected to client:", connection.endpoint)
|
||||||
|
|
||||||
|
case .waiting:
|
||||||
|
print("Waiting for connection...")
|
||||||
|
|
||||||
|
case .failed(let error):
|
||||||
|
print("Failed to connect to service \(connection.endpoint).", error)
|
||||||
|
self?.disconnect(connection)
|
||||||
|
|
||||||
|
case .cancelled:
|
||||||
|
self?.disconnect(connection)
|
||||||
|
|
||||||
|
@unknown default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.start(queue: self.dispatchQueue)
|
||||||
|
|
||||||
|
func finish(error: ALTServerError?)
|
||||||
|
{
|
||||||
|
if let error = error
|
||||||
|
{
|
||||||
|
print("Failed to process request from \(connection.endpoint).", error)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print("Processed request from \(connection.endpoint).")
|
||||||
|
}
|
||||||
|
|
||||||
|
let success = (error == nil)
|
||||||
|
let response = ServerResponse(success: success, error: error)
|
||||||
|
|
||||||
|
self.send(response, to: connection) { (result) in
|
||||||
|
print("Sent response to \(connection) with result:", result)
|
||||||
|
|
||||||
|
self.disconnect(connection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.receiveRequest(from: connection) { (result) in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error): finish(error: error)
|
||||||
|
case .success(let request, let fileURL):
|
||||||
|
ALTDeviceManager.shared.installApp(at: fileURL, toDeviceWithUDID: request.udid) { (success, error) in
|
||||||
|
let error = error.map { $0 as? ALTServerError ?? ALTServerError(.unknown) }
|
||||||
|
finish(error: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func receiveRequest(from connection: NWConnection, completionHandler: @escaping (Result<(ServerRequest, URL), ALTServerError>) -> Void)
|
||||||
|
{
|
||||||
|
let size = MemoryLayout<Int32>.size
|
||||||
|
|
||||||
|
connection.receive(minimumIncompleteLength: size, maximumLength: size) { (data, _, _, error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try self.process(data: data, error: error, from: connection)
|
||||||
|
|
||||||
|
let expectedBytes = Int(data.withUnsafeBytes { $0.load(as: Int32.self) })
|
||||||
|
connection.receive(minimumIncompleteLength: expectedBytes, maximumLength: expectedBytes) { (data, _, _, error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try self.process(data: data, error: error, from: connection)
|
||||||
|
|
||||||
|
let request = try JSONDecoder().decode(ServerRequest.self, from: data)
|
||||||
|
self.process(request, from: connection, completionHandler: completionHandler)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(_ request: ServerRequest, from connection: NWConnection, completionHandler: @escaping (Result<(ServerRequest, URL), ALTServerError>) -> Void)
|
||||||
|
{
|
||||||
|
connection.receive(minimumIncompleteLength: request.contentSize, maximumLength: request.contentSize) { (data, _, _, error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try self.process(data: data, error: error, from: connection)
|
||||||
|
|
||||||
|
guard ALTDeviceManager.shared.connectedDevices.contains(where: { $0.identifier == request.udid }) else { throw ALTServerError(.deviceNotFound) }
|
||||||
|
|
||||||
|
let temporaryURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".ipa")
|
||||||
|
try data.write(to: temporaryURL, options: .atomic)
|
||||||
|
|
||||||
|
print("Wrote app to URL:", temporaryURL)
|
||||||
|
|
||||||
|
completionHandler(.success((request, temporaryURL)))
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func send(_ response: ServerResponse, to connection: NWConnection, completionHandler: @escaping (Result<Void, ALTServerError>) -> Void)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try JSONEncoder().encode(response)
|
||||||
|
let responseSize = withUnsafeBytes(of: Int32(data.count)) { Data($0) }
|
||||||
|
|
||||||
|
connection.send(content: responseSize, completion: .contentProcessed { (error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if let error = error
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.send(content: data, completion: .contentProcessed { (error) in
|
||||||
|
if error != nil
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.init(.lostConnection)))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionHandler(.success(()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.init(.lostConnection)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.init(.invalidResponse)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,23 +11,13 @@
|
|||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
extern NSErrorDomain const ALTDeviceErrorDomain;
|
|
||||||
|
|
||||||
typedef NS_ERROR_ENUM(ALTDeviceErrorDomain, ALTDeviceError)
|
|
||||||
{
|
|
||||||
ALTDeviceErrorUnknown,
|
|
||||||
ALTDeviceErrorNotConnected,
|
|
||||||
ALTDeviceErrorConnectionFailed,
|
|
||||||
ALTDeviceErrorWriteFailed,
|
|
||||||
};
|
|
||||||
|
|
||||||
@interface ALTDeviceManager : NSObject
|
@interface ALTDeviceManager : NSObject
|
||||||
|
|
||||||
@property (class, nonatomic, readonly) ALTDeviceManager *sharedManager;
|
@property (class, nonatomic, readonly) ALTDeviceManager *sharedManager;
|
||||||
|
|
||||||
@property (nonatomic, readonly) NSArray<ALTDevice *> *connectedDevices;
|
@property (nonatomic, readonly) NSArray<ALTDevice *> *connectedDevices;
|
||||||
|
|
||||||
- (NSProgress *)installAppAtURL:(NSURL *)fileURL toDevice:(ALTDevice *)altDevice completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
- (NSProgress *)installAppAtURL:(NSURL *)fileURL toDeviceWithUDID:(NSString *)udid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "ALTDeviceManager.h"
|
#import "ALTDeviceManager.h"
|
||||||
|
#import "NSError+ALTServerError.h"
|
||||||
|
|
||||||
#include <libimobiledevice/libimobiledevice.h>
|
#include <libimobiledevice/libimobiledevice.h>
|
||||||
#include <libimobiledevice/lockdown.h>
|
#include <libimobiledevice/lockdown.h>
|
||||||
@@ -51,7 +52,7 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSProgress *)installAppAtURL:(NSURL *)fileURL toDevice:(ALTDevice *)altDevice completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
- (NSProgress *)installAppAtURL:(NSURL *)fileURL toDeviceWithUDID:(NSString *)udid completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler
|
||||||
{
|
{
|
||||||
NSProgress *progress = [NSProgress discreteProgressWithTotalUnitCount:100];
|
NSProgress *progress = [NSProgress discreteProgressWithTotalUnitCount:100];
|
||||||
|
|
||||||
@@ -119,29 +120,29 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find Device */
|
/* Find Device */
|
||||||
if (idevice_new(&device, altDevice.identifier.UTF8String) != IDEVICE_E_SUCCESS)
|
if (idevice_new(&device, udid.UTF8String) != IDEVICE_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorNotConnected userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorDeviceNotFound userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect to Device */
|
/* Connect to Device */
|
||||||
if (lockdownd_client_new_with_handshake(device, &client, "altserver") != LOCKDOWN_E_SUCCESS)
|
if (lockdownd_client_new_with_handshake(device, &client, "altserver") != LOCKDOWN_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect to Notification Proxy */
|
/* Connect to Notification Proxy */
|
||||||
if ((lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
if ((lockdownd_start_service(client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (np_client_new(device, service, &np) != NP_E_SUCCESS)
|
if (np_client_new(device, service, &np) != NP_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,13 +160,13 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
/* Connect to Installation Proxy */
|
/* Connect to Installation Proxy */
|
||||||
if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instproxy_client_new(device, service, &ipc) != INSTPROXY_E_SUCCESS)
|
if (instproxy_client_new(device, service, &ipc) != INSTPROXY_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
/* Connect to AFC service */
|
/* Connect to AFC service */
|
||||||
if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || service == NULL)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +191,7 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
|
|
||||||
if (afc_client_new(device, service, &afc) != AFC_E_SUCCESS)
|
if (afc_client_new(device, service, &afc) != AFC_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorConnectionFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorConnectionFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +203,7 @@ NSErrorDomain const ALTDeviceErrorDomain = @"com.rileytestut.ALTDeviceError";
|
|||||||
{
|
{
|
||||||
if (afc_make_directory(afc, stagingURL.relativePath.fileSystemRepresentation) != AFC_E_SUCCESS)
|
if (afc_make_directory(afc, stagingURL.relativePath.fileSystemRepresentation) != AFC_E_SUCCESS)
|
||||||
{
|
{
|
||||||
finish([NSError errorWithDomain:ALTDeviceErrorDomain code:ALTDeviceErrorWriteFailed userInfo:nil]);
|
finish([NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorDeviceWriteFailed userInfo:nil]);
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,4 +455,6 @@ void ALTDeviceManagerUpdateStatus(plist_t command, plist_t status, void *udid)
|
|||||||
{
|
{
|
||||||
progress.completedUnitCount = percent;
|
progress.completedUnitCount = percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSLog(@"Installation Progress: %@", @(percent));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,20 @@ class ViewController: NSViewController
|
|||||||
{
|
{
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
ConnectionManager.shared.stateUpdateHandler = { (state) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
switch state
|
||||||
|
{
|
||||||
|
case .notRunning: self.view.window?.title = ""
|
||||||
|
case .connecting: self.view.window?.title = "Connecting..."
|
||||||
|
case .running(let service): self.view.window?.title = service.name ?? ""
|
||||||
|
case .failed(let error): self.view.window?.title = error.localizedDescription
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionManager.shared.start()
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +350,7 @@ private extension ViewController
|
|||||||
let infoPlistURL = appBundleURL.appendingPathComponent("Info.plist")
|
let infoPlistURL = appBundleURL.appendingPathComponent("Info.plist")
|
||||||
|
|
||||||
guard var infoDictionary = NSDictionary(contentsOf: infoPlistURL) as? [String: Any] else { throw ALTError(.missingInfoPlist) }
|
guard var infoDictionary = NSDictionary(contentsOf: infoPlistURL) as? [String: Any] else { throw ALTError(.missingInfoPlist) }
|
||||||
infoDictionary["altstore"] = ["udid": device.identifier]
|
infoDictionary[Bundle.Info.deviceID] = device.identifier
|
||||||
try (infoDictionary as NSDictionary).write(to: infoPlistURL)
|
try (infoDictionary as NSDictionary).write(to: infoPlistURL)
|
||||||
|
|
||||||
let zippedURL = try FileManager.default.zipAppBundle(at: appBundleURL)
|
let zippedURL = try FileManager.default.zipAppBundle(at: appBundleURL)
|
||||||
@@ -346,7 +360,7 @@ private extension ViewController
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
let resignedURL = try Result(resignedURL, error).get()
|
let resignedURL = try Result(resignedURL, error).get()
|
||||||
ALTDeviceManager.shared.installApp(at: resignedURL, to: device) { (success, error) in
|
ALTDeviceManager.shared.installApp(at: resignedURL, toDeviceWithUDID: device.identifier) { (success, error) in
|
||||||
let result = Result(success, error)
|
let result = Result(success, error)
|
||||||
print(result)
|
print(result)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
BF1E312B229F474900370A3C /* ConnectionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3129229F474900370A3C /* ConnectionManager.swift */; };
|
||||||
|
BF1E3137229F599C00370A3C /* App.ipa in Resources */ = {isa = PBXBuildFile; fileRef = BF1E3136229F599C00370A3C /* App.ipa */; };
|
||||||
|
BF1E315722A061F500370A3C /* ServerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3128229F474900370A3C /* ServerProtocol.swift */; };
|
||||||
|
BF1E315822A061F900370A3C /* Result+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBAC8852295C90300587369 /* Result+Conveniences.swift */; };
|
||||||
|
BF1E315922A061FB00370A3C /* Bundle+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E314122A05D4C00370A3C /* Bundle+AltStore.swift */; };
|
||||||
|
BF1E315A22A0620000370A3C /* NSError+ALTServerError.m in Sources */ = {isa = PBXBuildFile; fileRef = BF1E314922A060F400370A3C /* NSError+ALTServerError.m */; };
|
||||||
|
BF1E315F22A0635900370A3C /* libAltKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1E315022A0616100370A3C /* libAltKit.a */; };
|
||||||
|
BF1E316022A0636400370A3C /* libAltKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1E315022A0616100370A3C /* libAltKit.a */; };
|
||||||
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF45868F229872EA00BD7491 /* AppDelegate.swift */; };
|
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF45868F229872EA00BD7491 /* AppDelegate.swift */; };
|
||||||
BF458692229872EA00BD7491 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF458691229872EA00BD7491 /* ViewController.swift */; };
|
BF458692229872EA00BD7491 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF458691229872EA00BD7491 /* ViewController.swift */; };
|
||||||
BF458694229872EA00BD7491 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF458693229872EA00BD7491 /* Assets.xcassets */; };
|
BF458694229872EA00BD7491 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF458693229872EA00BD7491 /* Assets.xcassets */; };
|
||||||
@@ -106,12 +114,11 @@
|
|||||||
BF4588932298DE0C00BD7491 /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888D2298DE0C00BD7491 /* iterator.c */; };
|
BF4588932298DE0C00BD7491 /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888D2298DE0C00BD7491 /* iterator.c */; };
|
||||||
BF4588942298DE0C00BD7491 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888E2298DE0C00BD7491 /* cnary.c */; };
|
BF4588942298DE0C00BD7491 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888E2298DE0C00BD7491 /* cnary.c */; };
|
||||||
BF4588952298DE0C00BD7491 /* node.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888F2298DE0C00BD7491 /* node.c */; };
|
BF4588952298DE0C00BD7491 /* node.c in Sources */ = {isa = PBXBuildFile; fileRef = BF45888F2298DE0C00BD7491 /* node.c */; };
|
||||||
BF4588972298DE6E00BD7491 /* libzip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF4588962298DE6E00BD7491 /* libzip.framework */; };
|
BF4713A522976D1E00784A2F /* openssl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF4713A422976CFC00784A2F /* openssl.framework */; };
|
||||||
|
BF4713A622976D1E00784A2F /* openssl.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF4713A422976CFC00784A2F /* openssl.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
BF5AB3A82285FE7500DC914B /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; };
|
BF5AB3A82285FE7500DC914B /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; };
|
||||||
BF5AB3A92285FE7500DC914B /* AltSign.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BF5AB3A92285FE7500DC914B /* AltSign.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF5AB3A72285FE6C00DC914B /* AltSign.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
BF9B63C6229DD44E002F0A62 /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9B63C5229DD44D002F0A62 /* AltSign.framework */; };
|
BF9B63C6229DD44E002F0A62 /* AltSign.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9B63C5229DD44D002F0A62 /* AltSign.framework */; };
|
||||||
BF9B63F6229DE476002F0A62 /* App.ipa in Resources */ = {isa = PBXBuildFile; fileRef = BF9B63F5229DE476002F0A62 /* App.ipa */; };
|
|
||||||
BF9B6426229E1331002F0A62 /* Result+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9B6425229E1331002F0A62 /* Result+Conveniences.swift */; };
|
|
||||||
BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB11691229322E400BB457C /* DatabaseManager.swift */; };
|
BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB11691229322E400BB457C /* DatabaseManager.swift */; };
|
||||||
BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */; };
|
BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */; };
|
||||||
BFB1169D22932DB100BB457C /* Apps.json in Resources */ = {isa = PBXBuildFile; fileRef = BFB1169C22932DB100BB457C /* Apps.json */; };
|
BFB1169D22932DB100BB457C /* Apps.json in Resources */ = {isa = PBXBuildFile; fileRef = BFB1169C22932DB100BB457C /* Apps.json */; };
|
||||||
@@ -132,9 +139,26 @@
|
|||||||
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247922284D4B700981D42 /* AppTableViewCell.swift */; };
|
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247922284D4B700981D42 /* AppTableViewCell.swift */; };
|
||||||
BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */; };
|
BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */; };
|
||||||
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */; };
|
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */; };
|
||||||
|
BFD52BD422A0800A000B7ED1 /* ServerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BD322A0800A000B7ED1 /* ServerManager.swift */; };
|
||||||
|
BFD52BD622A08A85000B7ED1 /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD52BD522A08A85000B7ED1 /* Server.swift */; };
|
||||||
|
BFD52BDA22A099FA000B7ED1 /* App.ipa in Resources */ = {isa = PBXBuildFile; fileRef = BFD52BD922A099FA000B7ED1 /* App.ipa */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
BF1E315B22A0621900370A3C /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = BFD247622284B9A500981D42 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = BF1E314F22A0616100370A3C;
|
||||||
|
remoteInfo = AltKit;
|
||||||
|
};
|
||||||
|
BF1E315D22A0621F00370A3C /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = BFD247622284B9A500981D42 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = BF1E314F22A0616100370A3C;
|
||||||
|
remoteInfo = AltKit;
|
||||||
|
};
|
||||||
BF4588442298D48B00BD7491 /* PBXContainerItemProxy */ = {
|
BF4588442298D48B00BD7491 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = BFD247622284B9A500981D42 /* Project object */;
|
containerPortal = BFD247622284B9A500981D42 /* Project object */;
|
||||||
@@ -145,6 +169,15 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
BF1E314E22A0616100370A3C /* CopyFiles */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "include/$(PRODUCT_NAME)";
|
||||||
|
dstSubfolderSpec = 16;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
BF9B6324229DBBED002F0A62 /* Embed Frameworks */ = {
|
BF9B6324229DBBED002F0A62 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -161,6 +194,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
|
BF4713A622976D1E00784A2F /* openssl.framework in Embed Frameworks */,
|
||||||
BFD247882284BB4200981D42 /* Roxas.framework in Embed Frameworks */,
|
BFD247882284BB4200981D42 /* Roxas.framework in Embed Frameworks */,
|
||||||
BF5AB3A92285FE7500DC914B /* AltSign.framework in Embed Frameworks */,
|
BF5AB3A92285FE7500DC914B /* AltSign.framework in Embed Frameworks */,
|
||||||
);
|
);
|
||||||
@@ -170,6 +204,14 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
BF1E3128229F474900370A3C /* ServerProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
BF1E3129229F474900370A3C /* ConnectionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConnectionManager.swift; sourceTree = "<group>"; };
|
||||||
|
BF1E3136229F599C00370A3C /* App.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; name = App.ipa; path = ../../../../../../../../../../Desktop/App.ipa; sourceTree = "<group>"; };
|
||||||
|
BF1E314122A05D4C00370A3C /* Bundle+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+AltStore.swift"; sourceTree = "<group>"; };
|
||||||
|
BF1E314722A060F300370A3C /* AltStore-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AltStore-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
BF1E314822A060F400370A3C /* NSError+ALTServerError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+ALTServerError.h"; sourceTree = "<group>"; };
|
||||||
|
BF1E314922A060F400370A3C /* NSError+ALTServerError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+ALTServerError.m"; sourceTree = "<group>"; };
|
||||||
|
BF1E315022A0616100370A3C /* libAltKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAltKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF45868D229872EA00BD7491 /* AltServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
BF45868D229872EA00BD7491 /* AltServer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltServer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF45868F229872EA00BD7491 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
BF45868F229872EA00BD7491 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
BF458691229872EA00BD7491 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
BF458691229872EA00BD7491 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||||
@@ -275,14 +317,14 @@
|
|||||||
BF45888E2298DE0C00BD7491 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/AltSign/Dependencies/ldid/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; };
|
BF45888E2298DE0C00BD7491 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/AltSign/Dependencies/ldid/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; };
|
||||||
BF45888F2298DE0C00BD7491 /* node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node.c; path = Dependencies/AltSign/Dependencies/ldid/libplist/libcnary/node.c; sourceTree = SOURCE_ROOT; };
|
BF45888F2298DE0C00BD7491 /* node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node.c; path = Dependencies/AltSign/Dependencies/ldid/libplist/libcnary/node.c; sourceTree = SOURCE_ROOT; };
|
||||||
BF4588962298DE6E00BD7491 /* libzip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = libzip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BF4588962298DE6E00BD7491 /* libzip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = libzip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
BF4713A422976CFC00784A2F /* openssl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = openssl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF5AB3A72285FE6C00DC914B /* AltSign.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BF5AB3A72285FE6C00DC914B /* AltSign.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF9B63C5229DD44D002F0A62 /* AltSign.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BF9B63C5229DD44D002F0A62 /* AltSign.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AltSign.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF9B63F5229DE476002F0A62 /* App.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; path = App.ipa; sourceTree = "<group>"; };
|
|
||||||
BF9B6425229E1331002F0A62 /* Result+Conveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Result+Conveniences.swift"; sourceTree = "<group>"; };
|
|
||||||
BFB11691229322E400BB457C /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
|
BFB11691229322E400BB457C /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = "<group>"; };
|
||||||
BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+ManagedObjectContext.swift"; sourceTree = "<group>"; };
|
BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+ManagedObjectContext.swift"; sourceTree = "<group>"; };
|
||||||
BFB1169C22932DB100BB457C /* Apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Apps.json; sourceTree = "<group>"; };
|
BFB1169C22932DB100BB457C /* Apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Apps.json; sourceTree = "<group>"; };
|
||||||
BFB1169F22933DEB00BB457C /* UpdatesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatesViewController.swift; sourceTree = "<group>"; };
|
BFB1169F22933DEB00BB457C /* UpdatesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdatesViewController.swift; sourceTree = "<group>"; };
|
||||||
|
BFBAC8852295C90300587369 /* Result+Conveniences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+Conveniences.swift"; sourceTree = "<group>"; };
|
||||||
BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = AltStore.xcdatamodel; sourceTree = "<group>"; };
|
BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = AltStore.xcdatamodel; sourceTree = "<group>"; };
|
||||||
BFBBE2DE22931F73002097FA /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
BFBBE2DE22931F73002097FA /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||||
BFBBE2E022931F81002097FA /* InstalledApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledApp.swift; sourceTree = "<group>"; };
|
BFBBE2E022931F81002097FA /* InstalledApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledApp.swift; sourceTree = "<group>"; };
|
||||||
@@ -300,10 +342,14 @@
|
|||||||
BFD247922284D4B700981D42 /* AppTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTableViewCell.swift; sourceTree = "<group>"; };
|
BFD247922284D4B700981D42 /* AppTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDetailViewController.swift; sourceTree = "<group>"; };
|
BFD2479B2284E19A00981D42 /* AppDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDetailViewController.swift; sourceTree = "<group>"; };
|
||||||
BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+AltStore.swift"; sourceTree = "<group>"; };
|
BFD2479E2284FBD000981D42 /* UIColor+AltStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+AltStore.swift"; sourceTree = "<group>"; };
|
||||||
|
BFD52BD222A06EFB000B7ED1 /* AltKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AltKit.h; sourceTree = "<group>"; };
|
||||||
|
BFD52BD322A0800A000B7ED1 /* ServerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerManager.swift; sourceTree = "<group>"; };
|
||||||
|
BFD52BD522A08A85000B7ED1 /* Server.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Server.swift; sourceTree = "<group>"; };
|
||||||
|
BFD52BD922A099FA000B7ED1 /* App.ipa */ = {isa = PBXFileReference; lastKnownFileType = file; path = App.ipa; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
BF4587292298D31600BD7491 /* Frameworks */ = {
|
BF1E314D22A0616100370A3C /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
@@ -314,8 +360,8 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
BF1E315F22A0635900370A3C /* libAltKit.a in Frameworks */,
|
||||||
BF9B63C6229DD44E002F0A62 /* AltSign.framework in Frameworks */,
|
BF9B63C6229DD44E002F0A62 /* AltSign.framework in Frameworks */,
|
||||||
BF4588972298DE6E00BD7491 /* libzip.framework in Frameworks */,
|
|
||||||
BF4588882298DD3F00BD7491 /* libxml2.tbd in Frameworks */,
|
BF4588882298DD3F00BD7491 /* libxml2.tbd in Frameworks */,
|
||||||
BF4588552298DC5400BD7491 /* openssl.framework in Frameworks */,
|
BF4588552298DC5400BD7491 /* openssl.framework in Frameworks */,
|
||||||
BF4588472298D4B000BD7491 /* libimobiledevice.a in Frameworks */,
|
BF4588472298D4B000BD7491 /* libimobiledevice.a in Frameworks */,
|
||||||
@@ -326,6 +372,8 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
BF1E316022A0636400370A3C /* libAltKit.a in Frameworks */,
|
||||||
|
BF4713A522976D1E00784A2F /* openssl.framework in Frameworks */,
|
||||||
BFD247872284BB4200981D42 /* Roxas.framework in Frameworks */,
|
BFD247872284BB4200981D42 /* Roxas.framework in Frameworks */,
|
||||||
BF5AB3A82285FE7500DC914B /* AltSign.framework in Frameworks */,
|
BF5AB3A82285FE7500DC914B /* AltSign.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
@@ -334,6 +382,19 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
BF1E315122A0616100370A3C /* AltKit */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFD52BD222A06EFB000B7ED1 /* AltKit.h */,
|
||||||
|
BFBAC8852295C90300587369 /* Result+Conveniences.swift */,
|
||||||
|
BF1E314122A05D4C00370A3C /* Bundle+AltStore.swift */,
|
||||||
|
BF1E3128229F474900370A3C /* ServerProtocol.swift */,
|
||||||
|
BF1E314822A060F400370A3C /* NSError+ALTServerError.h */,
|
||||||
|
BF1E314922A060F400370A3C /* NSError+ALTServerError.m */,
|
||||||
|
);
|
||||||
|
path = AltKit;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
BF45868E229872EA00BD7491 /* AltServer */ = {
|
BF45868E229872EA00BD7491 /* AltServer */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -341,7 +402,7 @@
|
|||||||
BF458695229872EA00BD7491 /* Main.storyboard */,
|
BF458695229872EA00BD7491 /* Main.storyboard */,
|
||||||
BF458691229872EA00BD7491 /* ViewController.swift */,
|
BF458691229872EA00BD7491 /* ViewController.swift */,
|
||||||
BF703195229F36FF006E110F /* Devices */,
|
BF703195229F36FF006E110F /* Devices */,
|
||||||
BF703193229F36E5006E110F /* Extensions */,
|
BFD52BDC22A0A659000B7ED1 /* Connections */,
|
||||||
BF703194229F36F6006E110F /* Resources */,
|
BF703194229F36F6006E110F /* Resources */,
|
||||||
BF703196229F370F006E110F /* Supporting Files */,
|
BF703196229F370F006E110F /* Supporting Files */,
|
||||||
);
|
);
|
||||||
@@ -486,19 +547,11 @@
|
|||||||
name = libcnary;
|
name = libcnary;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
BF703193229F36E5006E110F /* Extensions */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
BF9B6425229E1331002F0A62 /* Result+Conveniences.swift */,
|
|
||||||
);
|
|
||||||
path = Extensions;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
BF703194229F36F6006E110F /* Resources */ = {
|
BF703194229F36F6006E110F /* Resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF458693229872EA00BD7491 /* Assets.xcassets */,
|
BF458693229872EA00BD7491 /* Assets.xcassets */,
|
||||||
BF9B63F5229DE476002F0A62 /* App.ipa */,
|
BF1E3136229F599C00370A3C /* App.ipa */,
|
||||||
);
|
);
|
||||||
name = Resources;
|
name = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -538,11 +591,21 @@
|
|||||||
path = "My Apps";
|
path = "My Apps";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BFC51D7922972F1F00388324 /* Server */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFD52BD322A0800A000B7ED1 /* ServerManager.swift */,
|
||||||
|
BFD52BD522A08A85000B7ED1 /* Server.swift */,
|
||||||
|
);
|
||||||
|
path = Server;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
BFD247612284B9A500981D42 = {
|
BFD247612284B9A500981D42 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BFD2476C2284B9A500981D42 /* AltStore */,
|
BFD2476C2284B9A500981D42 /* AltStore */,
|
||||||
BF45868E229872EA00BD7491 /* AltServer */,
|
BF45868E229872EA00BD7491 /* AltServer */,
|
||||||
|
BF1E315122A0616100370A3C /* AltKit */,
|
||||||
BF45872C2298D31600BD7491 /* libimobiledevice */,
|
BF45872C2298D31600BD7491 /* libimobiledevice */,
|
||||||
BFD247852284BB3300981D42 /* Frameworks */,
|
BFD247852284BB3300981D42 /* Frameworks */,
|
||||||
BFD2476B2284B9A500981D42 /* Products */,
|
BFD2476B2284B9A500981D42 /* Products */,
|
||||||
@@ -555,6 +618,7 @@
|
|||||||
BFD2476A2284B9A500981D42 /* AltStore.app */,
|
BFD2476A2284B9A500981D42 /* AltStore.app */,
|
||||||
BF45868D229872EA00BD7491 /* AltServer.app */,
|
BF45868D229872EA00BD7491 /* AltServer.app */,
|
||||||
BF45872B2298D31600BD7491 /* libimobiledevice.a */,
|
BF45872B2298D31600BD7491 /* libimobiledevice.a */,
|
||||||
|
BF1E315022A0616100370A3C /* libAltKit.a */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -567,6 +631,7 @@
|
|||||||
BFD2478A2284C49000981D42 /* Apps */,
|
BFD2478A2284C49000981D42 /* Apps */,
|
||||||
BFBBE2E2229320A2002097FA /* My Apps */,
|
BFBBE2E2229320A2002097FA /* My Apps */,
|
||||||
BFB1169E22933DDC00BB457C /* Updates */,
|
BFB1169E22933DDC00BB457C /* Updates */,
|
||||||
|
BFC51D7922972F1F00388324 /* Server */,
|
||||||
BFD247982284D7FC00981D42 /* Model */,
|
BFD247982284D7FC00981D42 /* Model */,
|
||||||
BFD2478D2284C4C700981D42 /* Components */,
|
BFD2478D2284C4C700981D42 /* Components */,
|
||||||
BFD2479D2284FBBD00981D42 /* Extensions */,
|
BFD2479D2284FBBD00981D42 /* Extensions */,
|
||||||
@@ -585,6 +650,7 @@
|
|||||||
BF4588542298DC5400BD7491 /* openssl.framework */,
|
BF4588542298DC5400BD7491 /* openssl.framework */,
|
||||||
BFD247862284BB3B00981D42 /* Roxas.framework */,
|
BFD247862284BB3B00981D42 /* Roxas.framework */,
|
||||||
BF5AB3A72285FE6C00DC914B /* AltSign.framework */,
|
BF5AB3A72285FE6C00DC914B /* AltSign.framework */,
|
||||||
|
BF4713A422976CFC00784A2F /* openssl.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -611,6 +677,7 @@
|
|||||||
BFD247962284D7C100981D42 /* Resources */ = {
|
BFD247962284D7C100981D42 /* Resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
BFD52BD922A099FA000B7ED1 /* App.ipa */,
|
||||||
BFD247762284B9A700981D42 /* Assets.xcassets */,
|
BFD247762284B9A700981D42 /* Assets.xcassets */,
|
||||||
BFB1169C22932DB100BB457C /* Apps.json */,
|
BFB1169C22932DB100BB457C /* Apps.json */,
|
||||||
);
|
);
|
||||||
@@ -622,6 +689,7 @@
|
|||||||
children = (
|
children = (
|
||||||
BFD247782284B9A700981D42 /* LaunchScreen.storyboard */,
|
BFD247782284B9A700981D42 /* LaunchScreen.storyboard */,
|
||||||
BFD2477B2284B9A700981D42 /* Info.plist */,
|
BFD2477B2284B9A700981D42 /* Info.plist */,
|
||||||
|
BF1E314722A060F300370A3C /* AltStore-Bridging-Header.h */,
|
||||||
);
|
);
|
||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -646,6 +714,14 @@
|
|||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BFD52BDC22A0A659000B7ED1 /* Connections */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BF1E3129229F474900370A3C /* ConnectionManager.swift */,
|
||||||
|
);
|
||||||
|
path = Connections;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXHeadersBuildPhase section */
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
@@ -694,6 +770,23 @@
|
|||||||
/* End PBXHeadersBuildPhase section */
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
BF1E314F22A0616100370A3C /* AltKit */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = BF1E315422A0616100370A3C /* Build configuration list for PBXNativeTarget "AltKit" */;
|
||||||
|
buildPhases = (
|
||||||
|
BF1E314C22A0616100370A3C /* Sources */,
|
||||||
|
BF1E314D22A0616100370A3C /* Frameworks */,
|
||||||
|
BF1E314E22A0616100370A3C /* CopyFiles */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = AltKit;
|
||||||
|
productName = AltKit;
|
||||||
|
productReference = BF1E315022A0616100370A3C /* libAltKit.a */;
|
||||||
|
productType = "com.apple.product-type.library.static";
|
||||||
|
};
|
||||||
BF45868C229872EA00BD7491 /* AltServer */ = {
|
BF45868C229872EA00BD7491 /* AltServer */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = BF45869A229872EA00BD7491 /* Build configuration list for PBXNativeTarget "AltServer" */;
|
buildConfigurationList = BF45869A229872EA00BD7491 /* Build configuration list for PBXNativeTarget "AltServer" */;
|
||||||
@@ -706,6 +799,7 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
BF1E315E22A0621F00370A3C /* PBXTargetDependency */,
|
||||||
BF4588452298D48B00BD7491 /* PBXTargetDependency */,
|
BF4588452298D48B00BD7491 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = AltServer;
|
name = AltServer;
|
||||||
@@ -719,7 +813,6 @@
|
|||||||
buildPhases = (
|
buildPhases = (
|
||||||
BF4587272298D31600BD7491 /* Headers */,
|
BF4587272298D31600BD7491 /* Headers */,
|
||||||
BF4587282298D31600BD7491 /* Sources */,
|
BF4587282298D31600BD7491 /* Sources */,
|
||||||
BF4587292298D31600BD7491 /* Frameworks */,
|
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -742,6 +835,7 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
BF1E315C22A0621900370A3C /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = AltStore;
|
name = AltStore;
|
||||||
productName = AltStore;
|
productName = AltStore;
|
||||||
@@ -758,6 +852,9 @@
|
|||||||
LastUpgradeCheck = 1020;
|
LastUpgradeCheck = 1020;
|
||||||
ORGANIZATIONNAME = "Riley Testut";
|
ORGANIZATIONNAME = "Riley Testut";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
BF1E314F22A0616100370A3C = {
|
||||||
|
CreatedOnToolsVersion = 10.2.1;
|
||||||
|
};
|
||||||
BF45868C229872EA00BD7491 = {
|
BF45868C229872EA00BD7491 = {
|
||||||
CreatedOnToolsVersion = 10.2.1;
|
CreatedOnToolsVersion = 10.2.1;
|
||||||
LastSwiftMigration = 1020;
|
LastSwiftMigration = 1020;
|
||||||
@@ -772,6 +869,7 @@
|
|||||||
};
|
};
|
||||||
BFD247692284B9A500981D42 = {
|
BFD247692284B9A500981D42 = {
|
||||||
CreatedOnToolsVersion = 10.2.1;
|
CreatedOnToolsVersion = 10.2.1;
|
||||||
|
LastSwiftMigration = 1020;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -790,6 +888,7 @@
|
|||||||
targets = (
|
targets = (
|
||||||
BFD247692284B9A500981D42 /* AltStore */,
|
BFD247692284B9A500981D42 /* AltStore */,
|
||||||
BF45868C229872EA00BD7491 /* AltServer */,
|
BF45868C229872EA00BD7491 /* AltServer */,
|
||||||
|
BF1E314F22A0616100370A3C /* AltKit */,
|
||||||
BF45872A2298D31600BD7491 /* libimobiledevice */,
|
BF45872A2298D31600BD7491 /* libimobiledevice */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -800,7 +899,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BF9B63F6229DE476002F0A62 /* App.ipa in Resources */,
|
BF1E3137229F599C00370A3C /* App.ipa in Resources */,
|
||||||
BF458694229872EA00BD7491 /* Assets.xcassets in Resources */,
|
BF458694229872EA00BD7491 /* Assets.xcassets in Resources */,
|
||||||
BF458697229872EA00BD7491 /* Main.storyboard in Resources */,
|
BF458697229872EA00BD7491 /* Main.storyboard in Resources */,
|
||||||
);
|
);
|
||||||
@@ -811,6 +910,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BFB1169D22932DB100BB457C /* Apps.json in Resources */,
|
BFB1169D22932DB100BB457C /* Apps.json in Resources */,
|
||||||
|
BFD52BDA22A099FA000B7ED1 /* App.ipa in Resources */,
|
||||||
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */,
|
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */,
|
||||||
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */,
|
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */,
|
||||||
BFD247752284B9A500981D42 /* Main.storyboard in Resources */,
|
BFD247752284B9A500981D42 /* Main.storyboard in Resources */,
|
||||||
@@ -820,13 +920,24 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
BF1E314C22A0616100370A3C /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
BF1E315A22A0620000370A3C /* NSError+ALTServerError.m in Sources */,
|
||||||
|
BF1E315922A061FB00370A3C /* Bundle+AltStore.swift in Sources */,
|
||||||
|
BF1E315822A061F900370A3C /* Result+Conveniences.swift in Sources */,
|
||||||
|
BF1E315722A061F500370A3C /* ServerProtocol.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
BF458689229872EA00BD7491 /* Sources */ = {
|
BF458689229872EA00BD7491 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BF458692229872EA00BD7491 /* ViewController.swift in Sources */,
|
BF458692229872EA00BD7491 /* ViewController.swift in Sources */,
|
||||||
|
BF1E312B229F474900370A3C /* ConnectionManager.swift in Sources */,
|
||||||
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */,
|
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */,
|
||||||
BF9B6426229E1331002F0A62 /* Result+Conveniences.swift in Sources */,
|
|
||||||
BF4586C52298CDB800BD7491 /* ALTDeviceManager.mm in Sources */,
|
BF4586C52298CDB800BD7491 /* ALTDeviceManager.mm in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -911,6 +1022,8 @@
|
|||||||
BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */,
|
BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */,
|
||||||
BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */,
|
BFB1169B2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift in Sources */,
|
||||||
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */,
|
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */,
|
||||||
|
BFD52BD422A0800A000B7ED1 /* ServerManager.swift in Sources */,
|
||||||
|
BFD52BD622A08A85000B7ED1 /* Server.swift in Sources */,
|
||||||
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */,
|
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -918,6 +1031,16 @@
|
|||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
BF1E315C22A0621900370A3C /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = BF1E314F22A0616100370A3C /* AltKit */;
|
||||||
|
targetProxy = BF1E315B22A0621900370A3C /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
BF1E315E22A0621F00370A3C /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = BF1E314F22A0616100370A3C /* AltKit */;
|
||||||
|
targetProxy = BF1E315D22A0621F00370A3C /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
BF4588452298D48B00BD7491 /* PBXTargetDependency */ = {
|
BF4588452298D48B00BD7491 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = BF45872A2298D31600BD7491 /* libimobiledevice */;
|
target = BF45872A2298D31600BD7491 /* libimobiledevice */;
|
||||||
@@ -953,6 +1076,38 @@
|
|||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
|
BF1E315522A0616100370A3C /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
|
OTHER_LDFLAGS = "-ObjC";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
BF1E315622A0616100370A3C /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
|
OTHER_LDFLAGS = "-ObjC";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "AltStore/AltStore-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
BF45869B229872EA00BD7491 /* Debug */ = {
|
BF45869B229872EA00BD7491 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@@ -1170,6 +1325,7 @@
|
|||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
};
|
};
|
||||||
@@ -1224,6 +1380,7 @@
|
|||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
@@ -1234,15 +1391,18 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
||||||
INFOPLIST_FILE = AltStore/Info.plist;
|
INFOPLIST_FILE = AltStore/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore;
|
PRODUCT_BUNDLE_IDENTIFIER = com.rileytestut.AltStore;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
@@ -1252,9 +1412,11 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
DEVELOPMENT_TEAM = 6XVY5G3U44;
|
||||||
INFOPLIST_FILE = AltStore/Info.plist;
|
INFOPLIST_FILE = AltStore/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1269,6 +1431,15 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
BF1E315422A0616100370A3C /* Build configuration list for PBXNativeTarget "AltKit" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
BF1E315522A0616100370A3C /* Debug */,
|
||||||
|
BF1E315622A0616100370A3C /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
BF45869A229872EA00BD7491 /* Build configuration list for PBXNativeTarget "AltServer" */ = {
|
BF45869A229872EA00BD7491 /* Build configuration list for PBXNativeTarget "AltServer" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|||||||
5
AltStore/AltStore-Bridging-Header.h
Normal file
5
AltStore/AltStore-Bridging-Header.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSError+ALTServerError.h"
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
import AltSign
|
||||||
|
import Roxas
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
@@ -15,6 +18,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
|
||||||
{
|
{
|
||||||
|
ServerManager.shared.startDiscovering()
|
||||||
|
|
||||||
DatabaseManager.shared.start { (error) in
|
DatabaseManager.shared.start { (error) in
|
||||||
if let error = error
|
if let error = error
|
||||||
{
|
{
|
||||||
@@ -34,13 +39,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
func applicationDidEnterBackground(_ application: UIApplication)
|
||||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
{
|
||||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
ServerManager.shared.stopDiscovering()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
func applicationWillEnterForeground(_ application: UIApplication)
|
||||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
{
|
||||||
|
ServerManager.shared.startDiscovering()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||||
@@ -50,7 +56,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
func applicationWillTerminate(_ application: UIApplication) {
|
func applicationWillTerminate(_ application: UIApplication) {
|
||||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ class AppDetailViewController: UITableViewController
|
|||||||
self.update()
|
self.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool)
|
||||||
|
{
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLayoutSubviews()
|
override func viewDidLayoutSubviews()
|
||||||
{
|
{
|
||||||
super.viewDidLayoutSubviews()
|
super.viewDidLayoutSubviews()
|
||||||
@@ -77,10 +84,19 @@ private extension AppDetailViewController
|
|||||||
self.developerButton.setTitle(self.app.developerName, for: .normal)
|
self.developerButton.setTitle(self.app.developerName, for: .normal)
|
||||||
self.appIconImageView.image = UIImage(named: self.app.iconName)
|
self.appIconImageView.image = UIImage(named: self.app.iconName)
|
||||||
|
|
||||||
let text = String(format: NSLocalizedString("Download %@", comment: ""), self.app.name)
|
|
||||||
self.downloadButton.setTitle(text, for: .normal)
|
|
||||||
|
|
||||||
self.descriptionLabel.text = self.app.localizedDescription
|
self.descriptionLabel.text = self.app.localizedDescription
|
||||||
|
|
||||||
|
if self.app.installedApp == nil
|
||||||
|
{
|
||||||
|
let text = String(format: NSLocalizedString("Download %@", comment: ""), self.app.name)
|
||||||
|
self.downloadButton.setTitle(text, for: .normal)
|
||||||
|
self.downloadButton.isEnabled = true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.downloadButton.setTitle(NSLocalizedString("Installed", comment: ""), for: .normal)
|
||||||
|
self.downloadButton.isEnabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeScreenshotsDataSource() -> RSTArrayCollectionViewDataSource<UIImage>
|
func makeScreenshotsDataSource() -> RSTArrayCollectionViewDataSource<UIImage>
|
||||||
@@ -103,30 +119,69 @@ private extension AppDetailViewController
|
|||||||
{
|
{
|
||||||
guard self.app.installedApp == nil else { return }
|
guard self.app.installedApp == nil else { return }
|
||||||
|
|
||||||
sender.isIndicatingActivity = true
|
let appURL = Bundle.main.url(forResource: "App", withExtension: "ipa")!
|
||||||
|
|
||||||
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
do
|
||||||
let app = context.object(with: self.app.objectID) as! App
|
{
|
||||||
|
try FileManager.default.copyItem(at: appURL, to: self.app.ipaURL, shouldReplace: true)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print("Failed to copy .ipa", error)
|
||||||
|
}
|
||||||
|
|
||||||
_ = InstalledApp(app: app,
|
if let server = ServerManager.shared.discoveredServers.first
|
||||||
bundleIdentifier: app.identifier,
|
{
|
||||||
signedDate: Date(),
|
sender.isIndicatingActivity = true
|
||||||
expirationDate: Date().addingTimeInterval(60 * 60 * 24 * 7),
|
|
||||||
context: context)
|
|
||||||
|
|
||||||
do
|
server.install(self.app) { (result) in
|
||||||
{
|
DispatchQueue.main.async {
|
||||||
try context.save()
|
switch result
|
||||||
}
|
{
|
||||||
catch
|
case .success:
|
||||||
{
|
let toastView = RSTToastView(text: "Installed \(self.app.name)!", detailText: nil)
|
||||||
print("Failed to download app.", error)
|
toastView.tintColor = .altPurple
|
||||||
}
|
toastView.show(in: self.navigationController!.view, duration: 2)
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||||
sender.isIndicatingActivity = false
|
let app = context.object(with: self.app.objectID) as! App
|
||||||
|
|
||||||
|
_ = InstalledApp(app: app,
|
||||||
|
bundleIdentifier: app.identifier,
|
||||||
|
signedDate: Date(),
|
||||||
|
expirationDate: Date().addingTimeInterval(60 * 60 * 24 * 7),
|
||||||
|
context: context)
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try context.save()
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print("Failed to save context for downloaded app app.", error)
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
let toastView = RSTToastView(text: "Failed to install \(self.app.name)", detailText: error.localizedDescription)
|
||||||
|
toastView.tintColor = .altPurple
|
||||||
|
toastView.show(in: self.navigationController!.view, duration: 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.isIndicatingActivity = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let toastView = RSTToastView(text: "Could not find AltServer", detailText: nil)
|
||||||
|
toastView.tintColor = .altPurple
|
||||||
|
toastView.show(in: self.navigationController!.view, duration: 2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,5 +51,7 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>ALTDeviceID</key>
|
||||||
|
<string>1c3416b7b0ab68773e6e7eb7f0d110f7c9353acc</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
|
||||||
@objc(App)
|
@objc(App)
|
||||||
class App: NSManagedObject, Decodable
|
class App: NSManagedObject, Decodable
|
||||||
{
|
{
|
||||||
@@ -77,3 +79,29 @@ extension App
|
|||||||
return NSFetchRequest<App>(entityName: "App")
|
return NSFetchRequest<App>(entityName: "App")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension App
|
||||||
|
{
|
||||||
|
class var appsDirectoryURL: URL {
|
||||||
|
let appsDirectoryURL = FileManager.default.applicationSupportDirectory.appendingPathComponent("Apps")
|
||||||
|
|
||||||
|
do { try FileManager.default.createDirectory(at: appsDirectoryURL, withIntermediateDirectories: true, attributes: nil) }
|
||||||
|
catch { print(error) }
|
||||||
|
|
||||||
|
return appsDirectoryURL
|
||||||
|
}
|
||||||
|
|
||||||
|
var directoryURL: URL {
|
||||||
|
let directoryURL = App.appsDirectoryURL.appendingPathComponent(self.identifier)
|
||||||
|
|
||||||
|
do { try FileManager.default.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil) }
|
||||||
|
catch { print(error) }
|
||||||
|
|
||||||
|
return directoryURL
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipaURL: URL {
|
||||||
|
let ipaURL = self.directoryURL.appendingPathComponent("App.ipa")
|
||||||
|
return ipaURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
256
AltStore/Server/Server.swift
Normal file
256
AltStore/Server/Server.swift
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
//
|
||||||
|
// Server.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Network
|
||||||
|
|
||||||
|
import AltKit
|
||||||
|
|
||||||
|
extension ALTServerError
|
||||||
|
{
|
||||||
|
init<E: Error>(_ error: E)
|
||||||
|
{
|
||||||
|
switch error
|
||||||
|
{
|
||||||
|
case let error as ALTServerError: self = error
|
||||||
|
case is DecodingError: self = ALTServerError(.invalidResponse)
|
||||||
|
case is EncodingError: self = ALTServerError(.invalidRequest)
|
||||||
|
default:
|
||||||
|
assertionFailure("Caught unknown error type")
|
||||||
|
self = ALTServerError(.unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InstallError: Error
|
||||||
|
{
|
||||||
|
case unknown
|
||||||
|
case cancelled
|
||||||
|
case invalidApp
|
||||||
|
case noUDID
|
||||||
|
case server(ALTServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Server: Equatable
|
||||||
|
{
|
||||||
|
var service: NetService
|
||||||
|
|
||||||
|
private let dispatchQueue = DispatchQueue(label: "com.rileytestut.AltStore.server", qos: .utility)
|
||||||
|
|
||||||
|
func install(_ app: App, completionHandler: @escaping (Result<Void, InstallError>) -> Void)
|
||||||
|
{
|
||||||
|
let ipaURL = app.ipaURL
|
||||||
|
let appID = app.identifier
|
||||||
|
|
||||||
|
var isFinished = false
|
||||||
|
|
||||||
|
var serverConnection: NWConnection?
|
||||||
|
|
||||||
|
func finish(error: InstallError?)
|
||||||
|
{
|
||||||
|
// Prevent duplicate callbacks if connection is lost.
|
||||||
|
guard !isFinished else { return }
|
||||||
|
isFinished = true
|
||||||
|
|
||||||
|
if let connection = serverConnection
|
||||||
|
{
|
||||||
|
connection.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let error = error
|
||||||
|
{
|
||||||
|
print("Failed to install \(appID).", error)
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print("Installed \(appID)!")
|
||||||
|
completionHandler(.success(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.connect { (result) in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error): finish(error: error)
|
||||||
|
case .success(let connection):
|
||||||
|
serverConnection = connection
|
||||||
|
|
||||||
|
self.sendApp(at: ipaURL, via: connection) { (result) in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .failure(let error): finish(error: error)
|
||||||
|
case .success:
|
||||||
|
|
||||||
|
self.receiveResponse(from: connection) { (result) in
|
||||||
|
switch result
|
||||||
|
{
|
||||||
|
case .success: finish(error: nil)
|
||||||
|
case .failure(let error): finish(error: .server(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Server
|
||||||
|
{
|
||||||
|
func connect(completionHandler: @escaping (Result<NWConnection, InstallError>) -> Void)
|
||||||
|
{
|
||||||
|
let connection = NWConnection(to: .service(name: self.service.name, type: self.service.type, domain: self.service.domain, interface: nil), using: .tcp)
|
||||||
|
|
||||||
|
connection.stateUpdateHandler = { [weak service, unowned connection] (state) in
|
||||||
|
switch state
|
||||||
|
{
|
||||||
|
case .ready: completionHandler(.success(connection))
|
||||||
|
case .cancelled: completionHandler(.failure(.cancelled))
|
||||||
|
|
||||||
|
case .failed(let error):
|
||||||
|
print("Failed to connect to service \(service?.name ?? "").", error)
|
||||||
|
completionHandler(.failure(.server(.init(.connectionFailed))))
|
||||||
|
|
||||||
|
case .waiting: break
|
||||||
|
case .setup: break
|
||||||
|
case .preparing: break
|
||||||
|
@unknown default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.start(queue: self.dispatchQueue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendApp(at fileURL: URL, via connection: NWConnection, completionHandler: @escaping (Result<Void, InstallError>) -> Void)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
guard let appData = try? Data(contentsOf: fileURL) else { throw InstallError.invalidApp }
|
||||||
|
guard let udid = Bundle.main.object(forInfoDictionaryKey: Bundle.Info.deviceID) as? String else { throw InstallError.noUDID }
|
||||||
|
|
||||||
|
let request = ServerRequest(udid: udid, contentSize: appData.count)
|
||||||
|
let requestData = try JSONEncoder().encode(request)
|
||||||
|
|
||||||
|
let requestSize = Int32(requestData.count)
|
||||||
|
let requestSizeData = withUnsafeBytes(of: requestSize) { Data($0) }
|
||||||
|
|
||||||
|
// Send request data size.
|
||||||
|
connection.send(content: requestSizeData, completion: .contentProcessed { (error) in
|
||||||
|
if error != nil
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.server(.init(.lostConnection))))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send request.
|
||||||
|
connection.send(content: requestData, completion: .contentProcessed { (error) in
|
||||||
|
if error != nil
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.server(.init(.lostConnection))))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send app data.
|
||||||
|
connection.send(content: appData, completion: .contentProcessed { (error) in
|
||||||
|
if error != nil
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.server(.init(.lostConnection))))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionHandler(.success(()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch is EncodingError
|
||||||
|
{
|
||||||
|
completionHandler(.failure(.server(.init(.invalidRequest))))
|
||||||
|
}
|
||||||
|
catch let error as InstallError
|
||||||
|
{
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
assertionFailure("Unknown error type. \(error)")
|
||||||
|
completionHandler(.failure(.unknown))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func receiveResponse(from connection: NWConnection, completionHandler: @escaping (Result<Void, ALTServerError>) -> Void)
|
||||||
|
{
|
||||||
|
let size = MemoryLayout<Int32>.size
|
||||||
|
|
||||||
|
connection.receive(minimumIncompleteLength: size, maximumLength: size) { (data, _, _, error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try self.process(data: data, error: error, from: connection)
|
||||||
|
|
||||||
|
let expectedBytes = Int(data.withUnsafeBytes { $0.load(as: Int32.self) })
|
||||||
|
connection.receive(minimumIncompleteLength: expectedBytes, maximumLength: expectedBytes) { (data, _, _, error) in
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let data = try self.process(data: data, error: error, from: connection)
|
||||||
|
let response = try JSONDecoder().decode(ServerResponse.self, from: data)
|
||||||
|
|
||||||
|
if let error = response.error
|
||||||
|
{
|
||||||
|
completionHandler(.failure(error))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionHandler(.success(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
completionHandler(.failure(ALTServerError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(data: Data?, error: NWError?, from connection: NWConnection) throws -> Data
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
guard let data = data else { throw error ?? ALTServerError(.unknown) }
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
catch let error as NWError
|
||||||
|
{
|
||||||
|
print("Error receiving data from connection \(connection)", error)
|
||||||
|
|
||||||
|
throw ALTServerError(.lostConnection)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch let error as ALTServerError
|
||||||
|
{
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
preconditionFailure("A non-ALTServerError should never be thrown from this method.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
AltStore/Server/ServerManager.swift
Normal file
86
AltStore/Server/ServerManager.swift
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// ServerManager.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/30/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Network
|
||||||
|
|
||||||
|
import AltKit
|
||||||
|
|
||||||
|
class ServerManager: NSObject
|
||||||
|
{
|
||||||
|
static let shared = ServerManager()
|
||||||
|
|
||||||
|
private(set) var isDiscovering = false
|
||||||
|
private(set) var discoveredServers = [Server]()
|
||||||
|
|
||||||
|
private let serviceBrowser = NetServiceBrowser()
|
||||||
|
|
||||||
|
private override init()
|
||||||
|
{
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.serviceBrowser.delegate = self
|
||||||
|
self.serviceBrowser.includesPeerToPeer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ServerManager
|
||||||
|
{
|
||||||
|
func startDiscovering()
|
||||||
|
{
|
||||||
|
guard !self.isDiscovering else { return }
|
||||||
|
self.isDiscovering = true
|
||||||
|
|
||||||
|
self.serviceBrowser.searchForServices(ofType: ALTServerServiceType, inDomain: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopDiscovering()
|
||||||
|
{
|
||||||
|
guard self.isDiscovering else { return }
|
||||||
|
self.isDiscovering = false
|
||||||
|
|
||||||
|
self.discoveredServers.removeAll()
|
||||||
|
self.serviceBrowser.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ServerManager: NetServiceBrowserDelegate
|
||||||
|
{
|
||||||
|
func netServiceBrowserWillSearch(_ browser: NetServiceBrowser)
|
||||||
|
{
|
||||||
|
print("Discovering servers...")
|
||||||
|
}
|
||||||
|
|
||||||
|
func netServiceBrowserDidStopSearch(_ browser: NetServiceBrowser)
|
||||||
|
{
|
||||||
|
print("Stopped discovering servers.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber])
|
||||||
|
{
|
||||||
|
print("Failed to discovering servers.", errorDict)
|
||||||
|
}
|
||||||
|
|
||||||
|
func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool)
|
||||||
|
{
|
||||||
|
let server = Server(service: service)
|
||||||
|
guard !self.discoveredServers.contains(server) else { return }
|
||||||
|
|
||||||
|
self.discoveredServers.append(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool)
|
||||||
|
{
|
||||||
|
let server = Server(service: service)
|
||||||
|
|
||||||
|
if let index = self.discoveredServers.firstIndex(of: server)
|
||||||
|
{
|
||||||
|
self.discoveredServers.remove(at: index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user