From 40f34f3d771b8cd7cb260ee55ed5ee5d1f62faf0 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Tue, 30 Apr 2013 01:49:53 -0400 Subject: [PATCH] Avoid using object.managedObjectContext - when no strong reference exists to the MOC, it may yield nil. [FIXED] Unexpected nil MOCs. --- MasterPassword/ObjC/MPAlgorithm.h | 2 +- MasterPassword/ObjC/MPAlgorithmV0.m | 4 +- MasterPassword/ObjC/MPAppDelegate_Key.h | 2 +- MasterPassword/ObjC/MPAppDelegate_Key.m | 2 +- MasterPassword/ObjC/MPAppDelegate_Store.m | 4 + MasterPassword/ObjC/Mac/MPMacAppDelegate.m | 5 +- .../ObjC/Mac/MPPasswordWindowController.m | 14 +- .../ObjC/iOS/MPElementListController.m | 18 +- .../ObjC/iOS/MPLogsViewController.m | 12 +- .../ObjC/iOS/MPMainViewController.m | 42 ++- .../ObjC/iOS/MPPreferencesViewController.m | 32 ++- .../ObjC/iOS/MPUnlockViewController.m | 32 +-- MasterPassword/ObjC/iOS/MPiOSAppDelegate.h | 2 +- MasterPassword/ObjC/iOS/MPiOSAppDelegate.m | 8 +- .../ObjC/iOS/MainStoryboard_iPhone.storyboard | 242 ++++++++++++++++-- 15 files changed, 329 insertions(+), 92 deletions(-) diff --git a/MasterPassword/ObjC/MPAlgorithm.h b/MasterPassword/ObjC/MPAlgorithm.h index 70f42e2d..51cf976c 100644 --- a/MasterPassword/ObjC/MPAlgorithm.h +++ b/MasterPassword/ObjC/MPAlgorithm.h @@ -25,7 +25,7 @@ @required - (NSUInteger)version; -- (BOOL)migrateUser:(MPUserEntity *)user; +- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc; - (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit; - (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName; diff --git a/MasterPassword/ObjC/MPAlgorithmV0.m b/MasterPassword/ObjC/MPAlgorithmV0.m index 5c24ee67..831bc504 100644 --- a/MasterPassword/ObjC/MPAlgorithmV0.m +++ b/MasterPassword/ObjC/MPAlgorithmV0.m @@ -31,12 +31,12 @@ return 0; } -- (BOOL)migrateUser:(MPUserEntity *)user { +- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc { NSError *error = nil; NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )]; migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user]; - NSArray *migrationElements = [user.managedObjectContext executeFetchRequest:migrationRequest error:&error]; + NSArray *migrationElements = [moc executeFetchRequest:migrationRequest error:&error]; if (!migrationElements) { err(@"While looking for elements to migrate: %@", error); return NO; diff --git a/MasterPassword/ObjC/MPAppDelegate_Key.h b/MasterPassword/ObjC/MPAppDelegate_Key.h index b675b470..b7d18273 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Key.h +++ b/MasterPassword/ObjC/MPAppDelegate_Key.h @@ -10,7 +10,7 @@ @interface MPAppDelegate_Shared(Key) -- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password; +- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password; - (void)signOutAnimated:(BOOL)animated; - (void)storeSavedKeyFor:(MPUserEntity *)user; diff --git a/MasterPassword/ObjC/MPAppDelegate_Key.m b/MasterPassword/ObjC/MPAppDelegate_Key.m index f94639f3..0eb812de 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Key.m +++ b/MasterPassword/ObjC/MPAppDelegate_Key.m @@ -77,7 +77,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) { [[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{ @"animated" : @(animated) }]; } -- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password { +- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password { if (password) NSAssert(![NSThread isMainThread], @"Computing key may not happen from the main thread."); diff --git a/MasterPassword/ObjC/MPAppDelegate_Store.m b/MasterPassword/ObjC/MPAppDelegate_Store.m index 4d067a2d..34e1a85f 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Store.m +++ b/MasterPassword/ObjC/MPAppDelegate_Store.m @@ -493,6 +493,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]]; NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]]; NSString *version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]]; + if ([version length]) + version = [version substringFromIndex:1]; // Strip the leading colon. NSString *name = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]]; NSString *exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]]; @@ -509,6 +511,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext, [elementsToDelete addObjectsFromArray:existingSites]; [importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]]; + dbg(@"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, name=%@, exportContent=%@", + lastUsed, uses, type, version, name, exportContent); } } diff --git a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m index e51697cf..84664997 100644 --- a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m +++ b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m @@ -139,12 +139,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven if (sender == self.rememberPasswordItem) [MPConfig get].rememberLogin = [NSNumber numberWithBool:![[MPConfig get].rememberLogin boolValue]]; if (sender == self.savePasswordItem) { - MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserForThread]; + NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady]; + MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc]; if ((activeUser.saveKey = !activeUser.saveKey)) [[MPMacAppDelegate get] storeSavedKeyFor:activeUser]; else [[MPMacAppDelegate get] forgetSavedKeyFor:activeUser]; - [activeUser.managedObjectContext saveToStore]; + [moc saveToStore]; } if (sender == self.dialogStyleRegular) [MPMacConfig get].dialogStyleHUD = @NO; diff --git a/MasterPassword/ObjC/Mac/MPPasswordWindowController.m b/MasterPassword/ObjC/Mac/MPPasswordWindowController.m index 65ed0eaf..aa18f3e9 100644 --- a/MasterPassword/ObjC/Mac/MPPasswordWindowController.m +++ b/MasterPassword/ObjC/Mac/MPPasswordWindowController.m @@ -256,11 +256,12 @@ - (MPElementEntity *)activeElementForThread { - if (!_activeElementOID) - return nil; + return [self activeElementInContext:[MPMacAppDelegate managedObjectContextForThreadIfReady]]; +} - NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady]; - if (!moc) +- (MPElementEntity *)activeElementInContext:(NSManagedObjectContext *)moc { + + if (!_activeElementOID) return nil; NSError *error; @@ -297,9 +298,10 @@ return; } - MPElementEntity *activeElement = [self activeElementForThread]; + NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady]; + MPElementEntity *activeElement = [self activeElementInContext:moc]; [activeElement use]; - [activeElement.managedObjectContext saveToStore]; + [moc saveToStore]; } dispatch_async( dispatch_get_main_queue(), ^{ diff --git a/MasterPassword/ObjC/iOS/MPElementListController.m b/MasterPassword/ObjC/iOS/MPElementListController.m index 641c4362..abb7e73e 100644 --- a/MasterPassword/ObjC/iOS/MPElementListController.m +++ b/MasterPassword/ObjC/iOS/MPElementListController.m @@ -50,6 +50,10 @@ element.version = MPAlgorithmDefaultVersion; [moc saveToStore]; + NSError *error = nil; + if (element.objectID.isTemporaryID && ![moc obtainPermanentIDsForObjects:@[ element ] error:&error]) + err(@"Failed to obtain a permanent object ID after creating new element: %@", error); + NSManagedObjectID *elementOID = [element objectID]; dispatch_async( dispatch_get_main_queue(), ^{ MPElementEntity *element_ = (MPElementEntity *)[[MPiOSAppDelegate managedObjectContextForThreadIfReady] @@ -292,12 +296,18 @@ forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { - MPElementEntity *element = [self elementForTableIndexPath:indexPath]; - [element.managedObjectContext performBlockAndWait:^{ + NSManagedObjectID *elementOID = [self elementForTableIndexPath:indexPath].objectID; + [MPiOSAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) { + NSError *error = nil; + MPElementEntity *element = (MPElementEntity *)[context existingObjectWithID:elementOID error:&error]; + if (!element) { + err(@"Failed to retrieve element to delete: %@", error); + return; + } inf(@"Deleting element: %@", element.name); - [element.managedObjectContext deleteObject:element]; - [element.managedObjectContext saveToStore]; + [context deleteObject:element]; + [context saveToStore]; MPCheckpoint( MPCheckpointDeleteElement, @{ @"type" : element.typeName, diff --git a/MasterPassword/ObjC/iOS/MPLogsViewController.m b/MasterPassword/ObjC/iOS/MPLogsViewController.m index 37e2513b..99c98e2d 100644 --- a/MasterPassword/ObjC/iOS/MPLogsViewController.m +++ b/MasterPassword/ObjC/iOS/MPLogsViewController.m @@ -71,7 +71,17 @@ - (IBAction)mail:(UIBarButtonItem *)sender { - [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; + if ([[MPiOSConfig get].traceMode boolValue]) { + [PearlAlert showAlertWithTitle:@"Hiding Trace Messages" message: + @"Trace-level log messages will not be mailed. " + @"These messages contain sensitive and personal information." + viewStyle:UIAlertViewStyleDefault initAlert:nil + tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { + [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; + } cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil]; + } + else + [[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self]; } @end diff --git a/MasterPassword/ObjC/iOS/MPMainViewController.m b/MasterPassword/ObjC/iOS/MPMainViewController.m index eeb3dcd3..ca94e307 100644 --- a/MasterPassword/ObjC/iOS/MPMainViewController.m +++ b/MasterPassword/ObjC/iOS/MPMainViewController.m @@ -146,15 +146,15 @@ // Needed for when we appear after a modal VC dismisses: // We can't present until the other modal VC has been fully dismissed and presenting in -viewWillAppear: will fail. - dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{ - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread]; - if ([MPAlgorithmDefault migrateUser:activeUser] && !self.suppressOutdatedAlert) + [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; + if ([MPAlgorithmDefault migrateUser:activeUser inContext:moc] && !self.suppressOutdatedAlert) [UIView animateWithDuration:0.3f animations:^{ self.outdatedAlertContainer.alpha = 1; self.suppressOutdatedAlert = YES; }]; - [activeUser.managedObjectContext saveToStore]; - } ); + [moc saveToStore]; + }]; if (![[MPiOSConfig get].actionsTipShown boolValue]) [UIView animateWithDuration:animated? 0.3f: 0 animations:^{ @@ -506,7 +506,7 @@ @"If you continue, a new password will be generated for this site. " @"You will then need to update your account's old password to this newly generated password.\n\n" @"You can reset the counter by holding down on this button." - do:^BOOL(MPElementEntity *activeElement) { + do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) { if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) { // Not of a type that supports a password counter. err(@"Cannot increment password counter: Element is not generated: %@", activeElement.name); @@ -545,7 +545,7 @@ @"You are resetting the site's password counter.\n\n" @"If you continue, the site's password will change back to its original value. " @"You will then need to update your account's password back to this original value." - do:^BOOL(MPElementEntity *activeElement_) { + do:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) { inf(@"Resetting password counter for: %@", activeElement_.name); ((MPElementGeneratedEntity *)activeElement_).counter = 1; @@ -576,7 +576,8 @@ } ); } -- (void)changeActiveElementWithWarning:(NSString *)warning do:(BOOL (^)(MPElementEntity *activeElement))task; { +- (void)changeActiveElementWithWarning:(NSString *)warning + do:(BOOL (^)(MPElementEntity *activeElement, NSManagedObjectContext *context))task { [PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { @@ -587,7 +588,7 @@ } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil]; } -- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *activeElement))task; { +- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *, NSManagedObjectContext *context))task { [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { MPElementEntity *activeElement = [self activeElementInContext:context]; @@ -595,7 +596,7 @@ return; NSString *oldPassword = [activeElement.content description]; - if (!task( activeElement )) + if (!task( activeElement, context )) return; NSString *newPassword = [activeElement.content description]; @@ -669,7 +670,7 @@ @"This upgrade improves the site's compatibility with the latest version of Master Password."; [self changeActiveElementWithWarning:warning do: - ^BOOL(MPElementEntity *activeElement_) { + ^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) { inf(@"Explicitly migrating element: %@", activeElement_); [activeElement_ migrateExplicitly:YES]; @@ -785,12 +786,12 @@ @"You are about to change the type of this password.\n\n" @"If you continue, the password for this site will change. " @"You will need to update your account's old password to the new one." - do:^BOOL(MPElementEntity *activeElement) { + do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) { if ([activeElement.algorithm classOfType:type] != activeElement.typeClass) { // Type requires a different class of element. Recreate the element. MPElementEntity *newElement = [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type] - inManagedObjectContext:activeElement.managedObjectContext]; + inManagedObjectContext:context]; newElement.name = activeElement.name; newElement.user = activeElement.user; newElement.uses = activeElement.uses; @@ -798,11 +799,10 @@ newElement.version = activeElement.version; newElement.loginName = activeElement.loginName; - [activeElement.managedObjectContext deleteObject:activeElement]; + [context deleteObject:activeElement]; NSError *error; - if (![newElement.managedObjectContext obtainPermanentIDsForObjects:@[ newElement ] - error:&error]) + if (![context obtainPermanentIDsForObjects:@[ newElement ] error:&error]) err(@"Failed to obtain a permanent object ID after changing object type: %@", error); _activeElementOID = newElement.objectID; @@ -819,15 +819,11 @@ - (void)didSelectElement:(MPElementEntity *)element { inf(@"Selected: %@", element.name); - NSError *error = nil; - if (element.objectID.isTemporaryID && ![element.managedObjectContext obtainPermanentIDsForObjects:@[ element ] error:&error]) - err(@"Failed to obtain a permanent object ID after setting active element: %@", error); - _activeElementOID = element.objectID; [self closeAlert]; if (element) { - [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) { + [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) { if ([activeElement use] == 1) [self showAlertWithTitle:@"New Site" message: PearlString( @"You've just created a password for %@.\n\n" @@ -890,7 +886,7 @@ // Content hasn't changed. return; - [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_) { + [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) { ((MPElementStoredEntity *)activeElement_).content = self.contentField.text; return YES; }]; @@ -903,7 +899,7 @@ [MPiOSConfig get].loginNameTipShown = @YES; } - [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) { + [self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) { if ([self.loginNameField.text length]) activeElement.loginName = self.loginNameField.text; else diff --git a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m index 4e58cbb3..45543809 100644 --- a/MasterPassword/ObjC/iOS/MPPreferencesViewController.m +++ b/MasterPassword/ObjC/iOS/MPPreferencesViewController.m @@ -47,9 +47,13 @@ } options:0]; [avatar onSelect:^(BOOL selected) { if (selected) { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + if (!moc) + return; + + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; activeUser.avatar = (unsigned)avatar.tag; - [activeUser.managedObjectContext saveToStore]; + [moc saveToStore]; } } options:0]; avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForThread].avatar); @@ -129,8 +133,12 @@ [[MPiOSAppDelegate get] export]; else if (cell == self.changeMPCell) { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread]; - [[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser inContext:activeUser.managedObjectContext didResetBlock:nil]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + if (!moc) + return; + + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; + [[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil]; } [tableView deselectRowAtIndexPath:indexPath animated:YES]; @@ -140,9 +148,13 @@ - (void)didSelectType:(MPElementType)type { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + if (!moc) + return; + + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; activeUser.defaultType = type; - [activeUser.managedObjectContext saveToStore]; + [moc saveToStore]; self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType]; } @@ -156,12 +168,16 @@ - (IBAction)didToggleSwitch:(UISwitch *)sender { - MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + if (!moc) + return; + + MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc]; if ((activeUser.saveKey = sender.on)) [[MPiOSAppDelegate get] storeSavedKeyFor:activeUser]; else [[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser]; - [activeUser.managedObjectContext saveToStore]; + [moc saveToStore]; } @end diff --git a/MasterPassword/ObjC/iOS/MPUnlockViewController.m b/MasterPassword/ObjC/iOS/MPUnlockViewController.m index c1b3ce03..5803a847 100644 --- a/MasterPassword/ObjC/iOS/MPUnlockViewController.m +++ b/MasterPassword/ObjC/iOS/MPUnlockViewController.m @@ -345,20 +345,19 @@ [self.avatarToUserOID setObject:NilToNSNull([user objectID]) forKey:[NSValue valueWithNonretainedObject:avatar]]; - if ([_selectedUserOID isEqual:[user objectID]]) { - self.selectedUser = user; + if ([_selectedUserOID isEqual:[user objectID]]) avatar.selected = YES; - } return avatar; } - (void)didToggleUserSelection { - MPUserEntity *selectedUser = [self selectedUserForThread]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + MPUserEntity *selectedUser = [self selectedUserInContext:moc]; if (!selectedUser) [self.passwordField resignFirstResponder]; - else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser inContext:selectedUser.managedObjectContext usingMasterPassword:nil]) { + else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser saveInContext:moc usingMasterPassword:nil]) { [self performSegueWithIdentifier:@"MP_Unlock" sender:self]; return; } @@ -450,7 +449,12 @@ } // Confirm - [moc saveToStore]; + [moc performBlockAndWait:^{ + [moc saveToStore]; + NSError *error = nil; + if (![moc obtainPermanentIDsForObjects:@[newUser] error:&error]) + err(@"Failed to obtain permanent object ID for new user: %@", error); + }]; completion( YES ); [self updateUsers]; @@ -535,7 +539,7 @@ UIButton *targetedAvatar = selectedAvatar; if (!targetedAvatar) { targetedAvatar = [self findTargetedAvatar]; - targetedUser = [self userForAvatar:targetedAvatar]; + targetedUser = [self userForAvatar:targetedAvatar inContext:[MPiOSAppDelegate managedObjectContextForThreadIfReady]]; } [self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) { @@ -619,7 +623,7 @@ [self setSpinnerActive:YES]; [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { - BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] inContext:moc + BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] saveInContext:moc usingMasterPassword:self.passwordField.text]; dispatch_async( dispatch_get_main_queue(), ^{ @@ -656,11 +660,7 @@ return avatar; } -- (MPUserEntity *)userForAvatar:(UIButton *)avatar { - - NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; - if (!moc) - return nil; +- (MPUserEntity *)userForAvatar:(UIButton *)avatar inContext:(NSManagedObjectContext *)moc { NSManagedObjectID *userOID = NSNullToNil([self.avatarToUserOID objectForKey:[NSValue valueWithNonretainedObject:avatar]]); if (!userOID) @@ -984,11 +984,11 @@ if ([self selectedUserForThread]) return; - MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar]]; + NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady]; + MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar] inContext:moc]; if (!targetedUser) return; - NSManagedObjectContext *moc = targetedUser.managedObjectContext; [PearlSheet showSheetWithTitle:targetedUser.name viewStyle:UIActionSheetStyleBlackTranslucent initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) { @@ -1008,7 +1008,7 @@ } if (buttonIndex == [sheet firstOtherButtonIndex]) - [[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser inContext:moc didResetBlock:^{ + [[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser saveInContext:moc didResetBlock:^{ dispatch_async( dispatch_get_main_queue(), ^{ [[self avatarForUser:targetedUser] setSelected:YES]; } ); diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h index 388dbc83..2f63ef33 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.h @@ -20,6 +20,6 @@ - (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; - (void)export; -- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset; +- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset; @end diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m index f4b79ada..7b924d11 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m @@ -470,9 +470,9 @@ - (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController { NSString *userName = [[MPiOSAppDelegate get] activeUserForThread].name; - PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo; - if ([[MPiOSConfig get].traceMode boolValue]) - logLevel = PearlLogLevelTrace; + PearlLogLevel logLevel = PearlLogLevelInfo; + if (logs && ([[MPiOSConfig get].sendInfo boolValue] || [[MPiOSConfig get].traceMode boolValue])) + logLevel = PearlLogLevelDebug; [[[PearlEMail alloc] initForEMailTo:@"Master Password Development " subject:PearlString( @"Feedback for Master Password [%@]", @@ -567,7 +567,7 @@ nil]; } -- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset { +- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset { [PearlAlert showAlertWithTitle:@"Changing Master Password" message: diff --git a/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard index 62b24363..589cc276 100644 --- a/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/ObjC/iOS/MainStoryboard_iPhone.storyboard @@ -492,28 +492,28 @@ Your passwords will be AES-encrypted with your master password. - 119-20:51:52 MPiOSAppDelegate.m:36 | INFO : Initializing TestFlight -119-20:51:52 MPiOSAppDelegate.m:70 | INFO : Initializing Google+ -119-20:51:52 MPiOSAppDelegate.m:80 | INFO : Initializing Crashlytics -119-20:51:52 MPiOSAppDelegate.m:109 | INFO : Initializing Localytics -119-20:51:53 PearlAppDelegate.m:71 | INFO : Master Password (MasterPassword) 1.4 (1.4.0) (GIT: 1.4-0-g8a4eecd-dirty) -119-20:51:53 MPiOSAppDelegate.m:257 | INFO : Started up with device identifier: A8C51CDA-6F60-4F0C-BFC9-68A08F2F2DD7 -119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] (Re)loading store... -119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Will load cloud store: 0B3CA2DF-5796-44DF-B5E0-121EC3846464 (definite). -119-20:51:59 PearlConfig.m:193 | INFO : Lock screen will appear -119-20:51:59 MPiOSAppDelegate.m:412 | INFO : Re-activated -119-20:51:59 PearlConfig.m:180 | DEBUG : MPiOSConfig.launchCount = [70 ->] 71 -119-20:52:02 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Clearing stores... -119-20:52:03 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Loading store without seeding. -119-20:52:09 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Cloud enabled and successfully loaded cloud store. -119-20:52:09 MPAppDelegate_Store.m:299 | INFO : Using iCloud? 1 -119-20:52:12 MPAppDelegate_Key.m:28 | INFO : Found key in keychain for: b55911588b178466be1d6392597e899b8de46f9a -119-20:52:12 MPAppDelegate_Key.m:132 | INFO : Logged in: b55911588b178466be1d6392597e899b8de46f9a -119-20:52:13 MPUnlockViewController.m:229 | INFO : Lock screen will disappear -119-20:52:13 MPMainViewController.m:142 | INFO : Main will appear -119-20:52:16 MPMainViewController.m:734 | INFO : Action: Preferences -119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear. - + 119-20:51:52 MPiOSAppDelegate.m:36 | INFO : Initializing TestFlight +119-20:51:52 MPiOSAppDelegate.m:70 | INFO : Initializing Google+ +119-20:51:52 MPiOSAppDelegate.m:80 | INFO : Initializing Crashlytics +119-20:51:52 MPiOSAppDelegate.m:109 | INFO : Initializing Localytics +119-20:51:53 PearlAppDelegate.m:71 | INFO : Master Password (MasterPassword) 1.4 (1.4.0) (GIT: 1.4-0-g8a4eecd-dirty) +119-20:51:53 MPiOSAppDelegate.m:257 | INFO : Started up with device identifier: A8C51CDA-6F60-4F0C-BFC9-68A08F2F2DD7 +119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] (Re)loading store... +119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Will load cloud store: 0B3CA2DF-5796-44DF-B5E0-121EC3846464 (definite). +119-20:51:59 PearlConfig.m:193 | INFO : Lock screen will appear +119-20:51:59 MPiOSAppDelegate.m:412 | INFO : Re-activated +119-20:51:59 PearlConfig.m:180 | DEBUG : MPiOSConfig.launchCount = [70 ->] 71 +119-20:52:02 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Clearing stores... +119-20:52:03 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Loading store without seeding. +119-20:52:09 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Cloud enabled and successfully loaded cloud store. +119-20:52:09 MPAppDelegate_Store.m:299 | INFO : Using iCloud? 1 +119-20:52:12 MPAppDelegate_Key.m:28 | INFO : Found key in keychain for: b55911588b178466be1d6392597e899b8de46f9a +119-20:52:12 MPAppDelegate_Key.m:132 | INFO : Logged in: b55911588b178466be1d6392597e899b8de46f9a +119-20:52:13 MPUnlockViewController.m:229 | INFO : Lock screen will disappear +119-20:52:13 MPMainViewController.m:142 | INFO : Main will appear +119-20:52:16 MPMainViewController.m:734 | INFO : Action: Preferences +119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear. + @@ -2916,6 +2916,204 @@ However, it means that anyone who finds your device unlocked can do the same. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +