diff --git a/Cartfile b/Cartfile index b3db7dcf..54e3f2ff 100644 --- a/Cartfile +++ b/Cartfile @@ -1,3 +1,3 @@ github "sparkle-project/Sparkle" ~> 1.17.0 -github "mstarke/KeePassKit" "ab95d3a85b2bcb86d9e3e5e74d2168c209756b8b" +github "mstarke/KeePassKit" "b25eab0892f6101ee4929bef3f57788dbc5fa607" github "mstarke/HNHUi" ~> 1.1 diff --git a/Cartfile.resolved b/Cartfile.resolved index 7af78158..a085d4ea 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ github "mstarke/HNHUi" "1.1" -github "mstarke/KeePassKit" "ab95d3a85b2bcb86d9e3e5e74d2168c209756b8b" +github "mstarke/KeePassKit" "b25eab0892f6101ee4929bef3f57788dbc5fa607" github "sparkle-project/Sparkle" "1.17.0" diff --git a/MacPass/Base.lproj/EntryInspectorView.xib b/MacPass/Base.lproj/EntryInspectorView.xib index 0e71f501..299e796b 100644 --- a/MacPass/Base.lproj/EntryInspectorView.xib +++ b/MacPass/Base.lproj/EntryInspectorView.xib @@ -1,14 +1,16 @@ - + - - + + + + @@ -21,6 +23,7 @@ + @@ -94,7 +97,7 @@ - + @@ -271,7 +274,7 @@ - + diff --git a/MacPass/MPActionHelper.h b/MacPass/MPActionHelper.h index 822e868a..105854b0 100644 --- a/MacPass/MPActionHelper.h +++ b/MacPass/MPActionHelper.h @@ -31,7 +31,8 @@ typedef NS_ENUM(NSUInteger, MPActionType) { MPActionToggleQuicklook, MPActionShowEntryHistory, // show history MPActionHideEntryHistory, // exit history - MPActionPerformAutotypeForSelectedEntry // Perform Autotype for selected Entry + MPActionPerformAutotypeForSelectedEntry, // Perform Autotype for selected Entry + MPActionRemoveAttachment // Remove an attachment }; /** * Helper to retrieve commonly used actions diff --git a/MacPass/MPActionHelper.m b/MacPass/MPActionHelper.m index 791de86d..fad4bfea 100644 --- a/MacPass/MPActionHelper.m +++ b/MacPass/MPActionHelper.m @@ -40,7 +40,8 @@ @(MPActionToggleQuicklook): NSStringFromSelector(@selector(toggleQuicklookPreview:)), @(MPActionShowEntryHistory): NSStringFromSelector(@selector(showEntryHistory:)), @(MPActionHideEntryHistory): NSStringFromSelector(@selector(hideEntryHistory:)), - @(MPActionPerformAutotypeForSelectedEntry): NSStringFromSelector(@selector(performAutotypeForEntry:)) + @(MPActionPerformAutotypeForSelectedEntry): NSStringFromSelector(@selector(performAutotypeForEntry:)), + @(MPActionRemoveAttachment): NSStringFromSelector(@selector(removeAttachment:)) }; }); return actionDict; diff --git a/MacPass/MPCustomFieldTableViewDelegate.m b/MacPass/MPCustomFieldTableViewDelegate.m index 071ff574..d00f04e0 100644 --- a/MacPass/MPCustomFieldTableViewDelegate.m +++ b/MacPass/MPCustomFieldTableViewDelegate.m @@ -30,7 +30,7 @@ - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { MPCustomFieldTableCellView *view = [tableView makeViewWithIdentifier:@"SelectedCell" owner:tableView]; - + [view.labelTextField bind:NSValueBinding toObject:view withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(objectValue)), NSStringFromSelector(@selector(key))] @@ -39,6 +39,14 @@ toObject:view withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(objectValue)), NSStringFromSelector(@selector(value))] options:nil]; + // TODO: Move to public KeePassKit API! + for(NSControl *control in @[view.labelTextField, view.valueTextField, view.removeButton ]) { + [control bind:NSEnabledBinding + toObject:view + withKeyPath:[NSString stringWithFormat:@"%@.%@.%@", NSStringFromSelector(@selector(objectValue)), NSStringFromSelector(@selector(entry)), NSStringFromSelector(@selector(isHistory))] + options:@{NSConditionallySetsEditableBindingOption: @NO, NSValueTransformerNameBindingOption: NSNegateBooleanTransformerName}]; + + } view.removeButton.target = self.viewController; view.removeButton.action = @selector(removeCustomField:); view.removeButton.tag = row; diff --git a/MacPass/MPDocument+History.m b/MacPass/MPDocument+History.m index 24a0f9a9..5589e183 100644 --- a/MacPass/MPDocument+History.m +++ b/MacPass/MPDocument+History.m @@ -22,17 +22,22 @@ NSString *const MPDocumentHideEntryHistoryNotification = @"MPDocumentHideEntryH if(self.hasSearch) { [self exitSearch:sender]; } - [[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentShowEntryHistoryNotification - object:self - userInfo:@{ MPDocumentEntryKey: entries.firstObject }]; + self.historyEntry = entries.firstObject; + if(self.historyEntry) { + [[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentShowEntryHistoryNotification + object:self + userInfo:@{ MPDocumentEntryKey: self.historyEntry }]; + } } - (void)hideEntryHistory:(id)sender { + self.historyEntry = nil; [[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentHideEntryHistoryNotification object:self]; } - (void)revertEntry:(KPKEntry *)entry toEntry:(KPKEntry *)historyEntry { + [entry pushHistory]; [entry revertToEntry:historyEntry]; [self.undoManager setActionName:NSLocalizedString(@"RESTORE_HISTORY_ENTRY", "Action to restore and Entry to a previous state of it's history")]; } diff --git a/MacPass/MPDocument.h b/MacPass/MPDocument.h index de4d36c0..46b0f0b0 100644 --- a/MacPass/MPDocument.h +++ b/MacPass/MPDocument.h @@ -95,6 +95,7 @@ FOUNDATION_EXPORT NSString *const MPDocumentGroupKey; @property (nonatomic, readonly) BOOL hasSearch; @property (nonatomic, copy) MPEntrySearchContext *searchContext; @property (nonatomic, strong, readonly) NSArray *searchResult; +@property (nonatomic, weak) KPKEntry *historyEntry; + (KPKDatabaseFormat)formatForFileType:(NSString *)fileType; + (NSString *)fileTypeForVersion:(KPKDatabaseFormat)format; diff --git a/MacPass/MPEntryInspectorViewController.h b/MacPass/MPEntryInspectorViewController.h index b947b976..13544459 100644 --- a/MacPass/MPEntryInspectorViewController.h +++ b/MacPass/MPEntryInspectorViewController.h @@ -27,14 +27,18 @@ @property (weak) IBOutlet HNHUIRoundedSecureTextField *passwordTextField; @property (weak) IBOutlet NSButton *generatePasswordButton; @property (weak) IBOutlet NSButton *togglePassword; +@property (weak) IBOutlet NSButton *pickExpireDateButton; @property (weak) IBOutlet NSButton *expiresCheckButton; @property (weak) IBOutlet NSTokenField *tagsTokenField; @property (weak) IBOutlet NSTextField *uuidTextField; @property (weak) IBOutlet NSTextField *createdTextField; @property (weak) IBOutlet NSTextField *modifiedTextField; +@property (weak) IBOutlet NSButton *addCustomFieldButton; /* Attachments */ +@property (weak) IBOutlet NSButtonCell *addAttachmentButton; + @property (weak) IBOutlet NSTableView *attachmentTableView; @property (weak) IBOutlet NSTableView *customFieldsTableView; @@ -50,6 +54,7 @@ @property (weak) IBOutlet NSButton *showCustomAssociationSequenceAutotypeBuilderButton; @property (weak) IBOutlet NSTextField *associationSequenceTextField; +@property (weak) IBOutlet NSButton *addWindowAssociationButton; - (void)registerNotificationsForDocument:(MPDocument *)document; diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index 1fb5417f..e956bac7 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -240,6 +240,8 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { case MPActionToggleQuicklook: { BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyEnableQuicklookPreview]; return enabled ? [self acceptsPreviewPanelControl:nil] : NO; + case MPActionRemoveAttachment: + return !self.representedEntry.isHistory; } default: return YES; @@ -360,13 +362,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { #pragma mark - #pragma mark Entry Selection - (void)_setupViewBindings { - [self _bindEntry]; - [self _bindAttachments]; - [self _bindCustomFields]; - [self _bindAutotype]; -} - -- (void)_bindEntry { + /* general */ [self.titleTextField bind:NSValueBinding toObject:self withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(title))] @@ -396,21 +392,6 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(tags))] options:nil]; - NSArray *inputs = @[self.titleTextField, - self.passwordTextField, - self.usernameTextField, - self.URLTextField, - self.expiresCheckButton, - self.tagsTokenField, - self.generatePasswordButton]; - - for(NSControl *control in inputs) { - NSString *keyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(isHistory))]; - [control bind:NSEnabledBinding - toObject:self - withKeyPath:keyPath - options:@{NSConditionallySetsEditableBindingOption: @NO, NSValueTransformerNameBindingOption: NSNegateBooleanTransformerName}]; - } [self.uuidTextField bind:NSValueBinding toObject:self @@ -418,23 +399,19 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { options:@{ NSConditionallySetsEditableBindingOption: @NO }]; self.uuidTextField.editable = NO; -} - -- (void)_bindAttachments { + /* Attachments */ [_attachmentsController bind:NSContentArrayBinding toObject:self withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(binaries))] options:nil]; -} -- (void)_bindCustomFields { + /* CustomField */ [_customFieldsController bind:NSContentArrayBinding toObject:self withKeyPath:[NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(customAttributes))] options:nil]; -} -- (void)_bindAutotype { + /* Autotype */ [self.enableAutotypeCheckButton bind:NSValueBinding toObject:self withKeyPath:[NSString stringWithFormat:@"%@.%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(autotype)), NSStringFromSelector(@selector(enabled))] options:nil]; @@ -464,6 +441,27 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { toObject:_windowAssociationsController withKeyPath:[NSString stringWithFormat:@"selection.%@", NSStringFromSelector(@selector(keystrokeSequence))] options:nil]; + + NSArray *inputs = @[self.titleTextField, + self.passwordTextField, + self.usernameTextField, + self.URLTextField, + self.expiresCheckButton, + self.tagsTokenField, + self.generatePasswordButton, + self.addAttachmentButton, + self.addCustomFieldButton, + self.addWindowAssociationButton]; + + for(NSControl *control in inputs) { + NSString *keyPath = [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(representedObject)), NSStringFromSelector(@selector(isHistory))]; + [control bind:NSEnabledBinding + toObject:self + withKeyPath:keyPath + options:@{NSConditionallySetsEditableBindingOption: @NO, NSValueTransformerNameBindingOption: NSNegateBooleanTransformerName}]; + } + + } diff --git a/MacPass/MPEntryViewController.m b/MacPass/MPEntryViewController.m index 1e8ef996..890a568e 100644 --- a/MacPass/MPEntryViewController.m +++ b/MacPass/MPEntryViewController.m @@ -735,7 +735,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell"; if(historyEntries.count != 1) { return; } - //[document restoreEntry:entry toEntry:historyEntries.firstObject]; + [document revertEntry:document.historyEntry toEntry:historyEntries.firstObject]; } - (void)_columnDoubleClick:(id)sender {