From b954ff2445dea1ae26158d849672832d60a1647b Mon Sep 17 00:00:00 2001 From: Christine Corbett Date: Sun, 11 Jan 2015 08:48:18 -0800 Subject: [PATCH] Closes #261 - Signal 1.0 to 2.0 utility. Reviewed-by: @FredericJacobs --- Podfile | 1 + Podfile.lock | 5 + Pods | 2 +- Signal.xcodeproj/project.pbxproj | 25 ++-- Signal/src/AppDelegate.m | 27 ++-- Signal/src/call/RecentCallManager.h | 1 - Signal/src/call/RecentCallManager.m | 10 +- Signal/src/environment/Environment.h | 1 - Signal/src/environment/Environment.m | 1 - Signal/src/environment/PreferencesUtil.h | 3 + Signal/src/environment/PreferencesUtil.m | 23 ++- Signal/src/environment/SignalKeyingStorage.h | 9 ++ Signal/src/environment/SignalKeyingStorage.m | 15 +- Signal/src/environment/VersionMigrations.h | 5 +- Signal/src/environment/VersionMigrations.m | 98 ++++++++++++- .../CodeVerificationViewController.m | 1 - .../view controllers/InitialViewController.h | 1 - .../view controllers/InitialViewController.m | 2 +- .../view controllers/SignalTabBarController.m | 14 +- .../test/textsecure/VersionMigrationsTests.m | 134 ++++++++++++++++++ 20 files changed, 324 insertions(+), 54 deletions(-) create mode 100644 Signal/test/textsecure/VersionMigrationsTests.m diff --git a/Podfile b/Podfile index 72ea206ca..39e60c3be 100644 --- a/Podfile +++ b/Podfile @@ -16,3 +16,4 @@ pod 'Mantle', '~> 1.5' pod 'SSKeychain' pod 'JSQMessagesViewController', :git => 'https://github.com/dtsbourg/JSQMessagesViewController', :branch => 'JSignalQ' pod 'DJWActionSheet' +pod 'UICKeyChainStore', :podspec => 'Podspecs/UICKeyChainStore.podspec' diff --git a/Podfile.lock b/Podfile.lock index ce8d05fb8..600740e15 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -50,6 +50,7 @@ PODS: - SSKeychain (1.2.2) - TwistedOakCollapsingFutures (1.0.0): - UnionFind (~> 1.0) + - UICKeyChainStore (1.0.7) - UnionFind (1.0.1) - YapDatabase/common (2.5.4): - CocoaLumberjack (~> 1) @@ -69,6 +70,7 @@ DEPENDENCIES: - SocketRocket (from `https://github.com/square/SocketRocket.git`, commit `954750c018`) - SSKeychain - TwistedOakCollapsingFutures (~> 1.0) + - UICKeyChainStore (from `Podspecs/UICKeyChainStore.podspec`) - YapDatabase/SQLCipher EXTERNAL SOURCES: @@ -78,6 +80,8 @@ EXTERNAL SOURCES: SocketRocket: :commit: 954750c018 :git: https://github.com/square/SocketRocket.git + UICKeyChainStore: + :podspec: Podspecs/UICKeyChainStore.podspec CHECKOUT OPTIONS: JSQMessagesViewController: @@ -105,6 +109,7 @@ SPEC CHECKSUMS: SQLCipher: 981110217eb93c2779c34fb59e646a1c1da918d8 SSKeychain: cc48bd3ad24fcd9125adb9e0d23dd50b8bbd08b9 TwistedOakCollapsingFutures: 07aab84fd3958dc94d55ef705b12857d9fbe61d1 + UICKeyChainStore: eef407137f0397e95a3df32cdf05f7e2ddd99647 UnionFind: 45777a8b6878d3a602af3654cc3a09b87389d356 YapDatabase: c1d6912df1b4a160f7373ee7657d360e29bb00fd diff --git a/Pods b/Pods index dd570a162..135d13311 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit dd570a162f44f9cc88575962b2b08fda698d9f8e +Subproject commit 135d1331112829ed1b2842d61e5ae0036aa8f78e diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index df6c8e6d7..4bb7eecf8 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -282,6 +282,7 @@ A1A018531805C60D00A052A6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A091169C9E5E00537ABF /* CoreGraphics.framework */; }; A1C32D5017A06538000A904E /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4F17A06537000A904E /* AddressBookUI.framework */; }; A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; }; + A5578C721A646E5300704A25 /* VersionMigrationsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A5578C711A646E5300704A25 /* VersionMigrationsTests.m */; }; A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */; }; A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */; }; A5D0699B1A50E9CB004CB540 /* ShowGroupMembersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5D069991A50E9CB004CB540 /* ShowGroupMembersViewController.m */; }; @@ -884,6 +885,7 @@ A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; A1C32D4F17A06537000A904E /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; }; A1FDCBEE16DAA6C300868894 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + A5578C711A646E5300704A25 /* VersionMigrationsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrationsTests.m; sourceTree = ""; }; A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanIdentityBarcodeViewController.h; sourceTree = ""; }; A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanIdentityBarcodeViewController.m; sourceTree = ""; }; A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentIdentityQRCodeViewController.m; sourceTree = ""; }; @@ -1190,8 +1192,8 @@ FC1615191A37945D00F1761D /* notification_no_preview_with_name@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "notification_no_preview_with_name@2x.png"; sourceTree = ""; }; FC16151A1A37945D00F1761D /* notification_no_preview_no_name@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "notification_no_preview_no_name@2x.png"; sourceTree = ""; }; FC16151B1A37945D00F1761D /* notification_with_preview@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "notification_with_preview@2x.png"; sourceTree = ""; }; - FC18803A1A31D94D0044CE86 /* SignalTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SignalTabBarController.h; path = "view controllers/SignalTabBarController.h"; sourceTree = ""; }; - FC18803B1A31D94D0044CE86 /* SignalTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SignalTabBarController.m; path = "view controllers/SignalTabBarController.m"; sourceTree = ""; }; + FC18803A1A31D94D0044CE86 /* SignalTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalTabBarController.h; sourceTree = ""; }; + FC18803B1A31D94D0044CE86 /* SignalTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalTabBarController.m; sourceTree = ""; }; FC1F90BF1A22342B004F8253 /* group_photo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "group_photo@2x.png"; sourceTree = ""; }; FC1F90C41A223991004F8253 /* settings_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "settings_tab@2x.png"; sourceTree = ""; }; FC1F90C51A223991004F8253 /* signals_tab@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "signals_tab@2x.png"; sourceTree = ""; }; @@ -1379,8 +1381,6 @@ 76EB03C118170B33006006FC /* src */ = { isa = PBXGroup; children = ( - FC18803A1A31D94D0044CE86 /* SignalTabBarController.h */, - FC18803B1A31D94D0044CE86 /* SignalTabBarController.m */, FCAC963419FEF4E20046DFC5 /* Storyboard.storyboard */, 76EB03C218170B33006006FC /* AppDelegate.h */, 76EB03C318170B33006006FC /* AppDelegate.m */, @@ -2315,6 +2315,7 @@ B6B095DD1A1D25C5008BFAA6 /* textsecure */ = { isa = PBXGroup; children = ( + A5578C711A646E5300704A25 /* VersionMigrationsTests.m */, B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */, B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */, B6B095E01A1D25C5008BFAA6 /* TSMessageStorageTests.m */, @@ -2694,6 +2695,8 @@ FC3196321A08142D0094C78E /* Signals */ = { isa = PBXGroup; children = ( + FC18803A1A31D94D0044CE86 /* SignalTabBarController.h */, + FC18803B1A31D94D0044CE86 /* SignalTabBarController.m */, A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */, A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */, A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */, @@ -3444,6 +3447,7 @@ 76EB05CF18170B33006006FC /* ZrtpHandshakeResult.m in Sources */, 76EB060518170B33006006FC /* PhoneNumberDirectoryFilter.m in Sources */, A157076817F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m in Sources */, + A5578C721A646E5300704A25 /* VersionMigrationsTests.m in Sources */, 76EB065718170B34006006FC /* InCallViewController.m in Sources */, A157076917F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m in Sources */, 76EB062918170B33006006FC /* BadArgument.m in Sources */, @@ -3585,7 +3589,7 @@ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -3693,6 +3697,7 @@ baseConfigurationReference = 9CC6C6BD3B51923FD6317C94 /* Pods.ad-hoc distribution.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Signal.app/Signal"; + CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "\"$(SDKROOT)/Developer/Library/Frameworks\"", "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", @@ -3730,7 +3735,7 @@ "$(inherited)", ); PRODUCT_NAME = SignalTests; - PROVISIONING_PROFILE = "a377b8e6-d43e-485d-8830-bc7bfa3d1731"; + PROVISIONING_PROFILE = ""; TEST_HOST = "$(BUNDLE_LOADER)"; VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64"; }; @@ -3824,7 +3829,7 @@ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Distribution"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_GENERATE_TEST_COVERAGE_FILES = NO; @@ -3982,6 +3987,7 @@ baseConfigurationReference = 91E46203423941C0C94D90E9 /* Pods.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Signal.app/Signal"; + CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "\"$(SDKROOT)/Developer/Library/Frameworks\"", "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", @@ -4019,7 +4025,7 @@ "$(inherited)", ); PRODUCT_NAME = SignalTests; - PROVISIONING_PROFILE = "a377b8e6-d43e-485d-8830-bc7bfa3d1731"; + PROVISIONING_PROFILE = ""; TEST_HOST = "$(BUNDLE_LOADER)"; VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64"; }; @@ -4030,6 +4036,7 @@ baseConfigurationReference = 14DDBCE302E19644A773D119 /* Pods.app store release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Signal.app/Signal"; + CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "\"$(SDKROOT)/Developer/Library/Frameworks\"", "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", @@ -4067,7 +4074,7 @@ "$(inherited)", ); PRODUCT_NAME = SignalTests; - PROVISIONING_PROFILE = "a377b8e6-d43e-485d-8830-bc7bfa3d1731"; + PROVISIONING_PROFILE = ""; TEST_HOST = "$(BUNDLE_LOADER)"; VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64"; }; diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 124bda8ff..d1f7f0012 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1,6 +1,7 @@ #import "AppDelegate.h" #import "AppAudioManager.h" #import "CategorizingLogger.h" +#import "ContactsManager.h" #import "DebugLogger.h" #import "DialerViewController.h" #import "DiscardingLog.h" @@ -10,12 +11,11 @@ #import "NotificationTracker.h" #import "PushManager.h" #import "PriorityQueue.h" -#import "RecentCallManager.h" #import "Release.h" #import "SignalsViewController.h" +#import "TSAccountManager.h" #import "TSSocketManager.h" #import "TSStorageManager.h" -#import "TSAccountManager.h" #import "Util.h" #import "VersionMigrations.h" @@ -44,23 +44,24 @@ #pragma mark Detect updates - perform migrations - (void)performUpdateCheck{ - // We check if NSUserDefaults key for version exists. NSString *previousVersion = Environment.preferences.lastRanVersion; - NSString *currentVersion = [Environment.preferences setAndGetCurrentVersion]; - + NSString *currentVersion = [Environment.preferences setAndGetCurrentVersion]; if (!previousVersion) { DDLogError(@"No previous version found. Possibly first launch since install."); [Environment resetAppData]; // We clean previous keychain entries in case their are some entries remaining. - } else if ([currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){ - [Environment resetAppData]; - // Application was updated, let's see if we have a migration scheme for it. - if ([previousVersion isEqualToString:@"1.0.2"]) { - // Migrate from custom preferences to NSUserDefaults - [VersionMigrations migrationFrom1Dot0Dot2toLarger]; + } + else if ([Environment.preferences getIsMigratingToVersion2Dot0] || [currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){ + if([self isVersion:previousVersion atLeast:@"1.0.2"]) { + [VersionMigrations migrateFrom1Dot0Dot2ToVersion2Dot0]; // this is only necessary for older apps } } } + +- (BOOL) isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString { + return [thisVersionString compare:thatVersionString options:NSNumericSearch] != NSOrderedAscending; +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL loggingIsEnabled; @@ -84,8 +85,6 @@ } [[TSStorageManager sharedManager] setupDatabase]; - - [self performUpdateCheck]; self.notificationTracker = [NotificationTracker notificationTracker]; @@ -95,6 +94,8 @@ [Environment.getCurrent.phoneDirectoryManager startUntilCancelled:nil]; [Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup]; [UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleDefault]; + [self performUpdateCheck]; + //Accept push notification when app is not open NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; diff --git a/Signal/src/call/RecentCallManager.h b/Signal/src/call/RecentCallManager.h index 5c1766308..38e9ac305 100644 --- a/Signal/src/call/RecentCallManager.h +++ b/Signal/src/call/RecentCallManager.h @@ -18,5 +18,4 @@ - (void)addRecentCall:(RecentCall *)recentCall; - (void)addMissedCallDueToBusy:(ResponderSessionDescriptor*)incomingCallDescriptor; - @end diff --git a/Signal/src/call/RecentCallManager.m b/Signal/src/call/RecentCallManager.m index 6eb946232..70d6be9b4 100644 --- a/Signal/src/call/RecentCallManager.m +++ b/Signal/src/call/RecentCallManager.m @@ -8,6 +8,7 @@ #import "TSStorageManager.h" #import "TSContactThread.h" + @interface RecentCallManager () @property YapDatabaseConnection *dbConnection; @end @@ -74,9 +75,16 @@ - (void)addRecentCall:(RecentCall*)recentCall { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:recentCall.phoneNumber.toE164 transaction:transaction]; - TSCall *call = [[TSCall alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] withCallNumber:recentCall.phoneNumber.toE164 callType:recentCall.callType inThread:thread]; + + uint64_t callDateSeconds = (uint64_t)[recentCall.date timeIntervalSince1970]; + TSCall *call = [[TSCall alloc] initWithTimestamp:callDateSeconds*1000 withCallNumber:recentCall.phoneNumber.toE164 callType:recentCall.callType inThread:thread]; + if(recentCall.isArchived) { //for migration only from Signal versions with RedPhone only + thread.archivalDate = [NSDate dateWithTimeIntervalSince1970:(callDateSeconds+60)]; // archive has to happen in the future of the original call + [thread saveWithTransaction:transaction]; + } [call saveWithTransaction:transaction]; }]; } + @end diff --git a/Signal/src/environment/Environment.h b/Signal/src/environment/Environment.h index 3b72d72e2..1e2ab63c5 100644 --- a/Signal/src/environment/Environment.h +++ b/Signal/src/environment/Environment.h @@ -80,7 +80,6 @@ andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers +(BOOL)isRedPhoneRegistered; +(void)resetAppData; - - (void)setSignalsViewController:(SignalsViewController *)signalsViewController; - (void)setSignUpFlowNavigationController:(UINavigationController *)signUpFlowNavigationController; diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index 089ca4296..e626e28e7 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -203,7 +203,6 @@ phoneDirectoryManager; if ([tabBarController respondsToSelector:@selector(selectedIndex)]) { tabBarController.selectedIndex = 1; } - } + (void)resetAppData{ diff --git a/Signal/src/environment/PreferencesUtil.h b/Signal/src/environment/PreferencesUtil.h index d3dfb67f4..5e398de71 100644 --- a/Signal/src/environment/PreferencesUtil.h +++ b/Signal/src/environment/PreferencesUtil.h @@ -25,6 +25,9 @@ typedef NS_ENUM(NSUInteger, TSImageQuality) { -(NSTimeInterval) getCachedOrDefaultDesiredBufferDepth; -(void) setCachedDesiredBufferDepth:(double)value; +- (BOOL) getIsMigratingToVersion2Dot0; +- (void) setIsMigratingToVersion2Dot0:(BOOL)enabled; + -(BOOL)loggingIsEnabled; -(void)setLoggingEnabled:(BOOL)flag; diff --git a/Signal/src/environment/PreferencesUtil.m b/Signal/src/environment/PreferencesUtil.m index 3ccd0d3b9..56518f082 100644 --- a/Signal/src/environment/PreferencesUtil.m +++ b/Signal/src/environment/PreferencesUtil.m @@ -25,6 +25,7 @@ #define DEBUG_IS_ENABLED_KEY @"Debugging Log Enabled Key" #define NOTIFICATION_PREVIEW_TYPE_KEY @"Notification Preview Type Key" #define IMAGE_UPLOAD_QUALITY_KEY @"Image Upload Quality Key" +#define IS_MIGRATING_FROM_1DOT0_TO_LARGER_KEY @"Migrating from 1.0 to Larger" #define kSignalVersionKey @"SignalUpdateVersionKey" @@ -101,6 +102,17 @@ } } + +- (BOOL) getIsMigratingToVersion2Dot0 { + NSNumber *preference = [self tryGetValueForKey:IS_MIGRATING_FROM_1DOT0_TO_LARGER_KEY]; + if (preference) { + return [preference boolValue]; + } else{ + return NO; + } + +} + - (BOOL)loggingIsEnabled{ NSNumber *preference = [self tryGetValueForKey:DEBUG_IS_ENABLED_KEY]; if (preference) { @@ -181,13 +193,16 @@ return [NSUserDefaults.standardUserDefaults objectForKey:kSignalVersionKey]; } +- (void) setIsMigratingToVersion2Dot0:(BOOL)enabled { + [self setValueForKey:IS_MIGRATING_FROM_1DOT0_TO_LARGER_KEY toValue:@(enabled)]; +} + + + -(NSString*)setAndGetCurrentVersion{ NSString *lastVersion = self.lastRanVersion; - - [NSUserDefaults.standardUserDefaults setObject:[NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]] - forKey:kSignalVersionKey]; + [NSUserDefaults.standardUserDefaults setObject:[NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]] forKey:kSignalVersionKey]; [NSUserDefaults.standardUserDefaults synchronize]; - return lastVersion; } diff --git a/Signal/src/environment/SignalKeyingStorage.h b/Signal/src/environment/SignalKeyingStorage.h index d7c209bb2..932052a16 100644 --- a/Signal/src/environment/SignalKeyingStorage.h +++ b/Signal/src/environment/SignalKeyingStorage.h @@ -10,6 +10,15 @@ #import "PhoneNumber.h" #import "Zid.h" +#define LOCAL_NUMBER_KEY @"Number" +#define PASSWORD_COUNTER_KEY @"PasswordCounter" +#define SAVED_PASSWORD_KEY @"Password" +#define SIGNALING_MAC_KEY @"Signaling Mac Key" +#define SIGNALING_CIPHER_KEY @"Signaling Cipher Key" +#define ZID_KEY @"ZID" +#define ZID_LENGTH 12 +#define SIGNALING_EXTRA_KEY @"Signaling Extra Key" + @interface SignalKeyingStorage : NSObject +(void)generateSignaling; diff --git a/Signal/src/environment/SignalKeyingStorage.m b/Signal/src/environment/SignalKeyingStorage.m index de5762455..8768ac5f2 100644 --- a/Signal/src/environment/SignalKeyingStorage.m +++ b/Signal/src/environment/SignalKeyingStorage.m @@ -8,17 +8,8 @@ #import "CryptoTools.h" #import "SignalKeyingStorage.h" #import "Constraints.h" -#import "Util.h" #import "TSStorageManager.h" - -#define LOCAL_NUMBER_KEY @"Number" -#define PASSWORD_COUNTER_KEY @"PasswordCounter" -#define SAVED_PASSWORD_KEY @"Password" -#define SIGNALING_MAC_KEY @"Signaling Mac Key" -#define SIGNALING_CIPHER_KEY @"Signaling Cipher Key" -#define ZID_KEY @"ZID" -#define ZID_LENGTH 12 -#define SIGNALING_EXTRA_KEY @"Signaling Extra Key" +#import "Util.h" #define SignalKeyingCollection @"SignalKeyingCollection" @@ -126,4 +117,8 @@ [TSStorageManager.sharedManager setObject:string forKey:key inCollection:SignalKeyingCollection]; } + + + + @end diff --git a/Signal/src/environment/VersionMigrations.h b/Signal/src/environment/VersionMigrations.h index dd4cec48d..9d002033d 100644 --- a/Signal/src/environment/VersionMigrations.h +++ b/Signal/src/environment/VersionMigrations.h @@ -8,8 +8,11 @@ #import +#define RECENT_CALLS_DEFAULT_KEY @"RPRecentCallsDefaultKey" + @interface VersionMigrations : NSObject -+ (void)migrationFrom1Dot0Dot2toLarger; ++ (void)migrateFrom1Dot0Dot2ToGreater; ++ (void)migrateFrom1Dot0Dot2ToVersion2Dot0; @end diff --git a/Signal/src/environment/VersionMigrations.m b/Signal/src/environment/VersionMigrations.m index 2cb5f24d0..3054f8757 100644 --- a/Signal/src/environment/VersionMigrations.m +++ b/Signal/src/environment/VersionMigrations.m @@ -6,12 +6,47 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "PushManager.h" #import "VersionMigrations.h" +#import "Environment.h" +#import "PhoneNumberDirectoryFilterManager.h" +#import "PreferencesUtil.h" +#import "PushManager.h" +#import "TSAccountManager.h" +#import "RecentCallManager.h" +#import "SignalKeyingStorage.h" +#import "UICKeyChainStore.h" + +@interface SignalKeyingStorage(VersionMigrations) + ++(void)storeString:(NSString*)string forKey:(NSString*)key; ++(void)storeData:(NSData*)data forKey:(NSString*)key; +@end + @implementation VersionMigrations -+ (void)migrationFrom1Dot0Dot2toLarger{ ++ (void)migrateFrom1Dot0Dot2ToVersion2Dot0 { + [Environment.preferences setIsMigratingToVersion2Dot0:YES]; + [self migrateFrom1Dot0Dot2ToGreater]; + [self migrateRecentCallsToVersion2Dot0]; + [self migrateKeyingStorageToVersion2Dot0]; + [PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken, NSString *signupToken) { + [TSAccountManager registerWithRedPhoneToken:signupToken pushToken:pushToken success:^{ + [Environment.preferences setIsMigratingToVersion2Dot0:NO]; + Environment *env = [Environment getCurrent]; + PhoneNumberDirectoryFilterManager *manager = [env phoneDirectoryManager]; + [manager forceUpdate]; + } failure:^(NSError *error) { + // TODO: should we have a UI response here? + }]; + } failure:^{ + // TODO: should we have a UI response here? + }]; + + +} + ++ (void)migrateFrom1Dot0Dot2ToGreater { // Preferences were stored in both a preference file and a plist in the documents folder, as a temporary measure, we are going to move all the preferences to the NSUserDefaults preference store, those will be migrated to a SQLCipher-backed database @@ -25,6 +60,7 @@ NSPropertyListFormat format; NSDictionary *dict = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error]; + NSArray *entries = [dict allKeys]; NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; @@ -59,4 +95,62 @@ return; } +#pragma mark helper methods ++ (void) migrateRecentCallsToVersion2Dot0 { + + NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; + NSData *encodedData = [defaults objectForKey:RECENT_CALLS_DEFAULT_KEY]; + id data = [NSKeyedUnarchiver unarchiveObjectWithData:encodedData]; + + if(![data isKindOfClass:NSArray.class]) { + return; + } else { + NSMutableArray *allRecents = [NSMutableArray arrayWithArray:data]; + + for (RecentCall* recentCall in allRecents) { + [Environment.getCurrent.recentCallManager addRecentCall:recentCall]; + } + // Erasing recent calls in the defaults + NSUserDefaults *localDefaults = NSUserDefaults.standardUserDefaults; + NSData *saveData = [NSKeyedArchiver archivedDataWithRootObject:[NSMutableArray array]]; + [localDefaults setObject:saveData forKey:RECENT_CALLS_DEFAULT_KEY]; + [localDefaults synchronize]; + + } +} + + ++ (void)migrateKeyingStorageToVersion2Dot0{ + // if statements ensure that if this migration is called more than once for whatever reason, the original data isn't rewritten the second time + if([UICKeyChainStore stringForKey:LOCAL_NUMBER_KEY]!=nil) { + [SignalKeyingStorage storeString:[UICKeyChainStore stringForKey:LOCAL_NUMBER_KEY] forKey:LOCAL_NUMBER_KEY]; + } + if([UICKeyChainStore stringForKey:PASSWORD_COUNTER_KEY]!=nil) { + [SignalKeyingStorage storeString:[UICKeyChainStore stringForKey:PASSWORD_COUNTER_KEY] forKey:PASSWORD_COUNTER_KEY]; + } + if([UICKeyChainStore stringForKey:SAVED_PASSWORD_KEY]!=nil) { + [SignalKeyingStorage storeString:[UICKeyChainStore stringForKey:SAVED_PASSWORD_KEY] forKey:SAVED_PASSWORD_KEY]; + } + if([UICKeyChainStore dataForKey:SIGNALING_MAC_KEY]!=nil) { + [SignalKeyingStorage storeData:[UICKeyChainStore dataForKey:SIGNALING_MAC_KEY] forKey:SIGNALING_MAC_KEY]; + } + if([UICKeyChainStore dataForKey:SIGNALING_CIPHER_KEY]!=nil) { + [SignalKeyingStorage storeData:[UICKeyChainStore dataForKey:SIGNALING_CIPHER_KEY] forKey:SIGNALING_CIPHER_KEY]; + } + if([UICKeyChainStore dataForKey:ZID_KEY]!=nil) { + [SignalKeyingStorage storeData:[UICKeyChainStore dataForKey:ZID_KEY] forKey:ZID_KEY]; + } + if([UICKeyChainStore dataForKey:SIGNALING_EXTRA_KEY]!=nil) { + [SignalKeyingStorage storeData:[UICKeyChainStore dataForKey:SIGNALING_EXTRA_KEY] forKey:SIGNALING_EXTRA_KEY]; + } + // Erasing keys in the old key chain store + [UICKeyChainStore removeItemForKey:LOCAL_NUMBER_KEY]; + [UICKeyChainStore removeItemForKey:PASSWORD_COUNTER_KEY]; + [UICKeyChainStore removeItemForKey:SAVED_PASSWORD_KEY]; + [UICKeyChainStore removeItemForKey:SIGNALING_MAC_KEY]; + [UICKeyChainStore removeItemForKey:SIGNALING_CIPHER_KEY]; + [UICKeyChainStore removeItemForKey:ZID_KEY]; + [UICKeyChainStore removeItemForKey:SIGNALING_EXTRA_KEY]; +} + @end diff --git a/Signal/src/view controllers/CodeVerificationViewController.m b/Signal/src/view controllers/CodeVerificationViewController.m index 24324f441..a07b9f161 100644 --- a/Signal/src/view controllers/CodeVerificationViewController.m +++ b/Signal/src/view controllers/CodeVerificationViewController.m @@ -41,7 +41,6 @@ - (IBAction)verifyChallengeAction:(id)sender { - [self enableServerActions:NO]; [_challengeTextField resignFirstResponder]; diff --git a/Signal/src/view controllers/InitialViewController.h b/Signal/src/view controllers/InitialViewController.h index 0fb96a22b..f15b4f200 100644 --- a/Signal/src/view controllers/InitialViewController.h +++ b/Signal/src/view controllers/InitialViewController.h @@ -9,5 +9,4 @@ #import @interface InitialViewController : UIViewController - @end diff --git a/Signal/src/view controllers/InitialViewController.m b/Signal/src/view controllers/InitialViewController.m index 9e5a4c167..417ee53b9 100644 --- a/Signal/src/view controllers/InitialViewController.m +++ b/Signal/src/view controllers/InitialViewController.m @@ -18,7 +18,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - [[Environment getCurrent]setSignUpFlowNavigationController:self.navigationController]; + [[Environment getCurrent] setSignUpFlowNavigationController:self.navigationController]; } - (void)didReceiveMemoryWarning { diff --git a/Signal/src/view controllers/SignalTabBarController.m b/Signal/src/view controllers/SignalTabBarController.m index e00e83978..f4da80a9c 100644 --- a/Signal/src/view controllers/SignalTabBarController.m +++ b/Signal/src/view controllers/SignalTabBarController.m @@ -9,12 +9,16 @@ #import #import +#import "CodeVerificationViewController.h" +#import "Environment.h" +#import "PreferencesUtil.h" #import "SignalTabBarController.h" - #import "TSAccountManager.h" #import "TSDatabaseView.h" #import "TSStorageManager.h" +static NSString *const kSignupFlowSegueIndentifier = @"showSignupFlow"; + @interface SignalTabBarController () @property YapDatabaseConnection *dbConnection; @end @@ -34,8 +38,8 @@ - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; - if (![TSAccountManager isRegistered]){ - [self performSegueWithIdentifier:@"showSignupFlow" sender:self]; + if (![Environment.preferences getIsMigratingToVersion2Dot0] && ![TSAccountManager isRegistered] ){ + [self performSegueWithIdentifier:kSignupFlowSegueIndentifier sender:self]; } } @@ -55,10 +59,6 @@ [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber.integerValue]; } -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - - (UITabBarItem*)signalsItem{ return self.tabBar.items[1]; } diff --git a/Signal/test/textsecure/VersionMigrationsTests.m b/Signal/test/textsecure/VersionMigrationsTests.m new file mode 100644 index 000000000..1d3368c7c --- /dev/null +++ b/Signal/test/textsecure/VersionMigrationsTests.m @@ -0,0 +1,134 @@ +// +// VersionMigrationsTests.m +// TextSecureKit +// +// Created by Frederic Jacobs on 06/11/14. +// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// + +#import +#import "VersionMigrations.h" + +#import "CategorizingLogger.h" +#import "Cryptography.h" +#import "Environment.h" +#import "TSStorageManager.h" +#import "TSStorageManager+IdentityKeyStore.h" +#import "RecentCall.h" +#import "RecentCallManager.h" +#import "Release.h" +#import "SecurityUtils.h" +#import "TestUtil.h" +#import "TSCall.h" +#import "TSContactThread.h" +#import "TSDatabaseView.h" +#import "SignalKeyingStorage.h" +#import "UICKeyChainStore.h" +#import "YapDatabaseConnection.h" + + +@interface VersionMigrations(Testing) ++(void) migrateRecentCallsToVersion2Dot0; ++(void) migrateKeyingStorageToVersion2Dot0; +@end + + +@interface SignalKeyingStorage(Testing) ++(void)storeData:(NSData*)data forKey:(NSString*)key; ++(NSData*)dataForKey:(NSString*)key; ++(void)storeString:(NSString*)string forKey:(NSString*)key; ++(NSString*)stringForKey:(NSString*)key; +@end + +@interface TSDatabaseView(Testing) ++ (BOOL)threadShouldBeInInbox:(TSThread*)thread; +@end + + +@interface VersionMigrationsTests : XCTestCase +@property (nonatomic,strong) NSString* localNumber; +@property (nonatomic,strong) NSString* passwordCounter; +@property (nonatomic,strong) NSString* savedPassword; + +@property (nonatomic,strong) NSData* signalingMacKey; +@property (nonatomic,strong) NSData* signalingCipherKey; +@property (nonatomic,strong) NSData* zidKey; +@property (nonatomic,strong) NSData* signalingExtraKey; +@property (nonatomic,strong) NSMutableArray* recentCalls; +@end + +@implementation VersionMigrationsTests + +- (void)setUp { + [super setUp]; + [Environment setCurrent:[Release unitTestEnvironment:@[]]]; + + + _localNumber = @"+123456789"; + _passwordCounter = @"20"; + _savedPassword = @"muchlettersverysecure"; + _signalingMacKey = [Cryptography generateRandomBytes:8]; + _signalingCipherKey = [Cryptography generateRandomBytes:8]; + _zidKey = [Cryptography generateRandomBytes:8]; + _signalingExtraKey = [Cryptography generateRandomBytes:8]; + + // setup the keys + [UICKeyChainStore setString:_localNumber forKey:LOCAL_NUMBER_KEY]; + [UICKeyChainStore setString:_passwordCounter forKey:PASSWORD_COUNTER_KEY]; + [UICKeyChainStore setString:_savedPassword forKey:SAVED_PASSWORD_KEY]; + [UICKeyChainStore setData:_signalingMacKey forKey:SIGNALING_MAC_KEY]; + [UICKeyChainStore setData:_signalingCipherKey forKey:SIGNALING_CIPHER_KEY]; + [UICKeyChainStore setData:_zidKey forKey:ZID_KEY]; + [UICKeyChainStore setData:_signalingExtraKey forKey:SIGNALING_EXTRA_KEY]; + + // setup the recent calls + RecentCall* r1 = [RecentCall recentCallWithContactID:123 + andNumber:testPhoneNumber1 + andCallType:RPRecentCallTypeIncoming]; + RecentCall* r2 = [RecentCall recentCallWithContactID:456 + andNumber:testPhoneNumber2 + andCallType:RPRecentCallTypeMissed]; + + r2.isArchived = YES; + + _recentCalls = [[NSMutableArray alloc] initWithObjects:r1,r2,nil]; + + NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; + NSData *saveData = [NSKeyedArchiver archivedDataWithRootObject:_recentCalls.copy]; + [defaults setObject:saveData forKey:RECENT_CALLS_DEFAULT_KEY]; + [defaults synchronize]; + +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testMigrateKeyingStorageToVersion2Dot0 { + // migrate keying storage + [VersionMigrations migrateKeyingStorageToVersion2Dot0]; + + // checking that everything is migrated correctly + XCTAssert([[SignalKeyingStorage stringForKey:LOCAL_NUMBER_KEY] isEqualToString:_localNumber]); + XCTAssert([[SignalKeyingStorage stringForKey:PASSWORD_COUNTER_KEY] isEqualToString:_passwordCounter]); + XCTAssert([[SignalKeyingStorage stringForKey:SAVED_PASSWORD_KEY] isEqualToString:_savedPassword]); + + XCTAssert([[SignalKeyingStorage dataForKey:SIGNALING_MAC_KEY] isEqualToData:_signalingMacKey]); + XCTAssert([[SignalKeyingStorage dataForKey:SIGNALING_CIPHER_KEY] isEqualToData:_signalingCipherKey]); + XCTAssert([[SignalKeyingStorage dataForKey:ZID_KEY] isEqualToData:_zidKey]); + XCTAssert([[SignalKeyingStorage dataForKey:SIGNALING_EXTRA_KEY] isEqualToData:_signalingExtraKey]); + + // checking that the old storage is empty + XCTAssert([UICKeyChainStore stringForKey:LOCAL_NUMBER_KEY] == nil); + XCTAssert([UICKeyChainStore stringForKey:PASSWORD_COUNTER_KEY] == nil); + XCTAssert([UICKeyChainStore stringForKey:SAVED_PASSWORD_KEY] == nil); + + XCTAssert([UICKeyChainStore dataForKey:SIGNALING_MAC_KEY] == nil); + XCTAssert([UICKeyChainStore dataForKey:SIGNALING_CIPHER_KEY] == nil); + XCTAssert([UICKeyChainStore dataForKey:ZID_KEY] == nil); + XCTAssert([UICKeyChainStore dataForKey:SIGNALING_EXTRA_KEY] == nil); + +} + +@end