From 6cf89e2e63d94fc1cb04231c8b75fb99d1ef06ff Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Thu, 5 Jan 2017 18:22:21 +0530 Subject: [PATCH 1/7] Added secure text field for password --- AppBox/Base.lproj/Main.storyboard | 43 +++++++++++++++++-------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/AppBox/Base.lproj/Main.storyboard b/AppBox/Base.lproj/Main.storyboard index 390c32cc..30dbef4e 100644 --- a/AppBox/Base.lproj/Main.storyboard +++ b/AppBox/Base.lproj/Main.storyboard @@ -915,11 +915,11 @@ Gw - + - + @@ -930,7 +930,7 @@ Gw - + @@ -946,7 +946,7 @@ Gw - + @@ -981,7 +981,7 @@ Gw - + @@ -989,7 +989,7 @@ Gw - + @@ -997,7 +997,7 @@ Gw - + @@ -1005,10 +1005,10 @@ Gw - + - + @@ -1019,7 +1019,7 @@ Gw - + @@ -1027,7 +1027,7 @@ Gw - + @@ -1037,24 +1037,26 @@ Gw - + - + - - + + NSAllRomanInputSourcesLocaleIdentifier + + + - + - @@ -1063,7 +1065,6 @@ Gw - @@ -1071,14 +1072,16 @@ Gw + + - + @@ -1088,6 +1091,8 @@ Gw + + From 00215bc4e826a36cf6d4951cf9456642d504823c Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Thu, 5 Jan 2017 18:23:04 +0530 Subject: [PATCH 2/7] Added constants for BuildType and AppStoreUploadTools --- AppBox/Model/ProjectModel/XCProject.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/AppBox/Model/ProjectModel/XCProject.h b/AppBox/Model/ProjectModel/XCProject.h index 867aba78..e606776e 100644 --- a/AppBox/Model/ProjectModel/XCProject.h +++ b/AppBox/Model/ProjectModel/XCProject.h @@ -8,6 +8,16 @@ #import +#define BuildTypeAdHoc @"ad-hoc" +#define BuildTypePackage @"package" +#define BuildTypeAppStore @"app-store" +#define BuildTypeEnterprise @"enterprise" +#define BuildTypeDevelopment @"development" +#define BuildTypeDeveloperId @"developer-id" + +#define AppStoreUploadToolAL @"Application Loader" +#define AppStoreUploadToolXcode @"Xcode" + @interface XCProject : NSObject //Project Basic Properties @@ -33,6 +43,11 @@ @property(nonatomic, retain) NSArray *schemes; @property(nonatomic, retain) NSArray *targets; +//AppStore Details +@property(nonatomic, retain) NSString *itcPasswod; +@property(nonatomic, retain) NSString *itcUserName; +@property(nonatomic, retain) NSString *appStoreUploadTool; + //Info.plist, manifest.plist and buildlist information @property(nonatomic, retain) NSDictionary *ipaInfoPlist; @property(nonatomic, retain) NSDictionary *manifestData; @@ -40,8 +55,8 @@ @property(nonatomic, retain) NSDictionary *exportOptionsPlist; //UniqueLink.json -@property(nonatomic, retain) DBMetadata *uniqueLinkJsonMetaData; @property(nonatomic, retain) NSURL *uniquelinkShareableURL; +@property(nonatomic, retain) DBMetadata *uniqueLinkJsonMetaData; //Shareable URL DropBox or Google Shortern @property(nonatomic, retain) NSURL *dbDirectory; From b7b740b201216fb15678eb12396fbb0e07cc75ca Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Thu, 5 Jan 2017 18:29:52 +0530 Subject: [PATCH 3/7] Setup basic view and project model for App Store username/email & password --- AppBox/Base.lproj/Main.storyboard | 28 +++++++++---------- .../ProjectAdvancedViewController.h | 2 ++ .../ProjectAdvancedViewController.m | 10 +++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/AppBox/Base.lproj/Main.storyboard b/AppBox/Base.lproj/Main.storyboard index 30dbef4e..7cbaa8ab 100644 --- a/AppBox/Base.lproj/Main.storyboard +++ b/AppBox/Base.lproj/Main.storyboard @@ -915,11 +915,11 @@ Gw - + - + @@ -930,7 +930,7 @@ Gw - + @@ -946,7 +946,7 @@ Gw - + @@ -981,7 +981,7 @@ Gw - + @@ -989,7 +989,7 @@ Gw - + @@ -997,7 +997,7 @@ Gw - + @@ -1005,10 +1005,10 @@ Gw - + - + @@ -1019,15 +1019,15 @@ Gw - + - + - + @@ -1038,9 +1038,9 @@ Gw - + - + diff --git a/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.h b/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.h index f7e7316c..f84ce044 100644 --- a/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.h +++ b/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.h @@ -11,6 +11,8 @@ @interface ProjectAdvancedViewController : NSViewController{ IBOutlet NSPathControl *pathBuild; IBOutlet NSComboBox *comboAppStoreTool; + IBOutlet NSTextField *textFieldUserName; + IBOutlet NSSecureTextField *textFieldPassword; } @property(nonatomic, strong) XCProject *project; diff --git a/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.m b/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.m index 5861b9b5..052d6428 100644 --- a/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.m +++ b/AppBox/ViewController/ProjectAdvancedViewController/ProjectAdvancedViewController.m @@ -16,6 +16,13 @@ @implementation ProjectAdvancedViewController - (void)viewDidLoad { [super viewDidLoad]; + if ([self.project.buildType isEqualToString:BuildTypeAppStore]){ + [comboAppStoreTool selectItemAtIndex:0]; + }else{ + [comboAppStoreTool setEnabled:NO]; + [textFieldUserName setEnabled:NO]; + [textFieldPassword setEnabled:NO]; + } [pathBuild setURL:self.project.buildDirectory]; } @@ -25,6 +32,9 @@ - (IBAction)buttonCancelTapped:(NSButton *)sender { - (IBAction)buttonSaveTapped:(NSButton *)sender { [UserData setBuildLocation:self.project.buildDirectory]; + [self.project setItcPasswod:textFieldPassword.stringValue]; + [self.project setItcUserName:textFieldUserName.stringValue]; + [self.project setAppStoreUploadTool: comboAppStoreTool.stringValue]; [self dismissController:self]; } From fe219892fd507b22b020e1811b54eb7fa7cdffa2 Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Thu, 5 Jan 2017 19:04:23 +0530 Subject: [PATCH 4/7] Added Script for Application Loader and Xcode --- AppBox.xcodeproj/project.pbxproj | 8 ++++++-- AppBox/Commands/ALAppStoreUpload.sh | 20 ++++++++++++++++++++ AppBox/Commands/XcodeAppStoreUpload.sh | 7 +++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100755 AppBox/Commands/ALAppStoreUpload.sh create mode 100755 AppBox/Commands/XcodeAppStoreUpload.sh diff --git a/AppBox.xcodeproj/project.pbxproj b/AppBox.xcodeproj/project.pbxproj index 6193f176..8496cb2e 100644 --- a/AppBox.xcodeproj/project.pbxproj +++ b/AppBox.xcodeproj/project.pbxproj @@ -136,6 +136,8 @@ E1902B5F1E1661BE00C3E0F6 /* UpdateHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UpdateHandler.m; sourceTree = ""; }; E1902B621E16633A00C3E0F6 /* KeychainHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainHandler.h; sourceTree = ""; }; E1902B631E16633A00C3E0F6 /* KeychainHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainHandler.m; sourceTree = ""; }; + E191F7C21E1E7B2A00D2A590 /* ALAppStoreUpload.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ALAppStoreUpload.sh; sourceTree = ""; }; + E191F7C31E1E7B3B00D2A590 /* XcodeAppStoreUpload.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = XcodeAppStoreUpload.sh; sourceTree = ""; }; E1C148731E027A6100EE637F /* AFNetworking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AFNetworking.framework; sourceTree = ""; }; E1CFC65C1D7E7FEA005872BE /* Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Common.h; sourceTree = ""; }; E1CFC65D1D7E7FEA005872BE /* Common.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Common.m; sourceTree = ""; }; @@ -341,9 +343,11 @@ isa = PBXGroup; children = ( E13946141DF2FBAD00B3FAD0 /* ProjectBuildScript.sh */, - E13946151DF2FBAD00B3FAD0 /* WorkspaceBuildScript.sh */, - E172E13B1DEEB3B900405EF2 /* GetSchemeScript.sh */, E10B82211DF0498600BBE0CD /* TeamIDScript.sh */, + E172E13B1DEEB3B900405EF2 /* GetSchemeScript.sh */, + E13946151DF2FBAD00B3FAD0 /* WorkspaceBuildScript.sh */, + E191F7C21E1E7B2A00D2A590 /* ALAppStoreUpload.sh */, + E191F7C31E1E7B3B00D2A590 /* XcodeAppStoreUpload.sh */, ); path = Commands; sourceTree = ""; diff --git a/AppBox/Commands/ALAppStoreUpload.sh b/AppBox/Commands/ALAppStoreUpload.sh new file mode 100755 index 00000000..f8fbf389 --- /dev/null +++ b/AppBox/Commands/ALAppStoreUpload.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# ALAppStoreUpload.sh +# AppBox +# +# Created by Vineet Choudhary on 05/01/17. +# Copyright © 2017 Developer Insider. All rights reserved. + +#{1} - Application Loader Directory +cd "${1}" + +# Validate App +#{2} - IPA File Path +#{3} - itunesconnect username +#{4} - itunesconnect password +altool --validate-app -f "${2}" -u "${3}" -p "${4}" --output-format xml + + +# Upload App +altool --upload-app -f "${2}" -u "${3}" -p "${4}" --output-format xml diff --git a/AppBox/Commands/XcodeAppStoreUpload.sh b/AppBox/Commands/XcodeAppStoreUpload.sh new file mode 100755 index 00000000..606dc870 --- /dev/null +++ b/AppBox/Commands/XcodeAppStoreUpload.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# XcodeAppStoreUpload.sh +# AppBox +# +# Created by Vineet Choudhary on 05/01/17. +# Copyright © 2017 Developer Insider. All rights reserved. From 0df5fac27208babe3ecc8ba7dd353700f810fa52 Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Fri, 6 Jan 2017 10:48:12 +0530 Subject: [PATCH 5/7] Deleted unwanted outlet --- AppBox/Base.lproj/Main.storyboard | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/AppBox/Base.lproj/Main.storyboard b/AppBox/Base.lproj/Main.storyboard index 7cbaa8ab..ef3b01e1 100644 --- a/AppBox/Base.lproj/Main.storyboard +++ b/AppBox/Base.lproj/Main.storyboard @@ -166,8 +166,6 @@ - - @@ -194,7 +192,7 @@ - + From a87b13faf014c0f61f4754552c36dd0a7c96d23d Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Fri, 6 Jan 2017 10:59:51 +0530 Subject: [PATCH 6/7] UI Fixes --- AppBox/Base.lproj/Main.storyboard | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/AppBox/Base.lproj/Main.storyboard b/AppBox/Base.lproj/Main.storyboard index ef3b01e1..0f59c142 100644 --- a/AppBox/Base.lproj/Main.storyboard +++ b/AppBox/Base.lproj/Main.storyboard @@ -178,7 +178,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -197,21 +197,21 @@ - + - + - + - + @@ -425,13 +425,13 @@ - + - + @@ -452,7 +452,7 @@ - + @@ -460,12 +460,12 @@ - + - + From 61d30bc01a5c2ae3bdba9f55742cef099533816c Mon Sep 17 00:00:00 2001 From: Vineet Choudhary Date: Fri, 6 Jan 2017 12:52:59 +0530 Subject: [PATCH 7/7] Clean keychain handler and filter team ids --- AppBox/Common/Constants.h | 1 + .../Common/KeychainHandler/KeychainHandler.m | 67 ++++++++----------- 2 files changed, 29 insertions(+), 39 deletions(-) diff --git a/AppBox/Common/Constants.h b/AppBox/Common/Constants.h index f71c9464..7a4434da 100644 --- a/AppBox/Common/Constants.h +++ b/AppBox/Common/Constants.h @@ -43,6 +43,7 @@ #define abBuildLocation @"~/Desktop" //others +#define abTeamIdLength 10 #define abEmptyString @"" diff --git a/AppBox/Common/KeychainHandler/KeychainHandler.m b/AppBox/Common/KeychainHandler/KeychainHandler.m index cc896ad1..1ce9079f 100644 --- a/AppBox/Common/KeychainHandler/KeychainHandler.m +++ b/AppBox/Common/KeychainHandler/KeychainHandler.m @@ -9,55 +9,39 @@ #import "KeychainHandler.h" static NSString *const CERTIFICATE_KEY = @"CerKey"; static NSString *const CERTIFICATE_KEY_READABLE = @"CerKeyReadable"; + @implementation KeychainHandler + #pragma mark - Get Team Id + (NSArray *)getAllTeamId{ NSError *error = nil; NSArray *certficates = [self allKeychainCertificatesWithError:&error]; NSMutableArray *plainCertifcates = [[NSMutableArray alloc] init]; - NSMutableArray *tempTeamIds = [[NSMutableArray alloc] init]; - //////// + [certficates enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSMutableDictionary *certProperties = [self getPlainCertificate:obj]; - if([certProperties objectForKey:abTeamId]) - [plainCertifcates addObject:certProperties]; - }]; - NSMutableDictionary *dict = [plainCertifcates mutableCopy]; - NSLog(@"Plan certificates %@",dict); - //////////////////// - plainCertifcates = [NSMutableArray new]; - [certficates enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - NSMutableDictionary *certProperties = [[NSMutableDictionary alloc] init]; - NSString *certLabel = [obj valueForKey:(NSString *)kSecAttrLabel]; - NSArray *certComponent = [certLabel componentsSeparatedByString:@": "]; - if (certComponent.count == 2 && - ([[[certComponent firstObject] lowercaseString] isEqualToString:abiPhoneDistribution] || - [[[certComponent firstObject] lowercaseString] isEqualToString:abiPhoneDeveloper])){ - NSArray *certDetailsComponent = [[certComponent lastObject] componentsSeparatedByString:@" ("]; - if (certDetailsComponent.count == 2){ - NSString *teamId = [[certDetailsComponent lastObject] stringByReplacingOccurrencesOfString:@")" withString:abEmptyString]; - [certProperties setValue:certLabel forKey:abFullName]; - [certProperties setValue:[certComponent lastObject] forKey:abTeamName]; - [certProperties setObject:teamId forKey:abTeamId]; - if ([teamId containsString:@" "]){ - - } - if (![tempTeamIds containsObject:teamId] && ![teamId containsString:@" "]){ - [tempTeamIds addObject:teamId]; - [plainCertifcates addObject:certProperties]; - } - } - } - + NSString *teamId = [certProperties objectForKey:abTeamId]; + NSString *teamName = [certProperties objectForKey:abTeamName]; + NSString *fullName = [certProperties objectForKey:abFullName]; + NSPredicate *existingTeam = [NSPredicate predicateWithFormat:@"SELF.teamId = %@ AND SELF.teamName = %@ AND SELF.fullName = %@",teamId, teamName, fullName]; + NSLog(@"filter - %@",[plainCertifcates filteredArrayUsingPredicate:existingTeam]); + if (![teamId containsString:@" "] && teamId.length == abTeamIdLength //filter team id + && ([fullName.lowercaseString containsString:abiPhoneDeveloper] + || [fullName.lowercaseString containsString:abiPhoneDistribution]) //filter certifcates + && [plainCertifcates filteredArrayUsingPredicate:existingTeam].count == 0 //filter existing team + ){ + [plainCertifcates addObject:certProperties]; + } }]; + [plainCertifcates sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { return [obj1 valueForKey:abTeamId] > [obj2 valueForKey:abTeamId]; }]; return plainCertifcates; } -+ (NSArray *)allKeychainCertificatesWithError:(NSError *__autoreleasing *)error -{ + ++ (NSArray *)allKeychainCertificatesWithError:(NSError *__autoreleasing *)error{ NSDictionary *options = @{(__bridge id)kSecClass: (__bridge id)kSecClassCertificate, (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll}; CFArrayRef certs = NULL; @@ -68,24 +52,29 @@ + (NSArray *)allKeychainCertificatesWithError:(NSError *__autoreleasing *)error } return certificates; } + + (NSMutableDictionary *)getPlainCertificate:(id)certificate{ NSMutableDictionary *plainCertificate = [NSMutableDictionary new]; [plainCertificate addEntriesFromDictionary:[self getSubjectNameDetailsFromCertificate:certificate]]; [plainCertificate addEntriesFromDictionary:[self getIssuerDetailsFromCertificate:certificate]]; return plainCertificate; } + +(NSMutableDictionary *)getIssuerDetailsFromCertificate:(id)certificate{ NSMutableDictionary *sectionKeys = [NSMutableDictionary new]; [sectionKeys setObject:abExpiryDate forKey:((__bridge id)kSecOIDX509V1ValidityNotAfter)]; // [sectionKeys setObject:abTeamId forKey:((__bridge id)kSecOIDOrganizationalUnitName)]; return [self getCertificateDetails:certificate withSectionIdKey:(__bridge id)kSecOIDX509V1IssuerName withSectionKeys:sectionKeys]; } + +(NSMutableDictionary *)getSubjectNameDetailsFromCertificate:(id)certificate{ NSMutableDictionary *sectionKeys = [NSMutableDictionary new]; [sectionKeys setObject:abTeamName forKey:((__bridge id)kSecOIDOrganizationName)]; [sectionKeys setObject:abTeamId forKey:((__bridge id)kSecOIDOrganizationalUnitName)]; + [sectionKeys setObject:abFullName forKeyedSubscript:((__bridge id)kSecOIDCommonName)]; return [self getCertificateDetails:certificate withSectionIdKey:(__bridge id)kSecOIDX509V1SubjectName withSectionKeys:sectionKeys]; } + +(NSMutableDictionary *)getCertificateDetails:(id)certificate withSectionIdKey:(id)section withSectionKeys:(NSDictionary *)sectionKeys{ NSMutableDictionary *plainCertificate = [NSMutableDictionary new]; id sectionValue = [self valueWithCertificate:certificate key:section]; @@ -93,16 +82,13 @@ +(NSMutableDictionary *)getCertificateDetails:(id)certificate withSectionIdKey:( for (id subjectDetail in sectionValue) { for (id key in [sectionKeys allKeys]) { id label = subjectDetail[(__bridge id)kSecPropertyKeyLabel]; - NSLog(@"Key %@ Cerificate label %@",key,label); - if([label isEqualToString:key]) - { - id value = subjectDetail[(__bridge id)kSecPropertyKeyValue]; + id value = subjectDetail[(__bridge id)kSecPropertyKeyValue]; + if([label isEqualToString:key]){ [plainCertificate setObject:value forKey:[sectionKeys valueForKey:key]]; } } } } - NSLog(@"Section values %@",sectionValue); return plainCertificate; } +(NSArray *)keysNeedToExtract{ @@ -112,6 +98,7 @@ +(NSArray *)keysNeedToExtract{ }, ]; } + + (id)valueWithCertificate:(id)certificate key:(id)key{ return [self valuesWithCertificate:certificate keys:@[key] error:nil][key][(__bridge id)kSecPropertyKeyValue]; } @@ -122,6 +109,8 @@ + (NSDictionary *)valuesWithCertificate:(id)certificate keys:(NSArray *)keys err if (error) *error = CFBridgingRelease(e); return result; } + + #pragma mark - Remove All Cache, Cookies and Credentials + (void)removeAllStoredCredentials{ // Delete any cached URLrequests!