Addressing some storage related fixes.

- Tested on jailbroken phone that correct files are getting encrypted
- Fixes #557
- Stores image file extension
- Addresses issue with deletion of debug logs
- Preventing user to browse in app if not registered with TS server
pull/1/head
Frederic Jacobs 10 years ago
parent 1ede61f272
commit 9872bed428

@ -49,16 +49,11 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
- (void)performUpdateCheck{
NSString *previousVersion = Environment.preferences.lastRanVersion;
NSString *currentVersion = [Environment.preferences setAndGetCurrentVersion];
// TODO: remove
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(([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) || [Environment.preferences getIsMigratingToVersion2Dot0] ) {
} else if(([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"]) || [Environment.preferences getIsMigratingToVersion2Dot0] ) {
[VersionMigrations migrateFrom1Dot0Dot2ToVersion2Dot0];
}
else if([self isVersion:previousVersion atLeast:@"2.0" andLessThan:@"2.0.10"]){
[VersionMigrations migrateFrom2Dot0BetaTo2Dot0Dot10];
}
}
@ -77,15 +72,28 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
BOOL loggingIsEnabled;
[self setupAppearance];
#ifdef DEBUG
// Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like
// the phone directory being looked up during tests.
if (getenv("runningTests_dontStartApp")) {
return YES;
}
self.notificationTracker = [NotificationTracker notificationTracker];
CategorizingLogger* logger = [CategorizingLogger categorizingLogger];
[logger addLoggingCallback:^(NSString *category, id details, NSUInteger index) {}];
[Environment setCurrent:[Release releaseEnvironmentWithLogging:logger]];
[Environment.getCurrent.phoneDirectoryManager startUntilCancelled:nil];
[Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup];
[[TSStorageManager sharedManager] setupDatabase];
BOOL loggingIsEnabled;
#ifdef DEBUG
// Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like
// the phone directory being looked up during tests.
loggingIsEnabled = TRUE;
[DebugLogger.sharedInstance enableTTYLogging];
@ -97,18 +105,15 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
[DebugLogger.sharedInstance enableFileLogging];
}
self.notificationTracker = [NotificationTracker notificationTracker];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"UserInitialViewController"];
CategorizingLogger* logger = [CategorizingLogger categorizingLogger];
[logger addLoggingCallback:^(NSString *category, id details, NSUInteger index) {}];
[Environment setCurrent:[Release releaseEnvironmentWithLogging:logger]];
[Environment.getCurrent.phoneDirectoryManager startUntilCancelled:nil];
[Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = viewController;
[[TSStorageManager sharedManager] setupDatabase];
[self.window makeKeyAndVisible];
[self performUpdateCheck]; // this call must be made after environment has been initialized because in general upgrade may depend on environment
//Accept push notification when app is not open
NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
@ -117,14 +122,6 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
[self application:application didReceiveRemoteNotification:remoteNotif ];
}
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:[NSBundle mainBundle]];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"UserInitialViewController"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
[self prepareScreenshotProtection];
[Environment.phoneManager.currentCallObservable watchLatestValue:^(CallState* latestCall) {

@ -22,6 +22,8 @@ MacrosSingletonInterface
- (void)wipeLogs;
- (NSString*)logsDirectory;
@property (nonatomic) DDFileLogger *fileLogger;
@end

@ -11,6 +11,7 @@
#pragma mark Logging - Production logging wants us to write some logs to a file in case we need it for debugging.
#import <CocoaLumberjack/DDTTYLogger.h>
#import <CocoaLumberjack/DDFileLogger.h>
@interface DebugLogger ()
@ -21,7 +22,7 @@
MacrosSingletonImplemention
- (void)enableFileLogging{
self.fileLogger = [DDFileLogger new]; //Logging to file, because it's in the Cache folder, they are not uploaded in iTunes/iCloud backups.
self.fileLogger = [[DDFileLogger alloc] init]; //Logging to file, because it's in the Cache folder, they are not uploaded in iTunes/iCloud backups.
self.fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling.
self.fileLogger.logFileManager.maximumNumberOfLogFiles = 3; // Keep three days of logs.
[DDLog addLogger:self.fileLogger];
@ -38,17 +39,15 @@ MacrosSingletonImplemention
- (void)wipeLogs{
BOOL reenableLogging = (self.fileLogger?YES:NO);
NSError *error;
NSArray *logsPath = self.fileLogger.logFileManager.unsortedLogFilePaths;
if (reenableLogging) {
[self disableFileLogging];
}
NSError *error;
NSString *logPath = [NSHomeDirectory() stringByAppendingString:@"/Library/Caches/Logs/"];
NSArray *logsFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:logPath error:&error];
for (NSUInteger i = 0; i < logsFiles.count; i++) {
[[NSFileManager defaultManager] removeItemAtPath:[logPath stringByAppendingString:logsFiles[i]] error:&error];
for (NSUInteger i = 0; i < logsPath.count; i++) {
[[NSFileManager defaultManager] removeItemAtPath:[logsPath objectAtIndex:i] error:&error];
}
if (error) {
@ -60,4 +59,20 @@ MacrosSingletonImplemention
}
}
- (NSString*)logsDirectory{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *logsDirectory = [baseDir stringByAppendingPathComponent:@"Logs"];
if (![[NSFileManager defaultManager] fileExistsAtPath:logsDirectory]) {
NSError *error;
//[[NSFileManager defaultManager] createDirectoryAtPath:logsDirectory withIntermediateDirectories:YES attributes:nil error:nil];
if (error) {
DDLogError(@"Log folder couldn't be created. %@", error.description);
}
}
return logsDirectory;
}
@end

@ -11,6 +11,7 @@
#import "PhoneNumberDirectoryFilterManager.h"
#import "SignalKeyingStorage.h"
#import "SignalsViewController.h"
#import "TSStorageManager.h"
#define isRegisteredUserDefaultString @"isRegistered"
@ -201,12 +202,9 @@ phoneDirectoryManager;
}
+ (void)resetAppData{
[SignalKeyingStorage wipeKeychain];
[[TSStorageManager sharedManager] wipeSignalStorage];
[Environment.preferences clear];
if (self.preferences.loggingIsEnabled) {
[DebugLogger.sharedInstance wipeLogs];
}
[self.preferences setAndGetCurrentVersion];
[DebugLogger.sharedInstance wipeLogs];
}
@end

@ -24,8 +24,6 @@
+(void)generateSignaling;
+(void)generateServerAuthPassword;
+(void)wipeKeychain;
#pragma mark Registered Phone Number
+(PhoneNumber*)localNumber;

@ -31,10 +31,6 @@
[self storeData:[CryptoTools generateSecureRandomData:ZID_LENGTH] forKey:ZID_KEY];
}
+(void)wipeKeychain{
[TSStorageManager.sharedManager purgeCollection:SignalKeyingCollection];
}
+(int64_t) getAndIncrementOneTimeCounter {
__block int64_t oldCounter;
oldCounter = [[self stringForKey:PASSWORD_COUNTER_KEY] longLongValue];
@ -117,8 +113,4 @@
[TSStorageManager.sharedManager setObject:string forKey:key inCollection:SignalKeyingCollection];
}
@end

@ -12,8 +12,6 @@
@interface VersionMigrations : NSObject
+ (void)migrateFrom1Dot0Dot2ToGreater;
+ (void)migrateFrom1Dot0Dot2ToVersion2Dot0;
+ (void)migrateFrom2Dot0BetaTo2Dot0Dot10;
@end

@ -28,82 +28,58 @@
@implementation VersionMigrations
+ (void)migrateFrom1Dot0Dot2ToVersion2Dot0 {
if (!([self wasRedPhoneRegistered] || [Environment.preferences getIsMigratingToVersion2Dot0])) {
return;
}
[Environment.preferences setIsMigratingToVersion2Dot0:YES];
[self migrateFrom1Dot0Dot2ToGreater];
[self migrateRecentCallsToVersion2Dot0];
[self migrateRecentCallsToVersion2Dot0];
[self migrateKeyingStorageToVersion2Dot0];
UIAlertController *waitingController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_TEXTSECURE_COMPONENT", nil)
message:nil
preferredStyle:UIAlertControllerStyleAlert];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:waitingController
animated:YES
completion:nil];
[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];
[waitingController dismissViewControllerAnimated:YES completion:nil];
} failure:^(NSError *error) {
// TODO: should we have a UI response here?
[self refreshLock:waitingController];
DDLogError(@"Couldn't register with TextSecure server: %@", error.debugDescription);
}];
} failure:^{
// TODO: should we have a UI response here?
} failure:^(NSError *error) {
[self refreshLock:waitingController];
DDLogError(@"Couldn't register with RedPhone server.");
}];
}
+ (void)migrateFrom2Dot0BetaTo2Dot0Dot10 {
[[TSStorageManager sharedManager] deleteThreadsAndMessages];
}
+ (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
NSString* documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/"];
NSString *path = [NSString stringWithFormat:@"%@/%@.plist", documentsDirectory, @"RedPhone-Data"];
if ([NSFileManager.defaultManager fileExistsAtPath:path]) {
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSError *error;
NSPropertyListFormat format;
NSDictionary *dict = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
NSArray *entries = [dict allKeys];
NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
for (NSUInteger i = 0; i < entries.count; i++) {
NSString *key = entries[i];
[defaults setObject:dict[key] forKey:key];
}
+ (void)refreshLock:(UIAlertController*)waitingController {
[waitingController dismissViewControllerAnimated:NO completion:^{
UIAlertController *retryController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_TEXTSECURE_COMPONENT", nil)
message:NSLocalizedString(@"REGISTER_TEXTSECURE_FAILED", nil)
preferredStyle:UIAlertControllerStyleAlert];
[defaults synchronize];
[retryController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"REGISTER_FAILED_TRY_AGAIN", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self migrateFrom1Dot0Dot2ToVersion2Dot0];
}]];
[NSFileManager.defaultManager removeItemAtPath:path error:&error];
if (error) {
DDLogError(@"Error while migrating data: %@", error.description);
}
// Some users push IDs were not correctly registered, by precaution, we are going to re-register all of them
[PushManager.sharedManager registrationWithSuccess:^{
} failure:^{
DDLogError(@"Error re-registering on migration from 1.0.2");
}];
[NSFileManager.defaultManager removeItemAtPath:path error:&error];
if (error) {
DDLogError(@"Error upgrading from 1.0.2 : %@", error.description);
}
}
return;
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:retryController animated:YES completion:nil];
}];
}
#pragma mark helper methods
+ (void) migrateRecentCallsToVersion2Dot0 {
NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
NSData *encodedData = [defaults objectForKey:RECENT_CALLS_DEFAULT_KEY];
id data = [NSKeyedUnarchiver unarchiveObjectWithData:encodedData];
@ -116,16 +92,28 @@
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];
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
}
}
+(BOOL)wasRedPhoneRegistered{
BOOL hasPassCounter = [UICKeyChainStore stringForKey:PASSWORD_COUNTER_KEY]!=nil;
BOOL hasLocalNumber = [UICKeyChainStore stringForKey:LOCAL_NUMBER_KEY]!=nil;
BOOL hasPassKey = [UICKeyChainStore stringForKey:SAVED_PASSWORD_KEY]!=nil;
BOOL hasSignaling = [UICKeyChainStore dataForKey:SIGNALING_MAC_KEY]!=nil;
BOOL hasCipherKey = [UICKeyChainStore dataForKey:SIGNALING_CIPHER_KEY]!=nil;
BOOL hasZIDKey = [UICKeyChainStore dataForKey:ZID_KEY]!=nil;
BOOL hasSignalingExtra = [UICKeyChainStore dataForKey:SIGNALING_EXTRA_KEY]!=nil;
BOOL registered = [[NSUserDefaults.standardUserDefaults objectForKey:@"isRegistered"] boolValue];
return registered &&hasPassCounter && hasLocalNumber && hasPassKey && hasSignaling
&& hasCipherKey && hasCipherKey && hasZIDKey && hasSignalingExtra;
}
+ (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) {

@ -18,6 +18,8 @@
#define Signal_Message_View_Identifier @"Signal_Message_Read"
#define Signal_Message_MarkAsRead_Identifier @"Signal_Message_MarkAsRead"
typedef void(^failedPushRegistrationBlock)(NSError *error);
/**
* The Push Manager is responsible for registering the device for Signal push notifications.
*/
@ -40,7 +42,7 @@
* @param failure Block to executre if push notification registration fails
*/
- (void)registrationWithSuccess:(void (^)())success failure:(void (^)())failure;
- (void)registrationWithSuccess:(void (^)())success failure:(failedPushRegistrationBlock)failure;
/**
* Registers the push token with the RedPhone server, then returns the push token and a signup token to be used to register with TextSecure.
@ -49,14 +51,15 @@
* @param failure Failure completion block
*/
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(void (^)())failure;
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(failedPushRegistrationBlock)failure;
/**
* The pushNotification and userNotificationFutureSource are accessed by the App Delegate after requested permissions.
*/
-(TOCFuture*)registerPushNotificationFuture;
- (void)registrationForPushWithSuccess:(void (^)(NSData* pushToken))success failure:(void (^)())failure;
- (void)registrationForPushWithSuccess:(void (^)(NSData* pushToken))success failure:(void(^)(NSError *))failure;
@property TOCFutureSource *pushNotificationFutureSource;
@property TOCFutureSource *userNotificationFutureSource;

@ -11,12 +11,14 @@
#import "RPServerRequestsManager.h"
#import "TSAccountManager.h"
#define pushManagerDomain @"org.whispersystems.pushmanager"
@interface PushManager ()
@property TOCFutureSource *registerWithServerFutureSource;
@property UIAlertView *missingPermissionsAlertView;
@end
@implementation PushManager
@ -45,14 +47,14 @@
- (void)verifyPushPermissions{
if (self.isMissingMandatoryNotificationTypes || self.needToRegisterForRemoteNotifications){
[self registrationWithSuccess:^{
DDLogError(@"Re-enabled push succesfully");
} failure:^{
DDLogError(@"Failed to re-enable push.");
DDLogInfo(@"Re-enabled push succesfully");
} failure:^(NSError *error) {
DDLogError(@"Failed to re-register for push");
}];
}
}
- (void)registrationWithSuccess:(void (^)())success failure:(void (^)())failure{
- (void)registrationWithSuccess:(void (^)())success failure:(failedPushRegistrationBlock)failure{
if (!self.wantRemoteNotifications) {
success();
@ -60,9 +62,9 @@
}
[self registrationForPushWithSuccess:^(NSData* pushToken){
[self registrationForUserNotificationWithSuccess:success failure:^{
[self registrationForUserNotificationWithSuccess:success failure:^(NSError *error) {
[self.missingPermissionsAlertView show];
failure();
failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]);
}];
} failure:failure];
}
@ -82,7 +84,7 @@
[self.registerWithServerFutureSource trySetResult:@YES];
} else{
DDLogError(@"The server returned %@ instead of a 200 status code", task.response);
[self.registerWithServerFutureSource trySetFailure:nil];
[self.registerWithServerFutureSource trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]];
}
} else{
[self.registerWithServerFutureSource trySetFailure:task.response];
@ -104,21 +106,12 @@
return self.pushNotificationFutureSource.future;
}
-(TOCFuture*)registerForUserNotificationsFuture{
self.userNotificationFutureSource = [TOCFutureSource new];
NSSet *setOfCategories = [NSSet setWithArray:@[[self userNotificationsCallCategory], [self userNotificationsMessageCategory]]];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes]
categories:setOfCategories];
[UIApplication.sharedApplication registerUserNotificationSettings:settings];
return self.userNotificationFutureSource.future;
}
- (void)registrationForPushWithSuccess:(void (^)(NSData* pushToken))success failure:(void (^)())failure{
- (void)registrationForPushWithSuccess:(void (^)(NSData* pushToken))success failure:(failedPushRegistrationBlock)failure{
TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture];
[requestPushTokenFuture catchDo:^(id failureObj) {
failure();
[self.missingPermissionsAlertView show];
failure(failureObj);
DDLogError(@"This should not happen on iOS8. No push token was provided");
}];
@ -126,13 +119,7 @@
TOCFuture *registerPushTokenFuture = [self registerForPushFutureWithToken:pushToken];
[registerPushTokenFuture catchDo:^(id failureObj) {
UIAlertView *failureToRegisterWithServerAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"REGISTRATION_ERROR", @"")
message:NSLocalizedString(@"REGISTRATION_BODY", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil, nil];
[failureToRegisterWithServerAlert show];
failure();
failure(failureObj);
}];
[registerPushTokenFuture thenDo:^(id value) {
@ -142,8 +129,8 @@
}
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(void (^)())failure{
[self registrationForPushWithSuccess:^(NSData *pushToken) {
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(failedPushRegistrationBlock)failure{
[self registrationForPushWithSuccess:^(NSData *pushToken) {
[RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) {
NSError *error;
@ -151,31 +138,34 @@
NSString* tsToken = [dictionary objectForKey:@"token"];
if (!tsToken || !pushToken || error) {
failure();
failure(error);
return;
}
success(pushToken, tsToken);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
failure();
failure(error);
}];
} failure:^{
failure();
}];
} failure:failure];
}
-(TOCFuture*)registerForUserNotificationsFuture{
self.userNotificationFutureSource = [TOCFutureSource new];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes]
categories:nil];
[UIApplication.sharedApplication registerUserNotificationSettings:settings];
return self.userNotificationFutureSource.future;
}
- (void)registrationForUserNotificationWithSuccess:(void (^)())success failure:(void (^)())failure{
TOCFuture *registrerUserNotificationFuture = [self registerForUserNotificationsFuture];
[registrerUserNotificationFuture catchDo:^(id failureObj) {
[self.missingPermissionsAlertView show];
failure();
}];
[registrerUserNotificationFuture thenDo:^(id types) {
if (self.isMissingMandatoryNotificationTypes) {
[self.missingPermissionsAlertView show];
failure();
} else{
success();
@ -198,51 +188,6 @@
return YES;
}
- (UIUserNotificationCategory*)userNotificationsMessageCategory{
UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new];
action_accept.identifier = Signal_Message_View_Identifier;
action_accept.title = NSLocalizedString(@"PUSH_MANAGER_VIEW", @"");
action_accept.activationMode = UIUserNotificationActivationModeForeground;
action_accept.destructive = NO;
action_accept.authenticationRequired = YES;
UIMutableUserNotificationAction *action_decline = [UIMutableUserNotificationAction new];
action_decline.identifier = Signal_Message_MarkAsRead_Identifier;
action_decline.title = NSLocalizedString(@"PUSH_MANAGER_MARKREAD", @"");
action_decline.activationMode = UIUserNotificationActivationModeBackground;
action_decline.destructive = NO;
action_decline.authenticationRequired = NO;
UIMutableUserNotificationCategory *messageCategory = [UIMutableUserNotificationCategory new];
messageCategory.identifier = Signal_Message_Category;
[messageCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextMinimal];
[messageCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextDefault];
return messageCategory;
}
- (UIUserNotificationCategory*)userNotificationsCallCategory{
UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new];
action_accept.identifier = Signal_Call_Accept_Identifier;
action_accept.title = NSLocalizedString(@"ANSWER_CALL_BUTTON_TITLE", @"");
action_accept.activationMode = UIUserNotificationActivationModeForeground;
action_accept.destructive = NO;
action_accept.authenticationRequired = NO;
UIMutableUserNotificationAction *action_decline = [UIMutableUserNotificationAction new];
action_decline.identifier = Signal_Call_Decline_Identifier;
action_decline.title = NSLocalizedString(@"REJECT_CALL_BUTTON_TITLE", @"");
action_decline.activationMode = UIUserNotificationActivationModeBackground;
action_decline.destructive = NO;
action_decline.authenticationRequired = NO;
UIMutableUserNotificationCategory *callCategory = [UIMutableUserNotificationCategory new];
callCategory.identifier = Signal_Call_Category;
[callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextMinimal];
[callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextDefault];
return callCategory;
}
-(BOOL)isMissingMandatoryNotificationTypes {
int mandatoryTypes = self.mandatoryNotificationTypes;

@ -16,6 +16,7 @@
#import "SecurityUtils.h"
#import "TSNetworkManager.h"
#import "TSAccountManager.h"
#import "TSSocketManager.h"
#import "TSStorageManager+keyingMaterial.h"
#import "TSPreKeyManager.h"
#import "TSRegisterForPushRequest.h"
@ -120,6 +121,7 @@
[self registerForPushNotifications:pushToken success:^{
[self registerPreKeys:^{
successBlock();
[TSSocketManager becomeActive];
} failure:failureBlock];
} failure:^(NSError *error) {
failureBlock([self errorForRegistrationFailure:kTSRegistrationFailureNetwork HTTPStatusCode:0]);

@ -46,12 +46,10 @@
return [[self class] groupIdFromThreadId:self.uniqueId];
}
- (NSString*)name{
return self.groupModel.groupName;
}
+ (NSString*)threadIdFromGroupId:(NSData*)groupId{
return [TSGroupThreadPrefix stringByAppendingString:[groupId base64EncodedString]];
}
@ -60,8 +58,6 @@
return [NSData dataFromBase64String:[threadId substringWithRange:NSMakeRange(1, threadId.length-1)]];
}
- (NSArray *)recipientsWithTransaction:(YapDatabaseReadTransaction*)transaction{
NSMutableArray *recipients = [[NSMutableArray alloc] init];
@ -75,5 +71,4 @@
return recipients;
}
@end

@ -24,8 +24,6 @@
return self;
}
+ (NSString *)collection{
return @"TSAttachements";
}

@ -68,4 +68,13 @@ NSString * const TSAttachementsRelationshipEdgeName = @"TSAttachmentEdge";
}
}
- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction{
for (NSString *attachmentId in _attachments){
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction];
[attachment removeWithTransaction:transaction];
}
[super removeWithTransaction:transaction];
}
@end

@ -22,10 +22,13 @@ extern NSString *const TSUIDatabaseConnectionDidUpdateNotification;
+ (instancetype)sharedManager;
- (void)setupDatabase;
- (void)deleteThreadsAndMessages;
- (void)wipeSignalStorage;
- (YapDatabase*)database;
- (YapDatabaseConnection*)newDatabaseConnection;
- (void)setObject:(id)object forKey:(NSString*)key inCollection:(NSString*)collection;
- (void)removeObjectForKey:(NSString*)string inCollection:(NSString *)collection;
@ -44,5 +47,4 @@ extern NSString *const TSUIDatabaseConnectionDidUpdateNotification;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
- (void)wipe;
@end

@ -81,11 +81,10 @@ static NSString * keychainDBPassAccount = @"TSDatabasePass";
}
- (void)protectSignalFiles{
[self protectFolderAtPath:[TSAttachmentStream attachmentsFolder]];
[self protectFolderAtPath:[self dbPath]];
[self protectFolderAtPath:[NSHomeDirectory() stringByAppendingString:@"/Library/Caches/Logs/"]];
[self protectFolderAtPath:[[DebugLogger sharedInstance] logsDirectory]];
}
- (void)protectFolderAtPath:(NSString*)path {
@ -98,7 +97,7 @@ static NSString * keychainDBPassAccount = @"TSDatabasePass";
if (error || !success) {
DDLogError(@"Error while removing files from backup: %@", error.description);
SignalAlertView(NSLocalizedString(@"WARNING_STRING", @""), @"DISABLING_BACKUP_FAILED");
SignalAlertView(NSLocalizedString(@"WARNING_STRING", @""), NSLocalizedString(@"DISABLING_BACKUP_FAILED", @""));
return;
}
}
@ -250,16 +249,21 @@ static NSString * keychainDBPassAccount = @"TSDatabasePass";
[TSAttachmentStream deleteAttachments];
}
- (void)wipe{
- (void)wipeSignalStorage{
self.database = nil;
NSError *error;
[SSKeychain deletePasswordForService:keychainService account:keychainDBPassAccount];
[[NSFileManager defaultManager] removeItemAtPath:[self dbPath] error:&error];
if (error) {
DDLogError(@"Failed to delete database: %@", error.description);
}
[self setupDatabase];
[TSAttachmentStream deleteAttachments];
[[self init] setupDatabase];
}
@end

@ -92,8 +92,8 @@ static NSDictionary *supportedImageExtensionTypesToMIMETypes;
@"jpeg":@"image/jpeg",
@"jpg":@"image/jpeg",
@"gif":@"image/gif",
@".tif":@"image/tiff",
@".tiff":@"image/tiff"
@"tif":@"image/tiff",
@"tiff":@"image/tiff"
};
}
@ -175,13 +175,15 @@ static NSDictionary *supportedImageExtensionTypesToMIMETypes;
if ([self isVideo:contentType]){
return [MIMETypeUtil filePathForVideo:uniqueId ofMIMEType:contentType inFolder:folder];
}
else if([self isAudio:contentType]) {
return [MIMETypeUtil filePathForAudio:uniqueId ofMIMEType:contentType inFolder:folder];
}
else {
else if([self isImage:contentType]){
return [MIMETypeUtil filePathForImage:uniqueId ofMIMEType:contentType inFolder:folder];
}
DDLogError(@"Got asked for path of file %@ which is unsupported", contentType);
return nil;
}
+(NSURL*) simLinkCorrectExtensionOfFile:(NSURL*)mediaURL ofMIMEType:(NSString*)contentType {
@ -204,7 +206,7 @@ static NSDictionary *supportedImageExtensionTypesToMIMETypes;
}
+ (NSString*)filePathForImage:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{
return [folder stringByAppendingFormat:@"/%@",uniqueId];
return [[folder stringByAppendingFormat:@"/%@",uniqueId] stringByAppendingPathExtension:[self getSupportedExtensionFromImageMIMEType:contentType]];
}
+ (NSString*)filePathForVideo:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{

@ -103,8 +103,8 @@
-(void)didToggleSwitch:(UISwitch*)sender
{
if (!sender.isOn) {
[DebugLogger.sharedInstance disableFileLogging];
[DebugLogger.sharedInstance wipeLogs];
[DebugLogger.sharedInstance disableFileLogging];
} else {
[DebugLogger.sharedInstance enableFileLogging];
}

@ -64,21 +64,17 @@
- (void)registerWithSuccess:(void(^)())success failure:(void(^)(NSError *))failure{
//TODO: Refactor this to use futures? Better error handling needed. Good enough for PoC
[_submitCodeSpinner startAnimating];
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall verifyVerificationCode:_challengeTextField.text] success:^(NSURLSessionDataTask *task, id responseObject) {
[PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken, NSString *signupToken) {
[TSAccountManager registerWithRedPhoneToken:signupToken pushToken:pushToken success:^{
success();
} failure:^(NSError *error) {
failure(error);
}];
} failure:^{
// PushManager shows its own error alerts, so we don't want to show a second one
failure(nil);
} failure:^(NSError *error) {
failure(error);
[_submitCodeSpinner stopAnimating];
}];
} failure:^(NSURLSessionDataTask *task, NSError *error) {

@ -195,12 +195,12 @@ typedef enum {
[TSAccountManager unregisterTextSecureWithSuccess:^{
[PushManager.sharedManager registrationForPushWithSuccess:^(NSData* pushToken){
[[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall unregisterWithPushToken:pushToken] success:^(NSURLSessionDataTask *task, id responseObject) {
[[TSStorageManager sharedManager] wipe];
[Environment resetAppData];
exit(0);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
SignalAlertView(NSLocalizedString(@"UNREGISTER_REDPHONE_FAIL", @""), @"");
}];
} failure:^{
} failure:^(NSError *error) {
SignalAlertView(NSLocalizedString(@"UNREGISTER_REDPHONE_FAIL", @""), @"");
}];
} failure:^(NSError *error) {

@ -12,7 +12,7 @@
#import "TSAttachmentAdapter.h"
@interface TSGroupModel : TSYapDatabaseObject <YapDatabaseRelationshipNode>
@interface TSGroupModel : TSYapDatabaseObject
@property (nonatomic, strong) NSMutableArray *groupMemberIds;
@property (nonatomic, strong) UIImage *groupImage;

@ -87,17 +87,4 @@ NSString * const TSAttachementGroupAvatarFileRelationshipEdge = @"TSAttachementG
return updatedGroupInfoString;
}
- (NSArray *)yapDatabaseRelationshipEdges {
if([_associatedAttachmentId length]>0){
YapDatabaseRelationshipEdge *fileEdge = [[YapDatabaseRelationshipEdge alloc] initWithName:TSAttachementGroupAvatarFileRelationshipEdge
destinationKey:_associatedAttachmentId
collection:[TSAttachment collection]
nodeDeleteRules:YDB_DeleteDestinationIfAllSourcesDeleted];
return @[fileEdge];
}
else {
return nil;
}
}
@end

@ -54,6 +54,9 @@
"PUSH_SETTINGS_MESSAGE" = "Signal requires push notification alerts and sounds to be enabled to work properly. Please change it in the Settings app >> Notification Center >> Signal.";
"RECENT_NAV_BAR_TITLE" = "Call Log";
"REGISTER_BUTTON_TITLE" = "REGISTER";
"REGISTER_TEXTSECURE_COMPONENT" = "Sign up for TextSecure";
"REGISTER_TEXTSECURE_FAILED" = "We tried to sign you up for TextSecure but we couldn't reach the server. Please try again when connected.";
"REGISTER_FAILED_TRY_AGAIN" = "Try again";
"REGISTER_CC_ERR_ALERT_VIEW_MESSAGE" = "Please enter a valid country code";
"REGISTER_CC_ERR_ALERT_VIEW_TITLE" = "Country Code Error";
"REGISTER_CHALLENGE_ALERT_VIEW_TITLE" = "Incorrect code";

Loading…
Cancel
Save