diff --git a/MacPass/Base.lproj/GeneralSettings.xib b/MacPass/Base.lproj/GeneralSettings.xib
index 2ffb09c5..d72408e5 100644
--- a/MacPass/Base.lproj/GeneralSettings.xib
+++ b/MacPass/Base.lproj/GeneralSettings.xib
@@ -74,7 +74,7 @@
-
+
diff --git a/MacPass/Base.lproj/PasswordInputView.xib b/MacPass/Base.lproj/PasswordInputView.xib
index 5af982a3..60439661 100644
--- a/MacPass/Base.lproj/PasswordInputView.xib
+++ b/MacPass/Base.lproj/PasswordInputView.xib
@@ -23,7 +23,7 @@
-
diff --git a/MacPass/MPDocument.h b/MacPass/MPDocument.h
index eb4fffb7..0690cc3d 100644
--- a/MacPass/MPDocument.h
+++ b/MacPass/MPDocument.h
@@ -9,6 +9,8 @@
#import
#import "KPKVersion.h"
+APPKIT_EXTERN NSString *const MPDocumentDidChangeStoredKeyFilesSettings;
+
APPKIT_EXTERN NSString *const MPDocumentDidAddGroupNotification;
APPKIT_EXTERN NSString *const MPDocumentDidRevertNotifiation;
@@ -55,6 +57,14 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
#pragma mark Lock/Decrypt
- (void)lockDatabase:(id)sender;
- (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL error:(NSError *__autoreleasing*)error;
+/**
+ * Returns the suggest key URL for this document. This might be nil.
+ * If the user did disable remeberKeyFiles in the settings, this always returns nil
+ * Otherwise the preferences are searched to locate the last know key url for this document
+ *
+ * @return The suggested key URL if one was found and the settings are allowing suggesting key locations
+ */
+- (NSURL *)suggestedKeyURL;
#pragma mark Data Lookup
/**
diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m
index fb328adf..c1d7d70a 100644
--- a/MacPass/MPDocument.m
+++ b/MacPass/MPDocument.m
@@ -26,6 +26,8 @@
#import "KPKMetaData.h"
#import "KPKAttribute.h"
+NSString *const MPDocumentDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDocumentDidChangeStoredKeyFilesSettings";
+
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
@@ -52,8 +54,8 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
@property (weak, nonatomic) KPKGroup *root;
@property (assign) BOOL readOnly;
-
@property (strong) NSURL *lockFileURL;
+@property (nonatomic, assign) BOOL isAllowedToStoreKeyFile;
@property (readonly) BOOL useTrash;
@property (strong) IBOutlet NSView *warningView;
@@ -97,12 +99,18 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
_encryptedData = nil;
_didLockFile = NO;
_readOnly = NO;
+ _isAllowedToStoreKeyFile = NO;
self.tree = [KPKTree templateTree];
+ [self bind:@"isAllowedToStoreKeyFile"
+ toObject:[NSUserDefaultsController sharedUserDefaultsController]
+ withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyRememberKeyFilesForDatabases]
+ options:nil];
}
return self;
}
- (void)dealloc {
+ [self unbind:@"isAllowedToStoreKeyFile"];
[self _cleanupLock];
}
@@ -212,6 +220,13 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
#pragma mark Lock/Unlock/Decrypt
+- (void)lockDatabase:(id)sender {
+ NSError *error;
+ /* Locking needs to be lossless hence just use the XML format */
+ _encryptedData = [self.tree encryptWithPassword:self.compositeKey forVersion:KPKXmlVersion error:&error];
+ self.tree = nil;
+}
+
- (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL error:(NSError *__autoreleasing*)error{
self.compositeKey = [[KPKCompositeKey alloc] initWithPassword:password key:keyFileURL];
self.tree = [[KPKTree alloc] initWithData:_encryptedData password:self.compositeKey error:error];
@@ -219,6 +234,9 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
BOOL isUnlocked = (nil != self.tree);
if(isUnlocked) {
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidUnlockDatabaseNotification object:self];
+ if([password length] > 0 && self.isAllowedToStoreKeyFile) {
+ [self _storeKeyURL:keyFileURL];
+ }
}
else {
self.compositeKey = nil; // clear the key?
@@ -226,11 +244,16 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
return isUnlocked;
}
-- (void)lockDatabase:(id)sender {
- NSError *error;
- /* Locking needs to be lossless hence just use the XML format */
- _encryptedData = [self.tree encryptWithPassword:self.compositeKey forVersion:KPKXmlVersion error:&error];
- self.tree = nil;
+- (NSURL *)suggestedKeyURL {
+ if(!self.isAllowedToStoreKeyFile) {
+ return nil;
+ }
+ NSDictionary *keysForFiles = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases];
+ NSString *keyPath = keysForFiles[[[self fileURL] path]];
+ if(!keyPath) {
+ return nil;
+ }
+ return [NSURL fileURLWithPath:keyPath];
}
#pragma mark Properties
@@ -273,6 +296,17 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
}
+- (void)setIsAllowedToStoreKeyFile:(BOOL)isAllowedToStoreKeyFile {
+ if(_isAllowedToStoreKeyFile != isAllowedToStoreKeyFile) {
+ _isAllowedToStoreKeyFile = isAllowedToStoreKeyFile;
+ if(!self.isAllowedToStoreKeyFile) {
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:kMPSettingsKeyRememeberdKeysForDatabases];
+ }
+ /* Inform anyone that might be interested that we can now no longer/ or can use keyfiles */
+ [[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeStoredKeyFilesSettings object:self];
+ }
+}
+
#pragma mark Data Accesors
- (KPKEntry *)findEntry:(NSUUID *)uuid {
@@ -474,6 +508,16 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
return [super validateUserInterfaceItem:anItem];
}
+- (void)_storeKeyURL:(NSURL *)keyURL {
+ NSAssert(self.isAllowedToStoreKeyFile, @"We can only store if we are allowed to do so!");
+ NSMutableDictionary *keysForFiles = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases] mutableCopy];
+ if(nil == keysForFiles) {
+ keysForFiles = [[NSMutableDictionary alloc] initWithCapacity:1];
+ }
+ keysForFiles[[[self fileURL] path]] = [keyURL path];
+ [[NSUserDefaults standardUserDefaults] setObject:keysForFiles forKey:kMPSettingsKeyRememeberdKeysForDatabases];
+}
+
- (void)_cleanupLock {
if(_didLockFile) {
[[NSFileManager defaultManager] removeItemAtURL:_lockFileURL error:nil];
diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m
index 5d48a19b..e8c277e5 100644
--- a/MacPass/MPDocumentWindowController.m
+++ b/MacPass/MPDocumentWindowController.m
@@ -283,10 +283,6 @@ typedef NS_ENUM(NSUInteger, MPAlertContext) {
- (void)showPasswordInput {
if(!self.passwordInputController) {
self.passwordInputController = [[MPPasswordInputController alloc] init];
- self.passwordInputController.showLastUsedKeyFile = YES;
- }
- else {
- self.passwordInputController.showLastUsedKeyFile = NO;
}
[self _setContentViewController:self.passwordInputController];
[self.passwordInputController requestPassword];
diff --git a/MacPass/MPPasswordInputController.h b/MacPass/MPPasswordInputController.h
index d78531d1..732fff81 100644
--- a/MacPass/MPPasswordInputController.h
+++ b/MacPass/MPPasswordInputController.h
@@ -10,8 +10,6 @@
@interface MPPasswordInputController : MPViewController
-@property (nonatomic, assign) BOOL showLastUsedKeyFile;
-
- (void)requestPassword;
@end
diff --git a/MacPass/MPPasswordInputController.m b/MacPass/MPPasswordInputController.m
index bc7c91c0..0c7144e9 100644
--- a/MacPass/MPPasswordInputController.m
+++ b/MacPass/MPPasswordInputController.m
@@ -24,12 +24,8 @@
@property (weak) IBOutlet NSTextField *errorInfoTextField;
@property (weak) IBOutlet NSButton *togglePasswordButton;
-@property (nonatomic, assign) BOOL shouldRememberKeyURL;
@property (assign) BOOL showPassword;
-- (IBAction)_decrypt:(id)sender;
-- (IBAction)_clearKey:(id)sender;
-
@end
@implementation MPPasswordInputController
@@ -42,21 +38,20 @@
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
- _showLastUsedKeyFile = NO;
- _shouldRememberKeyURL = NO;
- NSUserDefaultsController *defaultsController = [NSUserDefaultsController sharedUserDefaultsController];
- [self bind:@"shouldRememberKeyURL" toObject:defaultsController withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyRememberKeyFilesForDatabases ] options:nil];
-
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_selectKeyURL) name:MPDocumentDidChangeStoredKeyFilesSettings object:nil];
}
return self;
}
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
- (void)didLoadView {
[self.keyPathControl setDelegate:self.pathControlDelegate];
[self.errorImageView setImage:[NSImage imageNamed:NSImageNameCaution]];
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
-
[self _reset];
}
@@ -67,20 +62,6 @@
- (void)requestPassword {
// show Warnign if read-only mode!
[self _reset];
- if(self.showLastUsedKeyFile) {
- [self _selectRecentKeyFile];
- }
-}
-
-#pragma mark Properties
-- (void)setShouldRememberKeyURL:(BOOL)shouldSelectKeyFile {
- if(_shouldRememberKeyURL != shouldSelectKeyFile) {
- _shouldRememberKeyURL = shouldSelectKeyFile;
- if(!self.shouldRememberKeyURL) {
- /* Remove any old settings to clean them up */
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:kMPSettingsKeyRememeberdKeysForDatabases];
- }
- }
}
#pragma mark -
@@ -89,53 +70,29 @@
MPDocument *document = [[self windowController] document];
if(document) {
NSError *error = nil;
- NSURL *keyURL = [self.keyPathControl URL];
- if([document unlockWithPassword:[self.passwordTextField stringValue] keyFileURL:keyURL error:&error]) {
- [self _setUsedKeyURL:keyURL forDocument:document];
- }
- else {
+ if(![document unlockWithPassword:[self.passwordTextField stringValue]
+ keyFileURL:[self.keyPathControl URL]
+ error:&error]) {
[self _showError:error];
}
}
}
-- (IBAction)_clearKey:(id)sender {
- [self.keyPathControl setURL:nil];
+- (IBAction)resetKeyFile:(id)sender {
+ [self _selectKeyURL];
}
- (void)_reset {
self.showPassword = NO;
[self.passwordTextField setStringValue:@""];
- [self.keyPathControl setURL:nil];
[self.errorInfoTextField setHidden:YES];
[self.errorImageView setHidden:YES];
+ [self resetKeyFile:nil];
}
-- (void)_selectRecentKeyFile {
- if(!self.shouldRememberKeyURL) {
- [self.keyPathControl setURL:nil];
- return; // If we aren't supposed to preselect paths, clear them!
- }
- NSDictionary *keysForFiles = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases];
+- (void)_selectKeyURL {
MPDocument *document = [[self windowController] document];
- if(document) {
- NSString *keyPath = keysForFiles[[[document fileURL] path]];
- NSURL *keyURL = keyPath != nil ? [NSURL fileURLWithPath:keyPath] : nil;
- [self.keyPathControl setURL:keyURL];
- }
-}
-
-- (void)_setUsedKeyURL:(NSURL *)keyURL forDocument:(NSDocument *)document {
- if(!self.shouldRememberKeyURL) {
- return;
- }
- NSMutableDictionary *keysForFiles = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases] mutableCopy];
- if(nil == keysForFiles) {
- keysForFiles = [[NSMutableDictionary alloc] initWithCapacity:1];
- }
- //NSLog(@"remembering keyfile %@ for document %@ at URL %@", keyURL, [document displayName], [document fileURL]);
- keysForFiles[[[document fileURL] path]] = [keyURL path];
- [[NSUserDefaults standardUserDefaults] setObject:keysForFiles forKey:kMPSettingsKeyRememeberdKeysForDatabases];
+ [self.keyPathControl setURL:document.suggestedKeyURL];
}
- (void)_showError:(NSError *)error {
diff --git a/MacPass/MPPasteBoardController.h b/MacPass/MPPasteBoardController.h
index 9f9cddd6..806bd90c 100644
--- a/MacPass/MPPasteBoardController.h
+++ b/MacPass/MPPasteBoardController.h
@@ -10,6 +10,17 @@
@interface MPPasteBoardController : NSObject
+/**
+ * The PasteBoardController did copy new items to the pasteboard
+ * The userInfo dictionary is empty. You can optain the timeout via the clearTimeout property
+ */
+FOUNDATION_EXPORT NSString *const MPPasteBoardControllerDidCopyObjects;
+/**
+ * The PasteBoardController did clear the clipboard.
+ * The userInfo dictionary is empty
+ */
+FOUNDATION_EXPORT NSString *const MPPasteBoardControllerDidClearClipboard;
+
/*
This time sets the time interval after which a copied entry shoudl be purged from the pasteboard
*/
diff --git a/MacPass/MPPasteBoardController.m b/MacPass/MPPasteBoardController.m
index bbdb4bbd..3b7aada6 100644
--- a/MacPass/MPPasteBoardController.m
+++ b/MacPass/MPPasteBoardController.m
@@ -9,6 +9,10 @@
#import "MPPasteBoardController.h"
#import "MPSettingsHelper.h"
+/* Notifications */
+NSString *const MPPasteBoardControllerDidCopyObjects = @"com.hicknhack.macpass.MPPasteBoardControllerDidCopyObjects";
+NSString *const MPPasteBoardControllerDidClearClipboard = @"com.hicknhack.macpass.MPPasteBoardControllerDidCopyObjects";
+
@interface MPPasteBoardController ()
@property (assign) BOOL isEmpty;
@@ -69,16 +73,21 @@
}
- (void)copyObjects:(NSArray *)objects {
+ /* Should we save the old content ?*/
[[NSPasteboard generalPasteboard] clearContents];
[[NSPasteboard generalPasteboard] writeObjects:objects];
self.isEmpty = NO;
- [self performSelector:@selector(_clearPasteboardContents) withObject:nil afterDelay:self.clearTimeout];
+ if(self.clearTimeout != 0) {
+ [[NSNotificationCenter defaultCenter] postNotificationName:MPPasteBoardControllerDidCopyObjects object:self];
+ [self performSelector:@selector(_clearPasteboardContents) withObject:nil afterDelay:self.clearTimeout];
+ }
}
- (void)_clearPasteboardContents {
/* Only clear stuff we might have put there */
if(!self.isEmpty) {
[[NSPasteboard generalPasteboard] clearContents];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MPPasteBoardControllerDidClearClipboard object:self];
}
self.isEmpty = YES;
}