diff --git a/MacPass/MPDocument.h b/MacPass/MPDocument.h index 9d240cc0..4ad43268 100644 --- a/MacPass/MPDocument.h +++ b/MacPass/MPDocument.h @@ -53,6 +53,7 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification; + (KPKVersion)versionForFileType:(NSString *)fileType; ++ (NSString *)fileTypeForVersion:(KPKVersion)version; #pragma mark Lock/Decrypt - (void)lockDatabase:(id)sender; diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index ebc3679a..3401d42b 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -72,6 +72,19 @@ typedef NS_ENUM(NSUInteger, MPAlertType) { return KPKUnknownVersion; } ++ (NSString *)fileTypeForVersion:(KPKVersion)version { + switch(version) { + case KPKLegacyVersion: + return MPLegacyDocumentUTI; + + case KPKXmlVersion: + return MPXMLDocumentUTI; + + default: + return @"Unknown"; + } +} + + (BOOL)autosavesInPlace { return NO; } @@ -103,8 +116,12 @@ typedef NS_ENUM(NSUInteger, MPAlertType) { } - (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError { + if(!self.hasPasswordOrKey) { + return NO; // No password or key. No save possible + } KPKPassword *password = [[KPKPassword alloc] initWithPassword:self.password key:self.key]; - KPKVersion version = [[self class] versionForFileType:(NSString *)typeName]; + NSString *fileType = [self fileTypeFromLastRunSavePanel]; + KPKVersion version = [[self class] versionForFileType:fileType]; if(version == KPKUnknownVersion) { if(outError != NULL) { *outError = [NSError errorWithDomain:MPErrorDomain code:0 userInfo:nil]; @@ -174,10 +191,20 @@ typedef NS_ENUM(NSUInteger, MPAlertType) { } self.savePanelViewController.savePanel = savePanel; self.savePanelViewController.document = self; + [savePanel setAccessoryView:[self.savePanelViewController view]]; + [self.savePanelViewController updateView]; + return YES; } +- (NSString *)fileTypeFromLastRunSavePanel { + if(self.savePanelViewController) { + return [[self class] fileTypeForVersion:self.savePanelViewController.selectedVersion]; + } + return [self fileType]; +} + - (void)writeXMLToURL:(NSURL *)url { NSData *xmlData = [self.tree xmlData]; [xmlData writeToURL:url atomically:YES]; diff --git a/MacPass/MPDocumentWindowController.h b/MacPass/MPDocumentWindowController.h index d53c9c68..78a0501a 100644 --- a/MacPass/MPDocumentWindowController.h +++ b/MacPass/MPDocumentWindowController.h @@ -7,6 +7,7 @@ // #import +#import "MPPasswordEditWindowController.h" @class MPViewController; @class MPEntryViewController; @@ -14,7 +15,7 @@ @class MPPasswordInputController; @class MPOutlineViewController; -@interface MPDocumentWindowController : NSWindowController +@interface MPDocumentWindowController : NSWindowController @property (readonly, strong) MPPasswordInputController *passwordInputController; @property (readonly, strong) MPEntryViewController *entryViewController; @@ -46,4 +47,7 @@ - (void)createGroup:(id)sender; - (void)toggleInspector:(id)sender; +#pragma mark MPPasswordEditWindowDelegater +- (void)didFinishPasswordEditing:(BOOL)changedPasswordOrKey; + @end diff --git a/MacPass/MPDocumentWindowController.m b/MacPass/MPDocumentWindowController.m index 78f69c28..6ff310ac 100644 --- a/MacPass/MPDocumentWindowController.m +++ b/MacPass/MPDocumentWindowController.m @@ -27,6 +27,7 @@ @interface MPDocumentWindowController () { @private id _firstResponder; + BOOL _saveAfterPasswordChange; } @property (strong) IBOutlet NSSplitView *splitView; @@ -51,6 +52,7 @@ self = [super initWithWindowNibName:@"DocumentWindow" owner:self]; if( self ) { _firstResponder = nil; + _saveAfterPasswordChange = NO; _toolbarDelegate = [[MPToolbarDelegate alloc] init]; _outlineViewController = [[MPOutlineViewController alloc] init]; _entryViewController = [[MPEntryViewController alloc] init]; @@ -153,6 +155,7 @@ #pragma mark Actions - (void)saveDocument:(id)sender { + _saveAfterPasswordChange = NO; MPDocument *document = [self document]; NSString *fileType = [document fileType]; /* we did open as legacy */ @@ -166,15 +169,20 @@ [alert addButtonWithTitle:NSLocalizedString(@"CANCEL", "Cancel")]; [[alert buttons][1] setKeyEquivalent:[NSString stringWithFormat:@"%c", 0x1b]]; - [alert beginSheetModalForWindow:[self window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL]; return; } } - if(!document.hasPasswordOrKey) { - NSLog(@"No Password and/or kefile set");// warning if no password ist set! + else if(!document.hasPasswordOrKey) { + _saveAfterPasswordChange = YES; + [self editPassword:sender]; + return; } - [[self document] saveDocument:sender]; + else { + /* All set and good ready to save */ + [[self document] saveDocument:sender]; + } + } - (void)exportDatabase:(id)sender { NSSavePanel *savePanel = [NSSavePanel savePanel]; @@ -274,7 +282,10 @@ - (void)editPassword:(id)sender { if(!self.passwordEditWindowController) { self.passwordEditWindowController = [[MPPasswordEditWindowController alloc] initWithDocument:[self document]]; + self.passwordEditWindowController.delegate = self; } + /* Disallow empty password if we want to save afterwards, otherwise the dialog keeps poping up */ + self.passwordEditWindowController.allowsEmptyPasswordOrKey = !_saveAfterPasswordChange; [NSApp beginSheet:[self.passwordEditWindowController window] modalForWindow:[self window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL]; } @@ -392,6 +403,14 @@ [_outlineViewController showOutline]; } +#pragma mark MPPasswordEditWindowDelegate +- (void)didFinishPasswordEditing:(BOOL)changedPasswordOrKey { + if(changedPasswordOrKey && _saveAfterPasswordChange) { + [self saveDocument:nil]; + } +} + + #pragma mark Helper - (void)_showDatabaseSetting:(MPDatabaseSettingsTab)tab { if(!self.documentSettingsWindowController) { diff --git a/MacPass/MPOutlineViewController.m b/MacPass/MPOutlineViewController.m index 6ae9fc54..0dbb0272 100644 --- a/MacPass/MPOutlineViewController.m +++ b/MacPass/MPOutlineViewController.m @@ -260,7 +260,6 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell"; id item = userInfo[@"NSObject"]; id representedObject = [item representedObject]; if([representedObject isKindOfClass:[KPKGroup class]]) { - NSLog(@"expanded:%@",representedObject); KPKGroup *group = (KPKGroup *)representedObject; group.isExpanded = YES; } @@ -270,7 +269,6 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell"; id item = userInfo[@"NSObject"]; id representedObject = [item representedObject]; if([representedObject isKindOfClass:[KPKGroup class]]) { - NSLog(@"collapsed:%@",representedObject); KPKGroup *group = (KPKGroup *)representedObject; group.isExpanded = NO; } diff --git a/MacPass/MPPasswordEditWindowController.h b/MacPass/MPPasswordEditWindowController.h index c197b057..53da6575 100644 --- a/MacPass/MPPasswordEditWindowController.h +++ b/MacPass/MPPasswordEditWindowController.h @@ -11,6 +11,17 @@ @class MPDocument; @class HNHRoundedSecureTextField; +@protocol MPPasswordEditWindowDelegate + +@optional +/** + * Get's called on dismissing the password editor. + * @param changedPasswordOrKey YES if the password and/or key was saved (not necessairly changed!); + */ +- (void)didFinishPasswordEditing:(BOOL)changedPasswordOrKey; + +@end + @interface MPPasswordEditWindowController : MPSheetWindowController @property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField; @@ -19,6 +30,9 @@ @property (weak) IBOutlet NSButton *togglePasswordButton; @property (weak) IBOutlet NSTextField *errorTextField; @property (weak) IBOutlet NSButton *changePasswordButton; +@property (nonatomic,assign) BOOL allowsEmptyPasswordOrKey; + +@property (weak) id delegate; /** * Dedicated initializer for the Windowcontroller diff --git a/MacPass/MPPasswordEditWindowController.m b/MacPass/MPPasswordEditWindowController.m index e76b3e30..2daee0e2 100644 --- a/MacPass/MPPasswordEditWindowController.m +++ b/MacPass/MPPasswordEditWindowController.m @@ -29,6 +29,7 @@ - (id)initWithDocument:(MPDocument *)document { self = [super initWithWindowNibName:@"PasswordEditWindow"]; if(self){ + _allowsEmptyPasswordOrKey = YES; _showPassword = NO; _hasValidPasswordOrKey = NO; _document = document; @@ -84,10 +85,16 @@ _document.password = [self.passwordTextField stringValue]; _document.key = [self.keyfilePathControl URL]; [self dismissSheet:NSRunStoppedResponse]; + if(self.delegate && [self.delegate respondsToSelector:@selector(didFinishPasswordEditing:)]) { + [self.delegate didFinishPasswordEditing:YES]; + } } - (IBAction)cancel:(id)sender { [self dismissSheet:NSRunAbortedResponse]; + if(self.delegate && [self.delegate respondsToSelector:@selector(didFinishPasswordEditing:)]) { + [self.delegate didFinishPasswordEditing:NO]; + } } - (IBAction)clearKey:(id)sender { @@ -138,7 +145,7 @@ BOOL hasPasswordOrKey = (hasKey || hasPassword); keyOk = hasKey ? keyOk : YES; passwordOk = hasPassword ? passwordOk : YES; - self.hasValidPasswordOrKey = passwordOk && keyOk; + self.hasValidPasswordOrKey = (hasPasswordOrKey || self.allowsEmptyPasswordOrKey ) && passwordOk && keyOk; if(!hasPasswordOrKey) { [self.errorTextField setTextColor:[NSColor controlTextColor]]; diff --git a/MacPass/MPSavePanelAccessoryViewController.h b/MacPass/MPSavePanelAccessoryViewController.h index 1b9e5515..a806c5da 100644 --- a/MacPass/MPSavePanelAccessoryViewController.h +++ b/MacPass/MPSavePanelAccessoryViewController.h @@ -19,5 +19,9 @@ @property (nonatomic, weak) IBOutlet NSPopUpButton *fileTypePopupButton; @property (nonatomic, weak) IBOutlet NSTextField *infoTextField; +/** + * Updates the view to current state + */ +- (void)updateView; @end diff --git a/MacPass/MPSavePanelAccessoryViewController.m b/MacPass/MPSavePanelAccessoryViewController.m index 364158b7..bcfc0390 100644 --- a/MacPass/MPSavePanelAccessoryViewController.m +++ b/MacPass/MPSavePanelAccessoryViewController.m @@ -41,7 +41,7 @@ } [self.fileTypePopupButton setMenu:menu]; [self.infoTextField setHidden:YES]; - [self _updateView]; + [self updateView]; } - (IBAction)setFileType:(id)sender { @@ -59,11 +59,11 @@ - (void)setDocument:(MPDocument *)document { if(_document != document) { _document = document; - [self _updateView]; + [self updateView]; } } -- (void)_updateView { +- (void)updateView { switch(self.document.versionForFileType) { case KPKLegacyVersion: [self.fileTypePopupButton selectItemAtIndex:1];