Skip to content

Commit

Permalink
Merge pull request Polidea#5 from marcinkiewiczblazej/pods-support
Browse files Browse the repository at this point in the history
CocoaPods obfuscation
  • Loading branch information
ayufan committed Aug 5, 2014
2 parents 3772be5 + 0680132 commit e548e76
Show file tree
Hide file tree
Showing 20 changed files with 515 additions and 42 deletions.
4 changes: 2 additions & 2 deletions CDCoreDataModelParser.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#import <Foundation/Foundation.h>
#import "CDParserSharedBase.h"
#import "CDXMLParserSharedBase.h"

@class GDataXMLElement;


@interface CDCoreDataModelParser : CDParserSharedBase
@interface CDCoreDataModelParser : CDXMLParserSharedBase
@end
2 changes: 1 addition & 1 deletion CDParserSharedBase.h → CDXMLParserSharedBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

@class GDataXMLElement;

@interface CDParserSharedBase : NSObject
@interface CDXMLParserSharedBase : NSObject
- (NSArray *)symbolsInData:(NSData *)data;

- (NSData *)obfuscatedXmlData:(NSData *)data symbols:(NSDictionary *)symbols;
Expand Down
4 changes: 2 additions & 2 deletions CDParserSharedBase.m → CDXMLParserSharedBase.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#import "CDParserSharedBase.h"
#import "CDXMLParserSharedBase.h"
#import "GDataXMLNode.h"


@implementation CDParserSharedBase
@implementation CDXMLParserSharedBase

- (NSArray *)symbolsInData:(NSData *)data {
NSMutableArray *array = [NSMutableArray array];
Expand Down
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ PODS:
- Kiwi/NonARC

DEPENDENCIES:
- Kiwi/XCTest
- Kiwi/XCTest (~> 2.2.0)

SPEC CHECKSUMS:
Kiwi: c73667f2b84cbf36f1a3830267c5a4ae8dcbd8ba
Expand Down
8 changes: 8 additions & 0 deletions Pods support/CDPbxProjectParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import <Foundation/Foundation.h>


@interface CDPbxProjectParser : NSObject

- (instancetype)initWithJsonDictionary:(NSDictionary *)project;
- (NSSet *)findTargets;
@end
74 changes: 74 additions & 0 deletions Pods support/CDPbxProjectParser.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#import "CDPbxProjectParser.h"
#import "CDPbxProjectTarget.h"


@interface CDPbxProjectParser ()
@property(nonatomic, strong) NSDictionary *project;
@end

@implementation CDPbxProjectParser {

}
- (instancetype)initWithJsonDictionary:(NSDictionary *)project {
self = [self init];
if (self) {
self.project = project;
}
return self;
}

- (NSSet *)findTargets {
__weak CDPbxProjectParser *weakSelf = self;
NSMutableSet *targets = [NSMutableSet set];
[self iterateBuildConfigurationsWithBlock:^(NSString *targetName, NSDictionary *buildConfiguration) {
NSDictionary *buildSettings = buildConfiguration[@"buildSettings"];
NSString *prefixHeaderName = buildSettings[@"GCC_PREFIX_HEADER"];

NSDictionary *baseConfiguration = [weakSelf getObjectWithHash:buildConfiguration[@"baseConfigurationReference"]];
NSString *configFileName = baseConfiguration[@"path"];

[targets addObject:[[CDPbxProjectTarget alloc] initWithTargetName:targetName precompiledHeaderName:prefixHeaderName configurationFile:configFileName]];

}];

return targets;
}

#pragma mark - helpers

- (void)iterateBuildConfigurationsWithBlock:(void (^)(NSString *, NSDictionary *))iterationBlock {
__weak CDPbxProjectParser *weakSelf = self;
[self iterateTargetsWithBlock:^(NSDictionary *target) {
NSDictionary *buildConfigurationList = [weakSelf getObjectWithHash:target[@"buildConfigurationList"]];
NSArray *buildConfigurations = buildConfigurationList[@"buildConfigurations"];
for (NSString *buildConfigurationHash in buildConfigurations) {
NSDictionary *buildConfiguration = [weakSelf getObjectWithHash:buildConfigurationHash];
if (iterationBlock) {
iterationBlock(target[@"name"], buildConfiguration);
} else {
break;
}
}
}];
}

- (void)iterateTargetsWithBlock:(void (^)(NSDictionary *))iterationBlock {
NSString *rootObjectHash = self.project[@"rootObject"];
NSDictionary *rootObject = [self getObjectWithHash:rootObjectHash];
NSArray *targetsHashArray = rootObject[@"targets"];

for (NSString *targetHash in targetsHashArray) {
if (iterationBlock) {
NSDictionary *target = [self getObjectWithHash:targetHash];
iterationBlock(target);
} else {
break;
}
}
}

- (id)getObjectWithHash:(NSString *)hash {
return self.project[@"objects"][hash];
}

@end
6 changes: 6 additions & 0 deletions Pods support/CDPbxProjectProcessor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#import <Foundation/Foundation.h>


@interface CDPbxProjectProcessor : NSObject
- (void)processPodsProjectAtPath:(NSString *)podsPath symbolsFilePath:(NSString *)symbolsPath;
@end
40 changes: 40 additions & 0 deletions Pods support/CDPbxProjectProcessor.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#import "CDPbxProjectProcessor.h"
#import "CDPbxProjectParser.h"
#import "CDPbxProjectTarget.h"
#import "CDPodsFileProcessor.h"

@interface CDPbxProjectProcessor ()
@property(nonatomic, strong) NSPipe *outputPipe;
@end

@implementation CDPbxProjectProcessor {

}

- (void)processPodsProjectAtPath:(NSString *)podsPath symbolsFilePath:(NSString *)symbolsPath {
NSTask *task = [[NSTask alloc] init];
task.launchPath = @"/usr/bin/plutil";
task.arguments = @[@"-convert", @"json", podsPath, @"-o", @"-"];

self.outputPipe = [[NSPipe alloc] init];
task.standardOutput = self.outputPipe;
[[self.outputPipe fileHandleForReading] readToEndOfFileInBackgroundAndNotify];

[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleReadToEndOfFileCompletionNotification object:[self.outputPipe fileHandleForReading] queue:nil usingBlock:^(NSNotification *notification){
NSData *output = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
NSDictionary *projectJSON = [NSJSONSerialization JSONObjectWithData:output options:0 error:nil];
CDPbxProjectParser *parser = [[CDPbxProjectParser alloc] initWithJsonDictionary:projectJSON];
NSSet *targets = [parser findTargets];
CDPodsFileProcessor *processor = [[CDPodsFileProcessor alloc] init];
for (CDPbxProjectTarget *target in targets) {
[processor processTarget:target symbolsFilePath:symbolsPath];
}
}];

[task launch];

[task waitUntilExit];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
14 changes: 14 additions & 0 deletions Pods support/CDPbxProjectTarget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#import <Foundation/Foundation.h>


@interface CDPbxProjectTarget : NSObject

@property(nonatomic, readonly) NSString *targetName;

@property(nonatomic, readonly) NSString *headerName;

@property(nonatomic, readonly) NSString *configFile;

- (instancetype)initWithTargetName:(NSString *)targetName precompiledHeaderName:(NSString *)precompiledHeader configurationFile:(NSString *)configurationFile;

@end
48 changes: 48 additions & 0 deletions Pods support/CDPbxProjectTarget.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#import "CDPbxProjectTarget.h"


@interface CDPbxProjectTarget ()
@property(nonatomic, readwrite) NSString *targetName;
@property(nonatomic, readwrite) NSString *headerName;
@property(nonatomic, readwrite) NSString *configFile;
@end

@implementation CDPbxProjectTarget {

}
- (instancetype)initWithTargetName:(NSString *)targetName precompiledHeaderName:(NSString *)precompiledHeader configurationFile:(NSString *)configurationFile {
self = [self init];
if (self) {
self.targetName = targetName;
self.headerName = precompiledHeader;
self.configFile = configurationFile;
}
return self;
}

- (BOOL)isEqual:(id)other {
if ([other isKindOfClass:[self class]]) {
CDPbxProjectTarget *otherTarget = other;
if ([otherTarget.targetName ?: @"" isEqualToString:self.targetName ?: @""] &&
[otherTarget.headerName ?: @"" isEqualToString:self.headerName ?: @""] &&
[otherTarget.configFile ?: @"" isEqualToString:self.configFile ?: @""]) {
return YES;
} else {
return NO;
}
}
return [super isEqual:other];
}

- (NSUInteger)hash {
NSString *string = [NSString stringWithFormat:@"%@_%@_%@", self.targetName, self.configFile, self.headerName];
return [string hash]; //Must be a unique unsigned integer
}

- (NSString *)debugDescription {

return [NSString stringWithFormat:@"<CDPbxProjectTarget target=%@ header=%@ config=%@>", self.targetName, self.headerName, self.configFile];
}


@end
8 changes: 8 additions & 0 deletions Pods support/CDPodsFileProcessor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import <Foundation/Foundation.h>

@class CDPbxProjectTarget;


@interface CDPodsFileProcessor : NSObject
- (void)processTarget:(CDPbxProjectTarget *)target symbolsFilePath:(NSString *)symbolsFilePath;
@end
57 changes: 57 additions & 0 deletions Pods support/CDPodsFileProcessor.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#import "CDPodsFileProcessor.h"
#import "CDPbxProjectTarget.h"


@implementation CDPodsFileProcessor {

}
- (void)processTarget:(CDPbxProjectTarget *)target symbolsFilePath:(NSString *)symbolsFilePath {
if (target.headerName.length == 0 || target.configFile.length == 0) {
NSLog(@"Error: Could not process target %@ config %@ header %@. Some values are missing.", target.targetName, target.configFile, target.headerName);
return;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *keys = [NSArray arrayWithObject:NSURLIsDirectoryKey];
NSURL *directoryURL = [[NSURL alloc] initWithString:@"."];

NSDirectoryEnumerator *enumerator = [fileManager
enumeratorAtURL:directoryURL
includingPropertiesForKeys:keys
options:0
errorHandler:^(NSURL *url, NSError *error) {
// Handle the error.
// Return YES if the enumeration should continue after the error.
return YES;
}];


for (NSURL *url in enumerator) {
NSError *error;
NSNumber *isDirectory = nil;
if ([url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error] && ![isDirectory boolValue]) {
NSString *symbolsFileName = [[symbolsFilePath pathComponents] lastObject];
if ([[[url.absoluteString pathComponents] lastObject] isEqualToString:target.headerName]) {
NSLog(@"Obfuscating precompiled header %@", target.headerName);
NSString *headerData = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSString *obfuscatedData = [NSString stringWithFormat:@"#import \"%@\"\n%@", symbolsFileName, headerData];
[obfuscatedData writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
if ([[[url.absoluteString pathComponents] lastObject] isEqualToString:target.configFile]) {
NSLog(@"Adding symbols file path to configuration file %@", target.configFile);
NSString *configData = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSArray *pathComponents = [symbolsFilePath pathComponents];

NSString *symbolsDirectory = @"";
for (NSString *component in pathComponents) {
if (![component isEqualToString:symbolsFileName]) {
symbolsDirectory = [symbolsDirectory stringByAppendingPathComponent:component];
}
}
NSString *processedData = [configData stringByReplacingOccurrencesOfString:@"HEADER_SEARCH_PATHS = " withString:[NSString stringWithFormat:@"HEADER_SEARCH_PATHS = \"${PODS_ROOT}/../%@\" ", symbolsDirectory]];
[processedData writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
}
}
}

@end
1 change: 1 addition & 0 deletions Source/CDSymbolsGeneratorVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
@property (nonatomic, copy) NSArray *ignoreSymbols;
@property (nonatomic, readonly) NSString *resultString;
@property (nonatomic, readonly) NSDictionary *symbols;
@property(nonatomic, copy) NSString *symbolsFilePath;
@end
Loading

0 comments on commit e548e76

Please sign in to comment.