mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			210 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Objective-C
		
	
			
		
		
	
	
			210 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Objective-C
		
	
//
 | 
						|
//  Copyright (c) 2018 Open Whisper Systems. All rights reserved.
 | 
						|
//
 | 
						|
 | 
						|
#import "VersionMigrations.h"
 | 
						|
#import "Environment.h"
 | 
						|
#import "LockInteractionController.h"
 | 
						|
#import "OWSDatabaseMigrationRunner.h"
 | 
						|
#import "SignalKeyingStorage.h"
 | 
						|
#import <SignalServiceKit/AppContext.h>
 | 
						|
#import <SignalServiceKit/AppVersion.h>
 | 
						|
#import <SignalServiceKit/NSUserDefaults+OWS.h>
 | 
						|
#import <SignalServiceKit/OWSPrimaryStorage.h>
 | 
						|
#import <SignalServiceKit/OWSRequestFactory.h>
 | 
						|
#import <SignalServiceKit/TSAccountManager.h>
 | 
						|
#import <SignalServiceKit/TSNetworkManager.h>
 | 
						|
#import <YapDatabase/YapDatabase.h>
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_BEGIN
 | 
						|
 | 
						|
#define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push"
 | 
						|
#define NEEDS_TO_REGISTER_ATTRIBUTES @"Register Attributes"
 | 
						|
 | 
						|
@interface SignalKeyingStorage (VersionMigrations)
 | 
						|
 | 
						|
+ (void)storeString:(NSString *)string forKey:(NSString *)key;
 | 
						|
+ (void)storeData:(NSData *)data forKey:(NSString *)key;
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
@implementation VersionMigrations
 | 
						|
 | 
						|
#pragma mark - Dependencies
 | 
						|
 | 
						|
+ (TSAccountManager *)tsAccountManager
 | 
						|
{
 | 
						|
    OWSAssertDebug(SSKEnvironment.shared.tsAccountManager);
 | 
						|
    
 | 
						|
    return SSKEnvironment.shared.tsAccountManager;
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark - Utility methods
 | 
						|
 | 
						|
+ (void)performUpdateCheckWithCompletion:(VersionMigrationCompletion)completion
 | 
						|
{
 | 
						|
    OWSLogInfo(@"");
 | 
						|
 | 
						|
    // performUpdateCheck must be invoked after Environment has been initialized because
 | 
						|
    // upgrade process may depend on Environment.
 | 
						|
    OWSAssertDebug(Environment.shared);
 | 
						|
    OWSAssertDebug(completion);
 | 
						|
 | 
						|
    NSString *previousVersion = AppVersion.sharedInstance.lastAppVersion;
 | 
						|
    NSString *currentVersion = AppVersion.sharedInstance.currentAppVersion;
 | 
						|
 | 
						|
    OWSLogInfo(@"Checking migrations. currentVersion: %@, lastRanVersion: %@", currentVersion, previousVersion);
 | 
						|
 | 
						|
    if (!previousVersion) {
 | 
						|
        OWSLogInfo(@"No previous version found. Probably first launch since install - nothing to migrate.");
 | 
						|
        OWSDatabaseMigrationRunner *runner = [[OWSDatabaseMigrationRunner alloc] init];
 | 
						|
        [runner assumeAllExistingMigrationsRun];
 | 
						|
        dispatch_async(dispatch_get_main_queue(), ^{
 | 
						|
            completion();
 | 
						|
        });
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if ([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) {
 | 
						|
        OWSLogError(@"Migrating from RedPhone no longer supported. Quitting.");
 | 
						|
        // Not translating these as so few are affected.
 | 
						|
        UIAlertController *alertController = [UIAlertController
 | 
						|
            alertControllerWithTitle:@"You must reinstall Signal"
 | 
						|
                             message:
 | 
						|
                                 @"Sorry, your installation is too old for us to update. You'll have to start fresh."
 | 
						|
                      preferredStyle:UIAlertControllerStyleAlert];
 | 
						|
 | 
						|
        UIAlertAction *quitAction = [UIAlertAction actionWithTitle:@"Quit"
 | 
						|
                                                             style:UIAlertActionStyleDefault
 | 
						|
                                                           handler:^(UIAlertAction *_Nonnull action) {
 | 
						|
                                                               OWSFail(@"Obsolete install.");
 | 
						|
                                                           }];
 | 
						|
        [alertController addAction:quitAction];
 | 
						|
 | 
						|
        [CurrentAppContext().frontmostViewController presentViewController:alertController animated:YES completion:nil];
 | 
						|
    }
 | 
						|
 | 
						|
    if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] && [self.tsAccountManager isRegistered]) {
 | 
						|
        [self clearVideoCache];
 | 
						|
        [self blockingAttributesUpdate];
 | 
						|
    }
 | 
						|
 | 
						|
    if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.3.0"] && [self.tsAccountManager isRegistered]) {
 | 
						|
        [self clearBloomFilterCache];
 | 
						|
    }
 | 
						|
 | 
						|
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 | 
						|
        [[[OWSDatabaseMigrationRunner alloc] init] runAllOutstandingWithCompletion:completion];
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
+ (BOOL)isVersion:(NSString *)thisVersionString
 | 
						|
          atLeast:(NSString *)openLowerBoundVersionString
 | 
						|
      andLessThan:(NSString *)closedUpperBoundVersionString
 | 
						|
{
 | 
						|
    return [self isVersion:thisVersionString atLeast:openLowerBoundVersionString] &&
 | 
						|
        [self isVersion:thisVersionString lessThan:closedUpperBoundVersionString];
 | 
						|
}
 | 
						|
 | 
						|
+ (BOOL)isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString
 | 
						|
{
 | 
						|
    return [thisVersionString compare:thatVersionString options:NSNumericSearch] != NSOrderedAscending;
 | 
						|
}
 | 
						|
 | 
						|
+ (BOOL)isVersion:(NSString *)thisVersionString lessThan:(NSString *)thatVersionString
 | 
						|
{
 | 
						|
    return [thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending;
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark Upgrading to 2.1 - Removing video cache folder
 | 
						|
 | 
						|
+ (void)clearVideoCache
 | 
						|
{
 | 
						|
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 | 
						|
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
 | 
						|
    basePath = [basePath stringByAppendingPathComponent:@"videos"];
 | 
						|
 | 
						|
    NSError *error;
 | 
						|
    if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
 | 
						|
        [NSFileManager.defaultManager removeItemAtPath:basePath error:&error];
 | 
						|
    }
 | 
						|
 | 
						|
    if (error) {
 | 
						|
        OWSLogError(
 | 
						|
            @"An error occured while removing the videos cache folder from old location: %@", error.debugDescription);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark - Update Account Attributes
 | 
						|
 | 
						|
+ (void)blockingAttributesUpdate
 | 
						|
{
 | 
						|
    LIControllerBlockingOperation blockingOperation = ^BOOL(void) {
 | 
						|
        [[NSUserDefaults appUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES];
 | 
						|
 | 
						|
        __block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
 | 
						|
 | 
						|
        __block BOOL success;
 | 
						|
 | 
						|
        TSRequest *request = [OWSRequestFactory updateAttributesRequest];
 | 
						|
        [[TSNetworkManager sharedManager] makeRequest:request
 | 
						|
            success:^(NSURLSessionDataTask *task, id responseObject) {
 | 
						|
                success = YES;
 | 
						|
                dispatch_semaphore_signal(sema);
 | 
						|
            }
 | 
						|
            failure:^(NSURLSessionDataTask *task, NSError *error) {
 | 
						|
                if (!IsNSErrorNetworkFailure(error)) {
 | 
						|
                    OWSProdError([OWSAnalyticsEvents errorUpdateAttributesRequestFailed]);
 | 
						|
                }
 | 
						|
                success = NO;
 | 
						|
                OWSLogError(@"Updating attributess failed with error: %@", error.description);
 | 
						|
                dispatch_semaphore_signal(sema);
 | 
						|
            }];
 | 
						|
 | 
						|
 | 
						|
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
 | 
						|
 | 
						|
        return success;
 | 
						|
    };
 | 
						|
 | 
						|
    LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry];
 | 
						|
 | 
						|
    [LockInteractionController performBlock:blockingOperation
 | 
						|
                            completionBlock:^{
 | 
						|
                                [[NSUserDefaults appUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES];
 | 
						|
                                OWSLogWarn(@"Successfully updated attributes.");
 | 
						|
                            }
 | 
						|
                                 retryBlock:retryBlock
 | 
						|
                                usesNetwork:YES];
 | 
						|
}
 | 
						|
 | 
						|
#pragma mark Upgrading to 2.3.0
 | 
						|
 | 
						|
// We removed bloom filter contact discovery. Clean up any local bloom filter data.
 | 
						|
+ (void)clearBloomFilterCache
 | 
						|
{
 | 
						|
    NSFileManager *fm = [NSFileManager defaultManager];
 | 
						|
    NSArray *cachesDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
 | 
						|
    NSString *bloomFilterPath = [[cachesDir objectAtIndex:0] stringByAppendingPathComponent:@"bloomfilter"];
 | 
						|
 | 
						|
    if ([fm fileExistsAtPath:bloomFilterPath]) {
 | 
						|
        NSError *deleteError;
 | 
						|
        if ([fm removeItemAtPath:bloomFilterPath error:&deleteError]) {
 | 
						|
            OWSLogInfo(@"Successfully removed bloom filter cache.");
 | 
						|
            [OWSPrimaryStorage.dbReadWriteConnection
 | 
						|
                readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
 | 
						|
                    [transaction removeAllObjectsInCollection:@"TSRecipient"];
 | 
						|
                }];
 | 
						|
            OWSLogInfo(@"Removed all TSRecipient records - will be replaced by SignalRecipients at next address sync.");
 | 
						|
        } else {
 | 
						|
            OWSLogError(@"Failed to remove bloom filter cache with error: %@", deleteError.localizedDescription);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        OWSLogDebug(@"No bloom filter cache to remove.");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
@end
 | 
						|
 | 
						|
NS_ASSUME_NONNULL_END
 |