diff --git a/HNHUi b/HNHUi
index f12405e3..c32f87da 160000
--- a/HNHUi
+++ b/HNHUi
@@ -1 +1 @@
-Subproject commit f12405e384eebdfb692e5750b4ff77b9be183bfb
+Subproject commit c32f87da30386cb9b74c8a43cc173ad4584f329d
diff --git a/MacPass/DatabaseSettingsWindow.xib b/MacPass/DatabaseSettingsWindow.xib
index 44c7a059..fd571e73 100644
--- a/MacPass/DatabaseSettingsWindow.xib
+++ b/MacPass/DatabaseSettingsWindow.xib
@@ -68,7 +68,7 @@
@@ -1177,6 +1249,38 @@
1050
+
+
+ passwordRepeatTextField
+
+
+
+ 1152
+
+
+
+ saveButton
+
+
+
+ 1183
+
+
+
+ cancelButton
+
+
+
+ 1201
+
+
+
+ errorTextField
+
+
+
+ 1202
+
@@ -2458,12 +2562,12 @@
620
-
+
- 11
+ 10
0
-
- 11
+
+ 10
1
0.0
@@ -2474,12 +2578,12 @@
24
2
-
+
- 5
+ 6
0
- 5
+ 6
1
0.0
@@ -2506,6 +2610,22 @@
24
3
+
+
+ 5
+ 0
+
+ 5
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
5
@@ -2522,38 +2642,6 @@
24
3
-
-
- 6
- 0
-
- 6
- 1
-
- 0.0
-
- 1000
-
- 6
- 24
- 2
-
-
-
- 6
- 0
-
- 6
- 1
-
- 0.0
-
- 1000
-
- 6
- 24
- 2
-
3
@@ -2570,6 +2658,22 @@
24
3
+
+
+ 6
+ 0
+
+ 6
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
5
@@ -2586,11 +2690,27 @@
24
2
-
+
+
+ 6
+ 0
+
+ 6
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
+
3
0
-
+
4
1
@@ -2618,15 +2738,31 @@
24
3
-
-
+
+
+ 9
+ 0
+
+ 9
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
+
+
3
0
3
1
- 55
+ 15
1000
@@ -2634,6 +2770,86 @@
9
3
+
+
+ 5
+ 0
+
+ 6
+ 1
+
+ 8
+
+ 1000
+
+ 6
+ 24
+ 3
+
+
+
+ 3
+ 0
+
+ 4
+ 1
+
+ 10
+
+ 1000
+
+ 6
+ 24
+ 3
+
+
+
+ 5
+ 0
+
+ 5
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
+
+
+ 5
+ 0
+
+ 5
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
+
+
+ 3
+ 0
+
+ 4
+ 1
+
+ 8
+
+ 1000
+
+ 6
+ 24
+ 3
+
5
@@ -2650,22 +2866,6 @@
24
3
-
-
- 5
- 0
-
- 5
- 1
-
- 0.0
-
- 1000
-
- 6
- 24
- 2
-
3
@@ -2714,6 +2914,22 @@
24
2
+
+
+ 11
+ 0
+
+ 11
+ 1
+
+ 0.0
+
+ 1000
+
+ 6
+ 24
+ 2
+
5
@@ -2731,12 +2947,15 @@
3
+
+
+
+
-
-
-
+
+
@@ -2964,46 +3183,21 @@
-
- 1016
-
-
-
1023
-
- 1024
-
-
-
-
- 1026
-
-
-
1027
-
- 1028
-
-
-
1029
-
- 1031
-
-
-
1037
@@ -3043,16 +3237,6 @@
-
- 1042
-
-
-
-
- 1043
-
-
-
1044
@@ -3098,11 +3282,6 @@
-
- 1079
-
-
-
1080
@@ -3188,6 +3367,141 @@
+
+ 1120
+
+
+
+
+
+
+
+ 1121
+
+
+
+
+ 1124
+
+
+
+
+
+
+
+ 1126
+
+
+
+
+ 1128
+
+
+
+
+ 1129
+
+
+
+
+ 1130
+
+
+
+
+ 1133
+
+
+
+
+ 1134
+
+
+
+
+ 1135
+
+
+
+
+ 1146
+
+
+
+
+ 1149
+
+
+
+
+ 1150
+
+
+
+
+ 1151
+
+
+
+
+ 1177
+
+
+
+
+ 1179
+
+
+
+
+ 1187
+
+
+
+
+
+ 8
+ 0
+
+ 0
+ 1
+
+ 17
+
+ 1000
+
+ 3
+ 9
+ 1
+
+
+
+
+
+ 1188
+
+
+
+
+ 1194
+
+
+
+
+ 1195
+
+
+
+
+ 1197
+
+
+
+
+ 1199
+
+
+
@@ -3201,14 +3515,9 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
HNHRoundedSecureTextField
@@ -3218,8 +3527,6 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -3235,7 +3542,6 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -3243,6 +3549,35 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ HNHRoundedSecureTextField
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+
+
+
+
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -3400,22 +3735,29 @@
com.apple.InterfaceBuilder.CocoaPlugin
+
-
-
+
+
+
+
+
+
+
-
+
+
-
-
+
-
-
+
+
+
com.apple.InterfaceBuilder.CocoaPlugin
@@ -3465,7 +3807,7 @@
- 1117
+ 1202
@@ -3506,22 +3848,30 @@
+ NSButton
NSTextView
NSTextField
NSButton
NSButton
+ NSTextField
NSPathControl
+ HNHRoundedSecureTextField
HNHRoundedSecureTextField
NSButton
NSButton
NSButton
NSButton
NSButton
+ NSButton
NSTabView
NSPopUpButton
NSButton
+
+ cancelButton
+ NSButton
+
databaseDescriptionTextView
NSTextView
@@ -3538,10 +3888,18 @@
enableRecycleBinCheckButton
NSButton
+
+ errorTextField
+ NSTextField
+
keyfilePathControl
NSPathControl
+
+ passwordRepeatTextField
+ HNHRoundedSecureTextField
+
passwordTextField
HNHRoundedSecureTextField
@@ -3566,6 +3924,10 @@
protectUserNameCheckButton
NSButton
+
+ saveButton
+ NSButton
+
sectionTabView
NSTabView
diff --git a/MacPass/MPDatabaseSettingsWindowController.h b/MacPass/MPDatabaseSettingsWindowController.h
index dc5593f8..72100b96 100644
--- a/MacPass/MPDatabaseSettingsWindowController.h
+++ b/MacPass/MPDatabaseSettingsWindowController.h
@@ -18,9 +18,11 @@ typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
@class MPDocument;
@class HNHRoundedSecureTextField;
-@interface MPDatabaseSettingsWindowController : NSWindowController
+@interface MPDatabaseSettingsWindowController : NSWindowController
@property (weak) IBOutlet NSTabView *sectionTabView;
+@property (weak) IBOutlet NSButton *saveButton;
+@property (weak) IBOutlet NSButton *cancelButton;
/* General Tab */
@property (weak) IBOutlet NSTextField *databaseNameTextField;
@@ -28,8 +30,11 @@ typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
/* Protection */
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
+@property (weak) IBOutlet HNHRoundedSecureTextField *passwordRepeatTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
@property (weak) IBOutlet NSButton *togglePasswordButton;
+@property (weak) IBOutlet NSTextField *errorTextField;
+
- (IBAction)clearKey:(id)sender;
- (IBAction)generateKey:(id)sender;
diff --git a/MacPass/MPDatabaseSettingsWindowController.m b/MacPass/MPDatabaseSettingsWindowController.m
index 917c912e..431154f3 100644
--- a/MacPass/MPDatabaseSettingsWindowController.m
+++ b/MacPass/MPDatabaseSettingsWindowController.m
@@ -14,6 +14,8 @@
#import "HNHRoundedSecureTextField.h"
+#import "NSString+Empty.h"
+
#import "Kdb.h"
#import "Kdb4Node.h"
#import "KdbGroup+MPAdditions.h"
@@ -24,6 +26,8 @@
@property (nonatomic,assign) BOOL trashEnabled;
@property (nonatomic,assign) BOOL showPassword;
+@property (nonatomic,assign) BOOL hasValidPasswordOrKey;
+@property (nonatomic,weak) NSURL *keyURL;
@end
@@ -38,6 +42,7 @@
if(self) {
_document = document;
_showPassword = NO;
+ _hasValidPasswordOrKey = NO;
}
return self;
}
@@ -47,6 +52,9 @@
NSAssert(_document != nil, @"Document needs to be present");
+ [self.saveButton bind:NSEnabledBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
+ [self.cancelButton bind:NSEnabledBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
+
Kdb4Tree *tree = _document.treeV4;
if( tree ) {
[self _setupDatabase:tree];
@@ -64,7 +72,7 @@
/* Protection */
_document.password = [self.passwordTextField stringValue];
_document.key = [self.keyfilePathControl URL];
-
+
/* General */
_document.treeV4.databaseDescription = [self.databaseDescriptionTextView string];
_document.treeV4.databaseName = [self.databaseNameTextField stringValue];
@@ -72,7 +80,7 @@
/* Display */
/* Advanced */
- _document.treeV4.recycleBinEnabled = self.trashEnabled;
+ _document.treeV4.recycleBinEnabled = self.trashEnabled;
NSMenuItem *menuItem = [self.selectRecycleBinGroupPopUpButton selectedItem];
KdbGroup *group = [menuItem representedObject];
[_document useGroupAsTrash:group];
@@ -109,15 +117,68 @@
[self.sectionTabView selectTabViewItemAtIndex:tab];
}
+- (void)setShowPassword:(BOOL)showPassword {
+ if(_showPassword != showPassword) {
+ _showPassword = showPassword;
+
+ [self.passwordRepeatTextField setStringValue:@""];
+ [self _verifyPasswordAndKey];
+ }
+}
+
+- (void)setKeyURL:(NSURL *)keyURL {
+ _keyURL = keyURL;
+ [self _verifyPasswordAndKey];
+}
+
#pragma mark Actions
- (IBAction)clearKey:(id)sender {
- [self.keyfilePathControl setURL:nil];
+ self.keyURL = nil;
}
- (IBAction)generateKey:(id)sender {
}
+#pragma makr NSTextFieldDelegate
+- (void)controlTextDidChange:(NSNotification *)obj {
+ [self _verifyPasswordAndKey];
+}
+
#pragma mark Private Helper
+- (void)_verifyPasswordAndKey {
+ NSString *password = [self.passwordTextField stringValue];
+ NSString *repeat = [self.passwordRepeatTextField stringValue];
+ BOOL hasKey = (self.keyURL != nil);
+ BOOL keyOk = YES;
+ if(hasKey) {
+ keyOk = [self.keyURL checkResourceIsReachableAndReturnError:nil];
+ }
+ BOOL hasPassword = ![password isEmpty];
+ BOOL passwordOk = YES;
+ if(hasPassword ) {
+ passwordOk = [password isEqualToString:repeat] || self.showPassword;
+ }
+ BOOL hasPasswordOrKey = (hasKey || hasPassword);
+ keyOk = hasKey ? keyOk : YES;
+ passwordOk = hasPassword ? passwordOk : YES;
+ self.hasValidPasswordOrKey = hasPasswordOrKey && passwordOk && keyOk;
+
+ if(!hasPasswordOrKey) {
+ [self.errorTextField setStringValue:NSLocalizedString(@"ERROR_NO_PASSWORD_OR_KEYFILE", "Missing Key or Password")];
+ return; // alldone
+ }
+ if(!passwordOk && !keyOk ) {
+ [self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH_INVALID_KEYFILE", "Passwords do not match, keyfile is invalid")];
+ }
+ else if(!passwordOk) {
+ [self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match")];
+ }
+ else {
+ [self.errorTextField setStringValue:NSLocalizedString(@"ERROR_INVALID_KEYFILE", "Keyfile not valid")];
+ }
+
+}
+
- (void)_setupDatabase:(Kdb4Tree *)tree {
[self.databaseNameTextField setStringValue:tree.databaseName];
[self.databaseDescriptionTextView setString:tree.databaseDescription];
@@ -140,10 +201,21 @@
- (void)_setupPasswordTab:(Kdb4Tree *)tree {
[self.passwordTextField setStringValue:_document.password ? _document.password : @""];
- [self.keyfilePathControl setURL:_document.key];
+ [self.passwordRepeatTextField setStringValue:[self.passwordRepeatTextField stringValue]];
+ self.keyURL = _document.key;
+ NSDictionary *negateOption = @{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName };
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
+ [self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:@"showPassword" options:negateOption];
+ [self.errorTextField bind:NSHiddenBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
+ [self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:@"keyURL" options:nil];
+
+ [self.passwordRepeatTextField setDelegate:self];
+ [self.passwordTextField setDelegate:self];
+
+ /* Manually initate the first check */
+ [self _verifyPasswordAndKey];
}
- (void)_updateTrashFolders:(Kdb4Tree *)tree {
@@ -154,7 +226,7 @@
- (NSMenu *)_buildTreeMenu:(Kdb4Tree *)tree {
NSMenu *menu = [[NSMenu alloc] init];
[menu setAutoenablesItems:NO];
-
+
for(Kdb4Group *group in tree.root.groups) {
NSMenuItem *groupItem = [[NSMenuItem alloc] init];
[groupItem setImage:group.icon];
diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m
index df213f3d..6c8b34a6 100644
--- a/MacPass/MPDocumentWindowController.m
+++ b/MacPass/MPDocumentWindowController.m
@@ -63,9 +63,6 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
-
-
-
}
#pragma mark View Handling
@@ -343,6 +340,7 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
[_outlineViewController showOutline];
}
+
#pragma mark NSWindowDelegate
- (void)windowDidUpdate:(NSNotification *)notification {
id firstResonder = [[self window] firstResponder];
@@ -351,10 +349,16 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
}
_firstResponder = firstResonder;
if([_firstResponder isKindOfClass:[NSView class]]) {
- [self _updateCurrentItem:[NSNotification notificationWithName:@"dummy" object:_firstResponder ]];
+ //self _updateCurrentItem:[NSNotification notificationWithName:@"dummy" object:_firstResponder ]];
}
}
+- (void)windowDidBecomeKey:(NSNotification *)notification {
+ MPDocument *document = [self document];
+ if(!document.hasPasswordOrKey && document.decrypted) {
+ [self performSelector:@selector(editPassword:) withObject:nil afterDelay:0.5];
+ }
+}
#pragma mark Helper
diff --git a/MacPass/MacPass-Info.plist b/MacPass/MacPass-Info.plist
index 8de34d18..dfb4ab2b 100644
--- a/MacPass/MacPass-Info.plist
+++ b/MacPass/MacPass-Info.plist
@@ -44,11 +44,11 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.3.3
+ 0.3.4
CFBundleSignature
????
CFBundleVersion
- 2511
+ 2514
LSMinimumSystemVersion
${MACOSX_DEPLOYMENT_TARGET}
NSHumanReadableCopyright
diff --git a/MacPass/de.lproj/Localizable.strings b/MacPass/de.lproj/Localizable.strings
index 9f0c6e57..7b575736 100644
Binary files a/MacPass/de.lproj/Localizable.strings and b/MacPass/de.lproj/Localizable.strings differ
diff --git a/MacPass/en.lproj/Localizable.strings b/MacPass/en.lproj/Localizable.strings
index e1987841..6b350ee4 100644
Binary files a/MacPass/en.lproj/Localizable.strings and b/MacPass/en.lproj/Localizable.strings differ