diff --git a/Cartfile b/Cartfile index e968e925..79f4f88e 100644 --- a/Cartfile +++ b/Cartfile @@ -1,3 +1,3 @@ github "sparkle-project/Sparkle" ~> 1.13.1 github "mstarke/KeePassKit" "bf47781a618fc514288315995a966b5f630f6918" -github "mstarke/HNHUi" ~> 1.0 +github "mstarke/HNHUi" ~> 1.1 diff --git a/Cartfile.resolved b/Cartfile.resolved index aa9a310c..a9012e78 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ -github "mstarke/HNHUi" "1.0.1" +github "mstarke/HNHUi" "1.1" github "mstarke/KeePassKit" "bf47781a618fc514288315995a966b5f630f6918" github "sparkle-project/Sparkle" "1.14.0" diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index cadb5d27..4f6ffb89 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -2187,7 +2187,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2/**"; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-lxml2"; SDKROOT = macosx; @@ -2221,7 +2221,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(SDKROOT)/usr/include/libxml2/**"; - MACOSX_DEPLOYMENT_TARGET = 10.8; + MACOSX_DEPLOYMENT_TARGET = 10.9; OTHER_LDFLAGS = "-lxml2"; SDKROOT = macosx; }; diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index 9b001bc5..f2c3dcf3 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -32,6 +32,7 @@ #import "MPSavePanelAccessoryViewController.h" #import "MPTreeDelegate.h" #import "MPTargetNodeResolving.h" +#import "MPErrorRecoveryAttempter.h" #import "KeePassKit/KeePassKit.h" @@ -154,9 +155,17 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou if(self.compositeKey.hasPasswordOrKeyFile) { return YES; // key is set, so autosave should be save } - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"NO_PASSWORD_OR_KEY_SET", "") }; + + MPErrorRecoveryAttempter *recovery = [[MPErrorRecoveryAttempter alloc] init]; + recovery.document = self; + + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"WARNING_ON_SAVE_NO_PASSWORD_OR_KEY_SET", ""), + NSLocalizedRecoverySuggestionErrorKey : NSLocalizedString(@"WARNING_ON_SAVE_NO_PASSWORD_OR_KEY_SET_SUGGESTION", ""), + NSLocalizedRecoveryOptionsErrorKey : @[ NSLocalizedString(@"CHANGE_PASSWORD_WITH_DOTS", ""), NSLocalizedString(@"CANCEL", "") ], + NSRecoveryAttempterErrorKey : recovery + }; if(outError != NULL) { - *outError = [NSError errorWithDomain:MPErrorDomain code:0 userInfo:userInfo]; + *outError = [NSError errorWithDomain:MPErrorDomain code:MPErrorNoPasswordOrKeyFile userInfo:userInfo]; } return NO; } @@ -167,7 +176,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou } if(!self.compositeKey.hasPasswordOrKeyFile) { if(outError != NULL) { - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"NO_PASSWORD_OR_KEY_SET", "") }; + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: NSLocalizedString(@"WARNING_ON_SAVE_NO_PASSWORD_OR_KEY_SET", "") }; *outError = [NSError errorWithDomain:MPErrorDomain code:0 userInfo:userInfo]; } return nil; // Saving without a password/key is not possible @@ -573,13 +582,11 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "Cancel")]; alert.buttons.lastObject.keyEquivalent = [NSString stringWithFormat:@"%c", 0x1b]; - [alert beginSheetModalForWindow:self.windowForSheet modalDelegate:self didEndSelector:@selector(_emptyTrashAlertDidEnd:returnCode:contextInfo:) contextInfo:NULL]; -} - -- (void)_emptyTrashAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - if(returnCode == NSAlertFirstButtonReturn) { - [self _emptyTrash]; - } + [alert beginSheetModalForWindow:self.windowForSheet completionHandler:^(NSModalResponse returnCode) { + if(returnCode == NSAlertFirstButtonReturn) { + [self _emptyTrash]; + } + }]; } - (void)_presentTrashAlertForItem:(KPKNode *)node { @@ -595,22 +602,19 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "Cancel")]; alert.buttons.lastObject.keyEquivalent = [NSString stringWithFormat:@"%c", 0x1b]; - [alert beginSheetModalForWindow:self.windowForSheet modalDelegate:self didEndSelector:@selector(_deleteTrashedItemAlertDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void *)(node)]; -} - -- (void)_deleteTrashedItemAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - if(returnCode == NSAlertFirstButtonReturn) { - KPKNode *node = (__bridge KPKNode *)(contextInfo); - /* No undo on this operation */ - for( KPKEntry *entry in node.asGroup.childEntries) { - [node.undoManager removeAllActionsWithTarget:entry]; + [alert beginSheetModalForWindow:self.windowForSheet completionHandler:^(NSModalResponse returnCode) { + if(returnCode == NSAlertFirstButtonReturn) { + /* No undo on this operation */ + for( KPKEntry *entry in node.asGroup.childEntries) { + [node.undoManager removeAllActionsWithTarget:entry]; + } + for(KPKGroup *group in node.asGroup.childGroups) { + [node.undoManager removeAllActionsWithTarget:group]; + } + //[self.undoManager setActionIsDiscardable:YES]; + [node remove]; } - for(KPKGroup *group in node.asGroup.childGroups) { - [node.undoManager removeAllActionsWithTarget:group]; - } - //[self.undoManager setActionIsDiscardable:YES]; - [node remove]; - } + }]; } - (void)createEntryFromTemplate:(id)sender { diff --git a/MacPass/MPDocumentWindowController.h b/MacPass/MPDocumentWindowController.h index d57f702e..2596a5c6 100644 --- a/MacPass/MPDocumentWindowController.h +++ b/MacPass/MPDocumentWindowController.h @@ -17,7 +17,7 @@ @class MPOutlineViewController; @class MPToolbarDelegate; -@interface MPDocumentWindowController : NSWindowController +@interface MPDocumentWindowController : NSWindowController @property (readonly, strong) MPPasswordInputController *passwordInputController; @property (readonly, strong) MPEntryViewController *entryViewController; @@ -31,6 +31,8 @@ - (void)showEntries; - (void)showPasswordInput; + +- (void)editPasswordWithCompetionHandler:(void (^)(NSInteger result))handler; #pragma mark Actions - (IBAction)saveDocument:(id)sender; - (IBAction)saveDocumentAs:(id)sender; @@ -62,8 +64,4 @@ - (IBAction)focusEntries:(id)sender; - (IBAction)focusInspector:(id)sender; - -#pragma mark MPPasswordEditWindowDelegater -- (void)didFinishPasswordEditing:(BOOL)changedPasswordOrKey; - @end diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m index 69cf4dc9..a9702b13 100644 --- a/MacPass/MPDocumentWindowController.m +++ b/MacPass/MPDocumentWindowController.m @@ -51,7 +51,7 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); @property (strong) MPToolbarDelegate *toolbarDelegate; @property (strong) MPFixAutotypeWindowController *fixAutotypeWindowController; -@property (nonatomic, copy) MPPasswordChangedBlock passwordChangedBlock; +//@property (nonatomic, copy) MPPasswordChangedBlock passwordChangedBlock; @end @@ -189,7 +189,6 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); #pragma mark Actions - (void)saveDocument:(id)sender { - self.passwordChangedBlock = nil; MPDocument *document = self.document; NSString *fileType = document.fileType; /* we did open as legacy */ @@ -203,31 +202,44 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); [alert addButtonWithTitle:NSLocalizedString(@"SAVE_LOSSY", "Save lossy")]; [alert addButtonWithTitle:NSLocalizedString(@"CHANGE_FORMAT", "")]; [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "Cancel")]; - - [alert beginSheetModalForWindow:self.window - modalDelegate:self - didEndSelector:@selector(_dataLossOnSaveAlertDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; + __weak MPDocumentWindowController *welf = self; + [alert beginSheetModalForWindow:[welf.document windowForSheet] completionHandler:^(NSModalResponse returnCode) { + switch(returnCode) { + case NSAlertFirstButtonReturn: + /* Save lossy */ + [welf.document saveDocument:nil]; + return; + + case NSAlertSecondButtonReturn: + [alert.window orderOut:nil]; + [welf.document saveDocumentAs:nil]; + return; + + case NSAlertThirdButtonReturn: + default: + return; // Cancel or unknown + } + }]; return; } } else if(!document.compositeKey) { - __weak MPDocument *weakDocument = [self document]; - self.passwordChangedBlock = ^void(BOOL didChangePassword){ - if(didChangePassword) { + __weak MPDocument *weakDocument = self.document; + + [self editPasswordWithCompetionHandler:^(NSInteger result) { + if(result == NSModalResponseOK) { [weakDocument saveDocument:sender]; } - }; - [self editPassword:nil]; + }]; return; } else if(document.shouldEnforcePasswordChange) { __weak MPDocument *weakDocument = [self document]; - self.passwordChangedBlock = ^void(BOOL didChangePassword){ - if(didChangePassword) { - [weakDocument saveDocument:nil]; + [self editPasswordWithCompetionHandler:^(NSInteger result) { + if(result == NSModalResponseOK) { + [weakDocument saveDocument:sender]; } - }; + }]; [self _presentPasswordIntervalAlerts]; return; } @@ -235,20 +247,18 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); [self.document saveDocument:sender]; } - (void)saveDocumentAs:(id)sender { - self.passwordChangedBlock = nil; MPDocument *document = [self document]; if(document.compositeKey) { [[self document] saveDocumentAs:sender]; return; } /* we need to make sure that a password is set */ - __weak MPDocument *weakDocument = [self document]; - self.passwordChangedBlock = ^void(BOOL didChangePassword){ - if(didChangePassword) { + __weak MPDocument *weakDocument = self.document; + [self editPasswordWithCompetionHandler:^(NSInteger result) { + if(result == NSModalResponseOK) { [weakDocument saveDocumentAs:sender]; } - }; - [self editPassword:nil]; + }]; } - (void)exportAsXML:(id)sender { @@ -303,15 +313,16 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); - (void)editPasswordWithCompetionHandler:(void (^)(NSInteger result))handler { if(!self.passwordEditWindowController) { self.passwordEditWindowController = [[MPPasswordEditWindowController alloc] init]; - self.passwordEditWindowController.delegate = self; } [self.document addWindowController:self.passwordEditWindowController]; - [NSApp beginSheet:self.passwordEditWindowController.window - modalForWindow:self.window - modalDelegate:self - didEndSelector:@selector(_editPasswordSheetDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; + [self.window beginSheet:self.passwordEditWindowController.window completionHandler:^(NSModalResponse returnCode) { + if(handler) { + handler(returnCode); + } + [self.passwordEditWindowController.document removeWindowController:self.passwordEditWindowController]; + self.passwordEditWindowController = nil; + }]; } - (void)showDatabaseSettings:(id)sender { @@ -480,14 +491,6 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); return ([[self document] validateMenuItem:menuItem]); } -#pragma mark MPPasswordEditWindowDelegate -- (void)didFinishPasswordEditing:(BOOL)changedPasswordOrKey { - if(self.passwordChangedBlock) { - self.passwordChangedBlock(changedPasswordOrKey); - } - self.passwordChangedBlock = nil; -} - #pragma mark NSAlert handling - (void)_presentPasswordIntervalAlerts { MPDocument *document = [self document]; @@ -502,10 +505,15 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "")]; alert.buttons[1].keyEquivalent = [NSString stringWithFormat:@"%c", 0x1b]; - [alert beginSheetModalForWindow:self.window - modalDelegate:self - didEndSelector:@selector(_enforcePasswordChangeAlertDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; + [alert beginSheetModalForWindow:[self.document windowForSheet] completionHandler:^(NSModalResponse returnCode) { + if(NSAlertSecondButtonReturn == returnCode) { + return; + } + id __weak welf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [welf editPassword:nil]; + }); + }]; } else if(document.shouldRecommendPasswordChange) { NSAlert *alert = [[NSAlert alloc] init]; @@ -518,77 +526,30 @@ typedef void (^MPPasswordChangedBlock)(BOOL didChangePassword); [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "")]; alert.buttons[1].keyEquivalent = [NSString stringWithFormat:@"%c", 0x1b]; - [alert beginSheetModalForWindow:self.window - modalDelegate:self - didEndSelector:@selector(_recommentPasswordChangeAlertDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; + + [alert beginSheetModalForWindow:[self.document windowForSheet]completionHandler:^(NSModalResponse returnCode) { + if(returnCode == NSAlertSecondButtonReturn) { + return; + } + id __weak welf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [welf editPassword:nil]; + }); + }]; } } -- (void)_dataLossOnSaveAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - - switch(returnCode) { - case NSAlertFirstButtonReturn: - /* Save lossy */ - [self.document saveDocument:nil]; - return; - - case NSAlertSecondButtonReturn: - [alert.window orderOut:nil]; - [self.document saveDocumentAs:nil]; - return; - - case NSAlertThirdButtonReturn: - default: - return; // Cancel or unknown - } -} - -- (void)_recommentPasswordChangeAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - if(returnCode == NSAlertSecondButtonReturn) { - return; - } - id __weak welf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [welf editPassword:nil]; - }); - -} - -- (void)_enforcePasswordChangeAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - if(NSAlertSecondButtonReturn == returnCode) { - return; - } - id __weak welf = self; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [welf editPassword:nil]; - }); -} - #pragma mark Sheet handling -- (void)_editPasswordSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - [self.document removeWindowController:self.passwordEditWindowController]; - self.passwordEditWindowController = nil; -} - -- (void)_settingsSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - /* cleanup the window controller */ - [self.document removeWindowController:self.documentSettingsWindowController]; - self.documentSettingsWindowController = nil; -} - - (void)_showDatabaseSetting:(MPDatabaseSettingsTab)tab { if(!self.documentSettingsWindowController) { self.documentSettingsWindowController = [[MPDatabaseSettingsWindowController alloc] init]; } [self.document addWindowController:self.documentSettingsWindowController]; [self.documentSettingsWindowController showSettingsTab:tab]; - [[NSApplication sharedApplication] beginSheet:self.documentSettingsWindowController.window - modalForWindow:self.window - modalDelegate:self - didEndSelector:@selector(_settingsSheetDidEnd:returnCode:contextInfo:) - contextInfo:NULL]; - + [self.window beginSheet:self.documentSettingsWindowController.window completionHandler:^(NSModalResponse returnCode) { + [self.documentSettingsWindowController.document removeWindowController:self.documentSettingsWindowController]; + self.documentSettingsWindowController = nil; + }]; } #pragma mark - diff --git a/MacPass/MPPasswordEditWindowController.h b/MacPass/MPPasswordEditWindowController.h index a4d1ac17..e5284cfb 100644 --- a/MacPass/MPPasswordEditWindowController.h +++ b/MacPass/MPPasswordEditWindowController.h @@ -34,7 +34,7 @@ @property (weak) IBOutlet NSButton *hasPasswordSwitchButton; //@property (nonatomic,assign) BOOL allowsEmptyPasswordOrKey; -@property (weak) id delegate; +//@property (weak) id delegate; - (IBAction)clearKey:(id)sender; - (IBAction)generateKey:(id)sender; diff --git a/MacPass/MPPasswordEditWindowController.m b/MacPass/MPPasswordEditWindowController.m index 2941ae22..f5344961 100644 --- a/MacPass/MPPasswordEditWindowController.m +++ b/MacPass/MPPasswordEditWindowController.m @@ -67,8 +67,8 @@ [self.changePasswordButton bind:NSEnabledBinding toObject:self withKeyPath:hasValidPasswordOrKeyKeyPath options:nil]; [self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:NSStringFromSelector(@selector(keyURL)) options:nil]; - [self.passwordRepeatTextField setDelegate:self]; - [self.passwordTextField setDelegate:self]; + self.passwordRepeatTextField.delegate = self; + self.passwordTextField.delegate = self; /* Manually initate the first check */ [self _verifyPasswordAndKey]; @@ -80,7 +80,7 @@ if(_showPassword != showPassword) { _showPassword = showPassword; - [self.passwordRepeatTextField setStringValue:@""]; + self.passwordRepeatTextField.stringValue = @""; [self _verifyPasswordAndKey]; } } @@ -94,27 +94,21 @@ } NSString *passwordPlaceHolder = _enablePassword ? NSLocalizedString(@"PASSWORD_INPUT_ENTER_PASSWORD", "") : NSLocalizedString(@"PASSWORD_INPUT_NO_PASSWORD", ""); NSString *repeatPlaceHolder = _enablePassword ? NSLocalizedString(@"PASSWORD_INPUT_REPEAT_PASSWORD", "") : NSLocalizedString(@"PASSWORD_INPUT_NO_PASSWORD", ""); - [[self.passwordTextField cell] setPlaceholderString:passwordPlaceHolder]; - [[self.passwordRepeatTextField cell] setPlaceholderString:repeatPlaceHolder]; + [self.passwordTextField.cell setPlaceholderString:passwordPlaceHolder]; + [self.passwordRepeatTextField.cell setPlaceholderString:repeatPlaceHolder]; } #pragma mark Actions - (IBAction)save:(id)sender { - const BOOL hasPassword = ([self.hasPasswordSwitchButton state] == NSOnState); - NSString *password = hasPassword ? [self.passwordTextField stringValue] : nil; + const BOOL hasPassword = HNHUIBoolForState(self.hasPasswordSwitchButton.state); + NSString *password = hasPassword ? self.passwordTextField.stringValue : nil; MPDocument *document = self.document; - [document changePassword:password keyFileURL:[self.keyfilePathControl URL]]; - [self dismissSheet:NSRunStoppedResponse]; - if(self.delegate && [self.delegate respondsToSelector:@selector(didFinishPasswordEditing:)]) { - [self.delegate didFinishPasswordEditing:YES]; - } + [document changePassword:password keyFileURL:self.keyfilePathControl.URL]; + [self dismissSheet:NSModalResponseOK]; } - (IBAction)cancel:(id)sender { - [self dismissSheet:NSRunAbortedResponse]; - if(self.delegate && [self.delegate respondsToSelector:@selector(didFinishPasswordEditing:)]) { - [self.delegate didFinishPasswordEditing:NO]; - } + [self dismissSheet:NSModalResponseCancel]; } - (IBAction)clearKey:(id)sender { @@ -126,9 +120,9 @@ NSData *data = [NSData generateKeyfiledataForVersion:document.tree.minimumVersion]; if(data) { NSSavePanel *savePanel = [NSSavePanel savePanel]; - [savePanel setAllowedFileTypes:@[@"key", @"xml"]]; - [savePanel setCanCreateDirectories:YES]; - [savePanel setTitle:NSLocalizedString(@"SAVE_KEYFILE", "")]; + savePanel.allowedFileTypes = @[@"key", @"xml"]; + savePanel.canCreateDirectories = YES; + savePanel.title = NSLocalizedString(@"SAVE_KEYFILE", ""); [savePanel beginWithCompletionHandler:^(NSInteger result) { if(result == NSFileHandlingPanelOKButton) { NSURL *keyURL = [savePanel URL]; diff --git a/MacPass/MacPass-Prefix.pch b/MacPass/MacPass-Prefix.pch index 6795a931..b6f3d873 100644 --- a/MacPass/MacPass-Prefix.pch +++ b/MacPass/MacPass-Prefix.pch @@ -3,7 +3,7 @@ // #ifdef __OBJC__ - #define __MAC_OS_X_VERSION_SOFT_MAX_REQUIRED __MAC_10_8 + #define __MAC_OS_X_VERSION_SOFT_MAX_REQUIRED __MAC_10_9 #import "MJGAvailability.h" #import #endif diff --git a/MacPass/NSError+Messages.h b/MacPass/NSError+Messages.h index 21ed9743..cb8c3172 100644 --- a/MacPass/NSError+Messages.h +++ b/MacPass/NSError+Messages.h @@ -10,6 +10,10 @@ FOUNDATION_EXPORT NSString *const MPErrorDomain; +typedef NS_ENUM(NSInteger, MPErrorCodes) { + MPErrorNoPasswordOrKeyFile = 10000, +}; + @interface NSError (Messages) + (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description; diff --git a/MacPass/en.lproj/Localizable.strings b/MacPass/en.lproj/Localizable.strings index e6ef3e53..fc0bdada 100644 Binary files a/MacPass/en.lproj/Localizable.strings and b/MacPass/en.lproj/Localizable.strings differ