diff --git a/platform-darwin/Source/MPAlgorithmV0.m b/platform-darwin/Source/MPAlgorithmV0.m index 01074990..f984322b 100644 --- a/platform-darwin/Source/MPAlgorithmV0.m +++ b/platform-darwin/Source/MPAlgorithmV0.m @@ -621,7 +621,7 @@ static NSOperationQueue *_mpwQueue = nil; - (NSString *)exportLoginForSite:(MPSiteEntity *)site usingKey:(MPKey *)key { - if (!(site.type & MPSiteFeatureExportContent) || site.loginGenerated || ![site.loginName length]) + if (site.loginGenerated || ![site.loginName length]) return nil; __block NSData *state = nil; diff --git a/platform-darwin/Source/MPAppDelegate_Store.m b/platform-darwin/Source/MPAppDelegate_Store.m index 28365a1f..65fb5674 100644 --- a/platform-darwin/Source/MPAppDelegate_Store.m +++ b/platform-darwin/Source/MPAppDelegate_Store.m @@ -719,6 +719,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); return nil; } + MPKey *key = [[MPKey alloc] initForFullName:user.name withMasterPassword:masterPassword]; exportUser = mpw_marshal_user( user.name.UTF8String, mpw_masterKeyProvider_str( masterPassword.UTF8String ), user.algorithm.version ); exportUser->redacted = !revealPasswords; @@ -731,11 +732,10 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted ); MPCounterValue counter = MPCounterValueInitial; if ([site isKindOfClass:[MPGeneratedSiteEntity class]]) counter = ((MPGeneratedSiteEntity *)site).counter; - MPMarshalledSite *exportSite = mpw_marshal_site( exportUser, - site.name.UTF8String, site.type, counter, site.algorithm.version ); - exportSite->resultState = mpw_strdup( [site.algorithm exportPasswordForSite:site usingKey:self.key].UTF8String ); - exportSite->loginState = mpw_strdup( [site.algorithm exportLoginForSite:site usingKey:self.key].UTF8String ); - exportSite->loginType = site.loginGenerated? MPResultTypeTemplateName: MPResultTypeStatefulPersonal; + MPMarshalledSite *exportSite = mpw_marshal_site( exportUser, site.name.UTF8String, site.type, counter, site.algorithm.version ); + exportSite->resultState = mpw_strdup( [site.algorithm exportPasswordForSite:site usingKey:key].UTF8String ); + exportSite->loginState = mpw_strdup( [site.algorithm exportLoginForSite:site usingKey:key].UTF8String ); + exportSite->loginType = site.loginGenerated || !exportSite->loginState? MPResultTypeTemplateName: MPResultTypeStatefulPersonal; exportSite->url = mpw_strdup( site.url.UTF8String ); exportSite->uses = (unsigned int)site.uses; exportSite->lastUsed = (time_t)site.lastUsed.timeIntervalSince1970; diff --git a/platform-darwin/Source/Mac/MPMacAppDelegate.m b/platform-darwin/Source/Mac/MPMacAppDelegate.m index 7a11a5e9..eeb585da 100644 --- a/platform-darwin/Source/Mac/MPMacAppDelegate.m +++ b/platform-darwin/Source/Mac/MPMacAppDelegate.m @@ -546,15 +546,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven return; } - if (!self.key) { - NSAlert *alert = [NSAlert new]; - alert.messageText = @"User Locked"; - alert.informativeText = @"To export your sites, first unlock your user by opening Master Password."; - [alert runModal]; - [self showPopup:nil]; - return; - } - NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; [exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; @@ -579,43 +570,46 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven if ([savePanel runModal] == NSFileHandlingPanelCancelButton) return; - [self exportSitesRevealPasswords:revealPasswords - askExportPassword:^NSString *(NSString *userName) { - return PearlMainQueueAwait( ^id { - NSAlert *alert = [NSAlert new]; - [alert addButtonWithTitle:@"Import"]; - [alert addButtonWithTitle:@"Cancel"]; - alert.messageText = strf( @"Master Password For\n%@", userName ); - alert.informativeText = @"Enter the current master password for this user."; - alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )]; - [alert layout]; - if ([alert runModal] == NSAlertFirstButtonReturn) - return ((NSTextField *)alert.accessoryView).stringValue; - else - return nil; - } ); - } result:^(NSString *mpsites, NSError *error) { - if (!mpsites || error) { - PearlMainQueue( ^{ - [[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal]; + [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { + NSError *error = nil; + NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword: + ^NSString *(NSString *userName) { + return PearlMainQueueAwait( ^id { + NSAlert *alert = [NSAlert new]; + [alert addButtonWithTitle:@"Export"]; + [alert addButtonWithTitle:@"Cancel"]; + alert.messageText = strf( @"Master Password For\n%@", userName ); + alert.informativeText = @"Enter the current master password for this user."; + alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )]; + [alert layout]; + if ([alert runModal] == NSAlertFirstButtonReturn) + return ((NSTextField *)alert.accessoryView).stringValue; + else + return nil; } ); - return; - } + } error:&error]; - NSError *coordinateError = nil; - [[[NSFileCoordinator alloc] initWithFilePresenter:nil] - coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) { - NSError *writeError = nil; - if (![mpsites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError]) - PearlMainQueue( ^{ - [[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal]; - } ); - }]; - if (coordinateError) - PearlMainQueue( ^{ - [[NSAlert alertWithError:MPError( coordinateError, @"Could not gain access to the export file." )] runModal]; - } ); - }]; + if (error) + PearlMainQueue( ^{ + [[NSAlert alertWithError:MPError( error, @"Failed to export mpsites." )] runModal]; + } ); + if (!exportedUser) + return; + + NSError *coordinateError = nil; + [[[NSFileCoordinator alloc] initWithFilePresenter:nil] + coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError byAccessor:^(NSURL *newURL) { + NSError *writeError = nil; + if (![exportedUser writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError]) + PearlMainQueue( ^{ + [[NSAlert alertWithError:MPError( writeError, @"Could not write to the export file." )] runModal]; + } ); + }]; + if (coordinateError) + PearlMainQueue( ^{ + [[NSAlert alertWithError:MPError( coordinateError, @"Could not gain access to the export file." )] runModal]; + } ); + }]; } - (void)updateUsers { diff --git a/platform-darwin/Source/iOS/MPiOSAppDelegate.m b/platform-darwin/Source/iOS/MPiOSAppDelegate.m index 333dbfb5..0d94a92a 100644 --- a/platform-darwin/Source/iOS/MPiOSAppDelegate.m +++ b/platform-darwin/Source/iOS/MPiOSAppDelegate.m @@ -626,25 +626,29 @@ [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { NSError *error = nil; - NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) { - return PearlAwait( ^(void (^setResult)(id)) { - PearlMainQueue( ^{ - UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName ) - message:@"Enter your master password to export the user." - preferredStyle:UIAlertControllerStyleAlert]; - [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { - textField.secureTextEntry = YES; - }]; - [alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - setResult( alert.textFields.firstObject.text ); - }]]; - [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { - setResult( nil ); - }]]; - [self.navigationController presentViewController:alert animated:YES completion:nil]; - } ); - } ); - } error:&error]; + NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword: + ^NSString *(NSString *userName) { + return PearlAwait( ^(void (^setResult)(id)) { + PearlMainQueue( ^{ + UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( + @"Master Password For:\n%@", userName ) + message:@"Enter your master password to export the user." + preferredStyle:UIAlertControllerStyleAlert]; + [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.secureTextEntry = YES; + }]; + [alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + setResult( alert.textFields.firstObject.text ); + }]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel + handler:^(UIAlertAction *action) { + setResult( nil ); + }]]; + [self.navigationController presentViewController:alert animated:YES completion:nil]; + } ); + } ); + } error:&error]; PearlMainQueue( ^{ if (error) {