From 85dab509965156e41aa0c281554f771be965570c Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Wed, 22 Oct 2014 21:17:02 -0400 Subject: [PATCH] More robust against exceptions and a few other fixes. --- External/Pearl | 2 +- MasterPassword/C/build | 9 +- MasterPassword/ObjC/MPAppDelegate_Store.m | 34 ++++++- MasterPassword/ObjC/MPEntities.m | 15 ++- MasterPassword/ObjC/iOS/MPPasswordCell.m | 7 +- .../ObjC/iOS/MPPasswordsViewController.m | 94 +++++++++++-------- 6 files changed, 106 insertions(+), 55 deletions(-) diff --git a/External/Pearl b/External/Pearl index 717bc5e5..3c7b13b3 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit 717bc5e5e7be3aedb997581260b67579eb651f8e +Subproject commit 3c7b13b3649c92f7d30e4b8bd0570c8c6b1798c6 diff --git a/MasterPassword/C/build b/MasterPassword/C/build index e2795a2c..0c83ed8a 100755 --- a/MasterPassword/C/build +++ b/MasterPassword/C/build @@ -32,6 +32,13 @@ fi ### DEPENDENCIES +digest() { + if hash xxd 2>/dev/null; then + openssl sha1 -binary < "$1" | xxd -p + else + openssl sha1 < "$1" | sed 's/.* //' + fi +} fetch() { if hash wget 2>/dev/null; then wget -O "${1##*/}" "$1" @@ -54,7 +61,7 @@ unpack() { fi printf 'Verifying package: %s, against digest: %s...' "$1" "$2" - [[ $(openssl sha < "$1") = $2 ]] || { + [[ $(digest "$1") = $2 ]] || { printf ' mismatch!\n' echo 2>&1 "Downloaded package doesn't match digest." exit 1 diff --git a/MasterPassword/ObjC/MPAppDelegate_Store.m b/MasterPassword/ObjC/MPAppDelegate_Store.m index 48facc4c..cb8a27bb 100644 --- a/MasterPassword/ObjC/MPAppDelegate_Store.m +++ b/MasterPassword/ObjC/MPAppDelegate_Store.m @@ -56,7 +56,11 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); return NO; [mainManagedObjectContext performBlock:^{ - mocBlock( mainManagedObjectContext ); + @try { + mocBlock( mainManagedObjectContext ); + } @catch (NSException *exception) { + err( @"While performing managed block:\n%@", [exception fullDescription] ); + } }]; return YES; @@ -69,7 +73,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); return NO; [mainManagedObjectContext performBlockAndWait:^{ - mocBlock( mainManagedObjectContext ); + @try { + mocBlock( mainManagedObjectContext ); + } + @catch (NSException *exception) { + err( @"While performing managed block:\n%@", [exception fullDescription] ); + } }]; return YES; @@ -84,7 +93,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; moc.parentContext = privateManagedObjectContextIfReady; [moc performBlock:^{ - mocBlock( moc ); + @try { + mocBlock( moc ); + } + @catch (NSException *exception) { + err( @"While performing managed block:\n%@", [exception fullDescription] ); + } }]; return YES; @@ -99,7 +113,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; moc.parentContext = privateManagedObjectContextIfReady; [moc performBlockAndWait:^{ - mocBlock( moc ); + @try { + mocBlock( moc ); + } + @catch (NSException *exception) { + err( @"While performing managed block:\n%@", [exception fullDescription] ); + } }]; return YES; @@ -195,7 +214,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); ^(NSNotification *note) { // When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext. [self.mainManagedObjectContext performBlock:^{ - [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note]; + @try { + [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note]; + } + @catch (NSException *exception) { + err( @"While merging changes:\n%@", [exception fullDescription] ); + } }]; }]; diff --git a/MasterPassword/ObjC/MPEntities.m b/MasterPassword/ObjC/MPEntities.m index 1c6a6c37..b69d90a7 100644 --- a/MasterPassword/ObjC/MPEntities.m +++ b/MasterPassword/ObjC/MPEntities.m @@ -23,7 +23,7 @@ } @catch (NSException *exception) { success = NO; - err( @"While saving: %@", exception ); + err( @"While saving: %@", [exception fullDescription] ); } }]; } @@ -128,10 +128,15 @@ - (NSString *)debugDescription { - return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}", - NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed, - (long)self.version, - self.loginName, self.requiresExplicitMigration ); + @try { + return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}", + NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed, + (long)self.version, + self.loginName, self.requiresExplicitMigration ); + } @catch (NSException *exception) { + return strf( @"{%@: inaccessible: %@}", + NSStringFromClass( [self class] ), [exception fullDescription] ); + } } - (BOOL)tryMigrateExplicitly:(BOOL)explicit { diff --git a/MasterPassword/ObjC/iOS/MPPasswordCell.m b/MasterPassword/ObjC/iOS/MPPasswordCell.m index 079fe2aa..b2140d18 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordCell.m +++ b/MasterPassword/ObjC/iOS/MPPasswordCell.m @@ -257,8 +257,11 @@ return; [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { - [context deleteObject:[self siteInContext:context]]; - [context saveToStore]; + MPSiteEntity *site_ = [self siteInContext:context]; + if (site_) { + [context deleteObject:site_]; + [context saveToStore]; + } }]; } cancelTitle:@"Cancel" destructiveTitle:@"Delete Site" otherTitles:nil]; } diff --git a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m index 16c62270..9b33266c 100644 --- a/MasterPassword/ObjC/iOS/MPPasswordsViewController.m +++ b/MasterPassword/ObjC/iOS/MPPasswordsViewController.m @@ -64,7 +64,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { self.view.backgroundColor = [UIColor clearColor]; [self.passwordCollectionView automaticallyAdjustInsetsForKeyboard]; self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone; - if ([self.passwordsSearchBar respondsToSelector:@selector(keyboardAppearance)]) + if ([self.passwordsSearchBar respondsToSelector:@selector( keyboardAppearance )]) self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark; else [self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) { @@ -170,23 +170,29 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { if (controller == _fetchedResultsController) { - [self.passwordCollectionView performBatchUpdates:^{ - [self fetchedItemsDidUpdate]; - switch (type) { - case NSFetchedResultsChangeInsert: - [self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]]; - break; - case NSFetchedResultsChangeDelete: - [self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]]; - break; - case NSFetchedResultsChangeMove: - [self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; - break; - case NSFetchedResultsChangeUpdate: - [self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]]; - break; - } - } completion:nil]; + @try { + [self.passwordCollectionView performBatchUpdates:^{ + [self fetchedItemsDidUpdate]; + switch (type) { + case NSFetchedResultsChangeInsert: + [self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]]; + break; + case NSFetchedResultsChangeDelete: + [self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]]; + break; + case NSFetchedResultsChangeMove: + [self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; + break; + case NSFetchedResultsChangeUpdate: + [self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]]; + break; + } + } completion:nil]; + } + @catch (NSException *exception) { + wrn( @"While updating password cells: %@", [exception fullDescription] ); + [self.passwordCollectionView reloadData]; + } } } @@ -249,7 +255,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { if (searchBar == self.passwordsSearchBar) { if ([self.query length] && [[self.query stringByTrimmingCharactersInSet:_siteNameAcceptableCharactersSet] length]) [self showTips:MPPasswordsBadNameTip]; - + [self updatePasswords]; } } @@ -261,7 +267,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { [UIView animateWithDuration:0.3f animations:^{ if (showTips & MPPasswordsBadNameTip) self.badNameTipContainer.alpha = 1; - } completion:^(BOOL finished) { + } completion:^(BOOL finished) { if (finished) PearlMainQueueAfter( 5, ^{ [UIView animateWithDuration:0.3f animations:^{ @@ -375,28 +381,34 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) { if (![self.fetchedResultsController performFetch:&error]) err( @"Couldn't fetch sites: %@", [error fullDescription] ); - [self.passwordCollectionView performBatchUpdates:^{ - [self fetchedItemsDidUpdate]; + @try { + [self.passwordCollectionView performBatchUpdates:^{ + [self fetchedItemsDidUpdate]; - NSInteger fromSections = self.passwordCollectionView.numberOfSections; - NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView]; - for (NSInteger section = 0; section < MAX( toSections, fromSections ); ++section) { - if (section >= fromSections) - [self.passwordCollectionView insertSections:[NSIndexSet indexSetWithIndex:section]]; - else if (section >= toSections) - [self.passwordCollectionView deleteSections:[NSIndexSet indexSetWithIndex:section]]; - else if (section < [oldSections count]) - [self.passwordCollectionView reloadItemsFromArray:oldSections[section] - toArray:[[self.fetchedResultsController sections][section] objects] - inSection:section]; - else - [self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:section]]; - } - } completion:^(BOOL finished) { - if (finished) - [self.passwordCollectionView setContentOffset:CGPointMake( 0, -self.passwordCollectionView.contentInset.top ) - animated:YES]; - }]; + NSInteger fromSections = self.passwordCollectionView.numberOfSections; + NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView]; + for (NSInteger section = 0; section < MAX( toSections, fromSections ); ++section) { + if (section >= fromSections) + [self.passwordCollectionView insertSections:[NSIndexSet indexSetWithIndex:section]]; + else if (section >= toSections) + [self.passwordCollectionView deleteSections:[NSIndexSet indexSetWithIndex:section]]; + else if (section < [oldSections count]) + [self.passwordCollectionView reloadItemsFromArray:oldSections[section] + toArray:[[self.fetchedResultsController sections][section] objects] + inSection:section]; + else + [self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:section]]; + } + } completion:^(BOOL finished) { + if (finished) + [self.passwordCollectionView setContentOffset:CGPointMake( 0, -self.passwordCollectionView.contentInset.top ) + animated:YES]; + }]; + } + @catch (NSException *exception) { + wrn( @"While updating password cells: %@", [exception fullDescription] ); + [self.passwordCollectionView reloadData]; + } }]; }