Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge MAS version into master #58

Merged
merged 10 commits into from
Oct 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build/*
*Library/*
*xcuserdata*
InjectionIII *
150 changes: 139 additions & 11 deletions InjectionBundle/InjectionClient.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,61 @@
#import "InjectionServer.h"

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __has_include("tvOSInjection-Swift.h")
#if __has_include("tvOSInjection10-Swift.h")
#import "tvOSInjection10-Swift.h"
#elif __has_include("tvOSInjection-Swift.h")
#import "tvOSInjection-Swift.h"
#else
#if __has_include("iOSInjection10-Swift.h")
#import "iOSInjection10-Swift.h"
#else
#import "iOSInjection-Swift.h"
#endif
#import <UIKit/UIKit.h>

@implementation NSObject (Remapper)

static struct {
NSMutableDictionary *inputIndexes;
NSMutableArray *output, *order;
int orderIndex;
} remapper;

+ (void)my_addMappingFromIdentifier:(NSString *)identifier toObject:(id)object forCoder:(id)coder {
//NSLog(@"Map %@ = %@", identifier, object);
if(remapper.output && [identifier hasPrefix:@"UpstreamPlaceholder-"]) {
if (remapper.inputIndexes)
remapper.inputIndexes[identifier] = @([remapper.inputIndexes count]);
else
[remapper.output addObject:object];
}
[self my_addMappingFromIdentifier:identifier toObject:object forCoder:coder];
}

+ (id)my_mappedObjectForCoder:(id)decoder withIdentifier:(NSString *)identifier {
//NSLog(@"Mapped? %@", identifier);
if(remapper.output && [identifier hasPrefix:@"UpstreamPlaceholder-"]) {
if (remapper.inputIndexes)
[remapper.order addObject:remapper.inputIndexes[identifier] ?: @""];
else
return remapper.output[[remapper.order[remapper.orderIndex++] intValue]];
}
return [self my_mappedObjectForCoder:decoder withIdentifier:identifier];
}

@end

@interface UIViewController (StoryboardInjection)
- (void)_loadViewFromNibNamed:(NSString *)a0 bundle:(NSBundle *)a1;
@end
#endif
#else
#if __has_include("macOSInjection10-Swift.h")
#import "macOSInjection10-Swift.h"
#else
#import "macOSInjection-Swift.h"
#endif
#endif

#ifdef XPROBE_PORT
#import "../XprobePlugin/Classes/Xtrace.mm"
Expand Down Expand Up @@ -64,9 +111,10 @@ + (void)load {
}

- (void)runInBackground {
NSString *projectFile = [self readString];
printf("Injection connected, watching %s/...\n",
projectFile.stringByDeletingLastPathComponent.UTF8String);
[SwiftEval sharedInstance].tmpDir = [self readString];
[SwiftEval sharedInstance].injectionNumber = 100;

[self writeString:INJECTION_KEY];
[self writeString:[NSBundle mainBundle].privateFrameworksPath];
#ifdef __LP64__
[self writeString:@"x86_64"];
Expand All @@ -75,9 +123,6 @@ - (void)runInBackground {
#endif
[self writeString:[NSBundle mainBundle].executablePath];

[SwiftEval sharedInstance].projectFile = projectFile;
[SwiftEval sharedInstance].injectionNumber = 100;

int codesignStatusPipe[2];
pipe(codesignStatusPipe);
SimpleSocket *reader = [[SimpleSocket alloc] initSocket:codesignStatusPipe[0]];
Expand All @@ -91,15 +136,98 @@ - (void)runInBackground {

// As tmp file names come in, inject them
while (NSString *swiftSource = [self readString])
if ([swiftSource hasPrefix:@"LOG "])
if ([swiftSource hasPrefix:@"PROJECT "]) {
NSString *projectFile = [swiftSource substringFromIndex:@"PROJECT ".length];
[SwiftEval sharedInstance].projectFile = projectFile;
[SwiftEval sharedInstance].derivedLogs = nil;
printf("Injection connected, watching %s/**\n",
projectFile.stringByDeletingLastPathComponent.UTF8String);
}
else if ([swiftSource hasPrefix:@"LOG "])
printf("%s\n", [swiftSource substringFromIndex:@"LOG ".length].UTF8String);
else if ([swiftSource hasPrefix:@"SIGNED "])
[writer writeString:[swiftSource substringFromIndex:@"SIGNED ".length]];
else
dispatch_async(dispatch_get_main_queue(), ^{
NSError *err;
if ([swiftSource hasPrefix:@"INJECT "])
[SwiftInjection injectWithTmpfile:[swiftSource substringFromIndex:@"INJECT ".length] error:&err];
NSError *err = nil;
if ([swiftSource hasPrefix:@"LOAD "])
[SwiftInjection injectWithTmpfile:[swiftSource substringFromIndex:@"LOAD ".length] error:&err];
else if ([swiftSource hasPrefix:@"INJECT "]) {
NSString *changed = [swiftSource substringFromIndex:@"INJECT ".length];
#if __has_include("iOSInjection-Swift.h") || __has_include("iOSInjection10-Swift.h")
if ([changed hasSuffix:@"storyboard"] || [changed hasSuffix:@"xib"]) {
static NSMutableDictionary *allOrder;
static dispatch_once_t once;

dispatch_once(&once, ^{
Class proxyClass = objc_getClass("UIProxyObject");
method_exchangeImplementations(
class_getClassMethod(proxyClass,
@selector(my_addMappingFromIdentifier:toObject:forCoder:)),
class_getClassMethod(proxyClass,
@selector(addMappingFromIdentifier:toObject:forCoder:)));
method_exchangeImplementations(
class_getClassMethod(proxyClass,
@selector(my_mappedObjectForCoder:withIdentifier:)),
class_getClassMethod(proxyClass,
@selector(mappedObjectForCoder:withIdentifier:)));
allOrder = [NSMutableDictionary new];
});

@try {
UIViewController *visibleVC = [UIApplication sharedApplication]
.windows.firstObject.rootViewController;
if (UIViewController *child =
visibleVC.childViewControllers.firstObject)
visibleVC = child;
if ([visibleVC respondsToSelector:@selector(viewControllers)])
visibleVC = [(UISplitViewController *)visibleVC
viewControllers].lastObject;
if ([visibleVC respondsToSelector:@selector(visibleViewController)])
visibleVC = [(UINavigationController *)visibleVC
visibleViewController];

NSString *nibName = visibleVC.nibName;

if (!(remapper.order = allOrder[nibName])) {
remapper.inputIndexes = [NSMutableDictionary new];
remapper.output = [NSMutableArray new];
allOrder[nibName] = remapper.order = [NSMutableArray new];

[visibleVC _loadViewFromNibNamed:visibleVC.nibName
bundle:visibleVC.nibBundle];

remapper.inputIndexes = nil;
remapper.output = nil;
}

[[SwiftEval sharedInstance] rebuildWithStoryboard:changed error:&err];
if (err)
return;

remapper.output = [NSMutableArray new];
remapper.orderIndex = 0;

[visibleVC _loadViewFromNibNamed:visibleVC.nibName
bundle:visibleVC.nibBundle];
[visibleVC viewDidLoad];
[visibleVC viewWillAppear:NO];
[visibleVC viewDidAppear:NO];

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
[SwiftInjection flash:visibleVC];
#endif
}
@catch(NSException *e) {
printf("Problem reloading nib: %s\n", e.reason.UTF8String);
}

remapper.output = nil;
}
else
#endif
[SwiftInjection injectWithOldClass:nil classNameOrFile:changed];
}
#ifdef XPROBE_PORT
else if ([swiftSource hasPrefix:@"XPROBE"]) {
[Xprobe connectTo:NULL retainObjects:YES];
Expand Down
Loading