mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-19 03:33:36 +01:00
[AltServer] Adds ALTDebugConnection to “debug” sideloaded apps
Allows AltServer to programmatically enable JIT execution in sideloaded apps.
This commit is contained in:
28
AltServer/Connections/ALTDebugConnection+Private.h
Normal file
28
AltServer/Connections/ALTDebugConnection+Private.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// ALTDebugConnection+Private.h
|
||||||
|
// AltServer
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 2/19/21.
|
||||||
|
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ALTDebugConnection.h"
|
||||||
|
|
||||||
|
#include <libimobiledevice/libimobiledevice.h>
|
||||||
|
#include <libimobiledevice/debugserver.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface ALTDebugConnection ()
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) dispatch_queue_t connectionQueue;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable) debugserver_client_t client;
|
||||||
|
|
||||||
|
- (instancetype)initWithDevice:(ALTDevice *)device;
|
||||||
|
|
||||||
|
- (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
24
AltServer/Connections/ALTDebugConnection.h
Normal file
24
AltServer/Connections/ALTDebugConnection.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// ALTDebugConnection.h
|
||||||
|
// AltServer
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 2/19/21.
|
||||||
|
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AltSign.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
NS_SWIFT_NAME(DebugConnection)
|
||||||
|
@interface ALTDebugConnection : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, copy, readonly) ALTDevice *device;
|
||||||
|
|
||||||
|
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler;
|
||||||
|
|
||||||
|
- (void)disconnect;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
249
AltServer/Connections/ALTDebugConnection.mm
Normal file
249
AltServer/Connections/ALTDebugConnection.mm
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
//
|
||||||
|
// ALTDebugConnection.m
|
||||||
|
// AltServer
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 2/19/21.
|
||||||
|
// Copyright © 2021 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ALTDebugConnection+Private.h"
|
||||||
|
|
||||||
|
#import "NSError+ALTServerError.h"
|
||||||
|
#import "NSError+libimobiledevice.h"
|
||||||
|
|
||||||
|
char *bin2hex(const unsigned char *bin, size_t length)
|
||||||
|
{
|
||||||
|
if (bin == NULL || length == 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *hex = (char *)malloc(length * 2 + 1);
|
||||||
|
for (size_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
hex[i * 2] = "0123456789ABCDEF"[bin[i] >> 4];
|
||||||
|
hex[i * 2 + 1] = "0123456789ABCDEF"[bin[i] & 0x0F];
|
||||||
|
}
|
||||||
|
hex[length * 2] = '\0';
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation ALTDebugConnection
|
||||||
|
|
||||||
|
- (instancetype)initWithDevice:(ALTDevice *)device
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
_device = device;
|
||||||
|
_connectionQueue = dispatch_queue_create_with_target("io.altstore.AltServer.DebugConnection",
|
||||||
|
DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL,
|
||||||
|
dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[self disconnect];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)disconnect
|
||||||
|
{
|
||||||
|
if (_client == nil)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugserver_client_free(_client);
|
||||||
|
_client = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)connectWithCompletionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
||||||
|
{
|
||||||
|
__block idevice_t device = NULL;
|
||||||
|
|
||||||
|
void (^finish)(BOOL, NSError *) = ^(BOOL success, NSError *error) {
|
||||||
|
if (device)
|
||||||
|
{
|
||||||
|
idevice_free(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
completionHandler(success, error);
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch_async(self.connectionQueue, ^{
|
||||||
|
/* Find Device */
|
||||||
|
if (idevice_new_with_options(&device, self.device.identifier.UTF8String, (enum idevice_options)((int)IDEVICE_LOOKUP_NETWORK | (int)IDEVICE_LOOKUP_USBMUX)) != IDEVICE_E_SUCCESS)
|
||||||
|
{
|
||||||
|
return finish(NO, [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorDeviceNotFound userInfo:nil]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect to debugserver */
|
||||||
|
debugserver_client_t client = NULL;
|
||||||
|
debugserver_error_t error = debugserver_client_start_service(device, &client, "AltServer");
|
||||||
|
if (error != DEBUGSERVER_E_SUCCESS)
|
||||||
|
{
|
||||||
|
return finish(NO, [NSError errorWithDebugServerError:error device:self.device]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client = client;
|
||||||
|
|
||||||
|
finish(YES, nil);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler
|
||||||
|
{
|
||||||
|
dispatch_async(self.connectionQueue, ^{
|
||||||
|
NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"JIT could not be enabled for %@.", comment: @""), processName];
|
||||||
|
|
||||||
|
NSString *encodedName = @(bin2hex((const unsigned char *)processName.UTF8String, (size_t)strlen(processName.UTF8String)));
|
||||||
|
NSString *attachCommand = [NSString stringWithFormat:@"vAttachName;%@", encodedName];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
if (![self sendCommand:attachCommand arguments:nil error:&error])
|
||||||
|
{
|
||||||
|
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||||||
|
userInfo[ALTAppNameErrorKey] = processName;
|
||||||
|
userInfo[ALTDeviceNameErrorKey] = self.device.name;
|
||||||
|
userInfo[NSLocalizedFailureErrorKey] = localizedFailure;
|
||||||
|
|
||||||
|
NSError *returnError = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||||
|
return completionHandler(NO, returnError);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *detachCommand = @"D";
|
||||||
|
if (![self sendCommand:detachCommand arguments:nil error:&error])
|
||||||
|
{
|
||||||
|
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||||||
|
userInfo[ALTAppNameErrorKey] = processName;
|
||||||
|
userInfo[ALTDeviceNameErrorKey] = self.device.name;
|
||||||
|
userInfo[NSLocalizedFailureErrorKey] = localizedFailure;
|
||||||
|
|
||||||
|
NSError *returnError = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
|
||||||
|
return completionHandler(NO, returnError);
|
||||||
|
}
|
||||||
|
|
||||||
|
completionHandler(YES, nil);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private -
|
||||||
|
|
||||||
|
- (BOOL)sendCommand:(NSString *)command arguments:(nullable NSArray<NSString *> *)arguments error:(NSError **)error
|
||||||
|
{
|
||||||
|
int argc = (int)arguments.count;
|
||||||
|
char **argv = new char*[argc + 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
NSString *argument = arguments[i];
|
||||||
|
argv[i] = (char *)argument.UTF8String;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
debugserver_command_t debugCommand = NULL;
|
||||||
|
debugserver_command_new(command.UTF8String, argc, argv, &debugCommand);
|
||||||
|
|
||||||
|
delete[] argv;
|
||||||
|
|
||||||
|
char *response = NULL;
|
||||||
|
size_t responseSize = 0;
|
||||||
|
debugserver_error_t debugServerError = debugserver_client_send_command(self.client, debugCommand, &response, &responseSize);
|
||||||
|
debugserver_command_free(debugCommand);
|
||||||
|
|
||||||
|
if (debugServerError != DEBUGSERVER_E_SUCCESS)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
*error = [NSError errorWithDebugServerError:debugServerError device:self.device];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![self processResponse:@(response) error:error])
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)processResponse:(NSString *)rawResponse error:(NSError **)error
|
||||||
|
{
|
||||||
|
if (rawResponse.length == 0 || [rawResponse isEqualToString:@"OK"])
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
char type = [rawResponse characterAtIndex:0];
|
||||||
|
NSString *response = [rawResponse substringFromIndex:1];
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 'O':
|
||||||
|
{
|
||||||
|
// stdout/stderr
|
||||||
|
|
||||||
|
char *decodedResponse = NULL;
|
||||||
|
debugserver_decode_string(response.UTF8String, response.length, &decodedResponse);
|
||||||
|
|
||||||
|
NSLog(@"Response: %@", @(decodedResponse));
|
||||||
|
|
||||||
|
if (decodedResponse)
|
||||||
|
{
|
||||||
|
free(decodedResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
{
|
||||||
|
// Thread Information
|
||||||
|
|
||||||
|
NSLog(@"Thread stopped. Details:\n%s", response.UTF8String + 1);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
{
|
||||||
|
// Error
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
NSInteger errorCode = [[[response componentsSeparatedByString:@";"] firstObject] integerValue];
|
||||||
|
|
||||||
|
switch (errorCode)
|
||||||
|
{
|
||||||
|
case 96:
|
||||||
|
*error = [NSError errorWithDomain:AltServerErrorDomain code:ALTServerErrorRequestedAppNotRunning userInfo:nil];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*error = [NSError errorWithDomain:AltServerConnectionErrorDomain code:ALTServerConnectionErrorUnknown userInfo:@{NSLocalizedFailureReasonErrorKey: response}];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'W':
|
||||||
|
{
|
||||||
|
// Warning
|
||||||
|
|
||||||
|
NSLog(@"WARNING: %@", response);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
@class ALTWiredConnection;
|
@class ALTWiredConnection;
|
||||||
@class ALTNotificationConnection;
|
@class ALTNotificationConnection;
|
||||||
|
@class ALTDebugConnection;
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ extern NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification
|
|||||||
/* Connections */
|
/* Connections */
|
||||||
- (void)startWiredConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTWiredConnection *_Nullable connection, NSError *_Nullable error))completionHandler;
|
- (void)startWiredConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTWiredConnection *_Nullable connection, NSError *_Nullable error))completionHandler;
|
||||||
- (void)startNotificationConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTNotificationConnection *_Nullable connection, NSError *_Nullable error))completionHandler;
|
- (void)startNotificationConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTNotificationConnection *_Nullable connection, NSError *_Nullable error))completionHandler;
|
||||||
|
- (void)startDebugConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTDebugConnection *_Nullable connection, NSError * _Nullable error))completionHandler;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#import "ALTWiredConnection+Private.h"
|
#import "ALTWiredConnection+Private.h"
|
||||||
#import "ALTNotificationConnection+Private.h"
|
#import "ALTNotificationConnection+Private.h"
|
||||||
|
#import "ALTDebugConnection+Private.h"
|
||||||
|
|
||||||
#import "ALTConstants.h"
|
#import "ALTConstants.h"
|
||||||
#import "NSError+ALTServerError.h"
|
#import "NSError+ALTServerError.h"
|
||||||
@@ -1277,6 +1278,20 @@ NSNotificationName const ALTDeviceManagerDeviceDidDisconnectNotification = @"ALT
|
|||||||
completionHandler(notificationConnection, nil);
|
completionHandler(notificationConnection, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)startDebugConnectionToDevice:(ALTDevice *)device completionHandler:(void (^)(ALTDebugConnection * _Nullable, NSError * _Nullable))completionHandler
|
||||||
|
{
|
||||||
|
ALTDebugConnection *connection = [[ALTDebugConnection alloc] initWithDevice:device];
|
||||||
|
[connection connectWithCompletionHandler:^(BOOL success, NSError * _Nullable error) {
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
completionHandler(connection, nil);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionHandler(nil, error);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
#pragma mark - Getters -
|
#pragma mark - Getters -
|
||||||
|
|
||||||
- (NSArray<ALTDevice *> *)connectedDevices
|
- (NSArray<ALTDevice *> *)connectedDevices
|
||||||
|
|||||||
@@ -212,6 +212,7 @@
|
|||||||
BF9ABA4D22DD16DE008935CF /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9ABA4C22DD16DE008935CF /* PillButton.swift */; };
|
BF9ABA4D22DD16DE008935CF /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9ABA4C22DD16DE008935CF /* PillButton.swift */; };
|
||||||
BFA8172923C56042001B5953 /* ServerConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172823C56042001B5953 /* ServerConnection.swift */; };
|
BFA8172923C56042001B5953 /* ServerConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172823C56042001B5953 /* ServerConnection.swift */; };
|
||||||
BFA8172B23C5633D001B5953 /* FetchAnisetteDataOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */; };
|
BFA8172B23C5633D001B5953 /* FetchAnisetteDataOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */; };
|
||||||
|
BFAD678E25E0649500D4C4D1 /* ALTDebugConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = BFAD678D25E0649500D4C4D1 /* ALTDebugConnection.mm */; };
|
||||||
BFAD67A325E0854500D4C4D1 /* DeveloperDiskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAD67A225E0854500D4C4D1 /* DeveloperDiskManager.swift */; };
|
BFAD67A325E0854500D4C4D1 /* DeveloperDiskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFAD67A225E0854500D4C4D1 /* DeveloperDiskManager.swift */; };
|
||||||
BFAECC522501B0A400528F27 /* CodableServerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD44605241188C300EAB90A /* CodableServerError.swift */; };
|
BFAECC522501B0A400528F27 /* CodableServerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD44605241188C300EAB90A /* CodableServerError.swift */; };
|
||||||
BFAECC532501B0A400528F27 /* ServerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3128229F474900370A3C /* ServerProtocol.swift */; };
|
BFAECC532501B0A400528F27 /* ServerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1E3128229F474900370A3C /* ServerProtocol.swift */; };
|
||||||
@@ -679,6 +680,9 @@
|
|||||||
BF9ABA4C22DD16DE008935CF /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
BF9ABA4C22DD16DE008935CF /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
||||||
BFA8172823C56042001B5953 /* ServerConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnection.swift; sourceTree = "<group>"; };
|
BFA8172823C56042001B5953 /* ServerConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnection.swift; sourceTree = "<group>"; };
|
||||||
BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchAnisetteDataOperation.swift; sourceTree = "<group>"; };
|
BFA8172A23C5633D001B5953 /* FetchAnisetteDataOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchAnisetteDataOperation.swift; sourceTree = "<group>"; };
|
||||||
|
BFAD678C25E0649500D4C4D1 /* ALTDebugConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALTDebugConnection.h; sourceTree = "<group>"; };
|
||||||
|
BFAD678D25E0649500D4C4D1 /* ALTDebugConnection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ALTDebugConnection.mm; sourceTree = "<group>"; };
|
||||||
|
BFAD679525E064D400D4C4D1 /* ALTDebugConnection+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ALTDebugConnection+Private.h"; sourceTree = "<group>"; };
|
||||||
BFAD67A225E0854500D4C4D1 /* DeveloperDiskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperDiskManager.swift; sourceTree = "<group>"; };
|
BFAD67A225E0854500D4C4D1 /* DeveloperDiskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperDiskManager.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>"; };
|
||||||
BFB364592325985F00CD0EB1 /* FindServerOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindServerOperation.swift; sourceTree = "<group>"; };
|
BFB364592325985F00CD0EB1 /* FindServerOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindServerOperation.swift; sourceTree = "<group>"; };
|
||||||
@@ -1566,6 +1570,9 @@
|
|||||||
BF718BD323C928A300A89F2D /* ALTNotificationConnection.h */,
|
BF718BD323C928A300A89F2D /* ALTNotificationConnection.h */,
|
||||||
BF718BD623C92B3700A89F2D /* ALTNotificationConnection+Private.h */,
|
BF718BD623C92B3700A89F2D /* ALTNotificationConnection+Private.h */,
|
||||||
BF718BD423C928A300A89F2D /* ALTNotificationConnection.mm */,
|
BF718BD423C928A300A89F2D /* ALTNotificationConnection.mm */,
|
||||||
|
BFAD678C25E0649500D4C4D1 /* ALTDebugConnection.h */,
|
||||||
|
BFAD679525E064D400D4C4D1 /* ALTDebugConnection+Private.h */,
|
||||||
|
BFAD678D25E0649500D4C4D1 /* ALTDebugConnection.mm */,
|
||||||
);
|
);
|
||||||
path = Connections;
|
path = Connections;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -2288,6 +2295,7 @@
|
|||||||
BF718BD523C928A300A89F2D /* ALTNotificationConnection.mm in Sources */,
|
BF718BD523C928A300A89F2D /* ALTNotificationConnection.mm in Sources */,
|
||||||
BF1E312B229F474900370A3C /* RequestHandler.swift in Sources */,
|
BF1E312B229F474900370A3C /* RequestHandler.swift in Sources */,
|
||||||
BF718BD123C91BD300A89F2D /* ALTWiredConnection.mm in Sources */,
|
BF718BD123C91BD300A89F2D /* ALTWiredConnection.mm in Sources */,
|
||||||
|
BFAD678E25E0649500D4C4D1 /* ALTDebugConnection.mm in Sources */,
|
||||||
BFECAC8524FD950B0077C41F /* Connection.swift in Sources */,
|
BFECAC8524FD950B0077C41F /* Connection.swift in Sources */,
|
||||||
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */,
|
BF458690229872EA00BD7491 /* AppDelegate.swift in Sources */,
|
||||||
BFECAC8424FD950B0077C41F /* ALTConstants.m in Sources */,
|
BFECAC8424FD950B0077C41F /* ALTConstants.m in Sources */,
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ typedef NS_ERROR_ENUM(AltServerErrorDomain, ALTServerError)
|
|||||||
ALTServerErrorProfileNotFound = 15,
|
ALTServerErrorProfileNotFound = 15,
|
||||||
|
|
||||||
ALTServerErrorAppDeletionFailed = 16,
|
ALTServerErrorAppDeletionFailed = 16,
|
||||||
|
|
||||||
|
ALTServerErrorRequestedAppNotRunning = 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NS_ERROR_ENUM(AltServerConnectionErrorDomain, ALTServerConnectionError)
|
typedef NS_ERROR_ENUM(AltServerConnectionErrorDomain, ALTServerConnectionError)
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ NSErrorUserInfoKey const ALTDeviceNameErrorKey = @"deviceName";
|
|||||||
|
|
||||||
case ALTServerErrorAppDeletionFailed:
|
case ALTServerErrorAppDeletionFailed:
|
||||||
return NSLocalizedString(@"An error occured while removing the app.", @"");
|
return NSLocalizedString(@"An error occured while removing the app.", @"");
|
||||||
|
|
||||||
|
case ALTServerErrorRequestedAppNotRunning:
|
||||||
|
{
|
||||||
|
NSString *appName = self.userInfo[ALTAppNameErrorKey] ?: NSLocalizedString(@"The requested app", @"");
|
||||||
|
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"the device", @"");
|
||||||
|
return [NSString stringWithFormat:NSLocalizedString(@"%@ is not currently running on %@.", ""), appName, deviceName];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +148,12 @@ NSErrorUserInfoKey const ALTDeviceNameErrorKey = @"deviceName";
|
|||||||
case ALTServerErrorMaximumFreeAppLimitReached:
|
case ALTServerErrorMaximumFreeAppLimitReached:
|
||||||
return NSLocalizedString(@"Make sure “Offload Unused Apps” is disabled in Settings > iTunes & App Stores, then install or delete all offloaded apps.", @"");
|
return NSLocalizedString(@"Make sure “Offload Unused Apps” is disabled in Settings > iTunes & App Stores, then install or delete all offloaded apps.", @"");
|
||||||
|
|
||||||
|
case ALTServerErrorRequestedAppNotRunning:
|
||||||
|
{
|
||||||
|
NSString *deviceName = self.userInfo[ALTDeviceNameErrorKey] ?: NSLocalizedString(@"your device", @"");
|
||||||
|
return [NSString stringWithFormat:NSLocalizedString(@"Make sure the app is running in the foreground on %@ then try again.", @""), deviceName];
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user