mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-13 21:42:32 +00:00
Fixed #46 Binaries get now deleted when entries are delete on trans cleaning
MenuEntries are validated and disabled to fix #58. Model still doesn't do any testing
This commit is contained in:
Submodule KeePassKit updated: 8008d6209f...428a53af6c
@@ -235,6 +235,15 @@
|
||||
<reference key="NSOnImage" ref="35465992"/>
|
||||
<reference key="NSMixedImage" ref="502551668"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="919874146">
|
||||
<reference key="NSMenu" ref="720053764"/>
|
||||
<string key="NSTitle">Lock</string>
|
||||
<string key="NSKeyEquiv">L</string>
|
||||
<int key="NSKeyEquivModMask">262144</int>
|
||||
<int key="NSMnemonicLoc">2147483647</int>
|
||||
<reference key="NSOnImage" ref="35465992"/>
|
||||
<reference key="NSMixedImage" ref="502551668"/>
|
||||
</object>
|
||||
<object class="NSMenuItem" id="776162233">
|
||||
<reference key="NSMenu" ref="720053764"/>
|
||||
<string key="NSTitle">Close</string>
|
||||
@@ -828,6 +837,14 @@
|
||||
</object>
|
||||
<int key="connectionID">1260</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">lock:</string>
|
||||
<reference key="source" ref="1014"/>
|
||||
<reference key="destination" ref="919874146"/>
|
||||
</object>
|
||||
<int key="connectionID">1263</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBActionConnection" key="connection">
|
||||
<string key="label">showPreferences:</string>
|
||||
@@ -932,6 +949,7 @@
|
||||
<reference ref="544639599"/>
|
||||
<reference ref="663106531"/>
|
||||
<reference ref="438377242"/>
|
||||
<reference ref="919874146"/>
|
||||
</array>
|
||||
<reference key="parent" ref="379814623"/>
|
||||
</object>
|
||||
@@ -1272,6 +1290,11 @@
|
||||
<reference key="object" ref="438377242"/>
|
||||
<reference key="parent" ref="720053764"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1261</int>
|
||||
<reference key="object" ref="919874146"/>
|
||||
<reference key="parent" ref="720053764"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
@@ -1291,6 +1314,7 @@
|
||||
<string key="125.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="1259.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="126.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="1261.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="129.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
<string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||
@@ -1346,7 +1370,7 @@
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">1260</int>
|
||||
<int key="maxID">1263</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
@@ -1407,6 +1431,7 @@
|
||||
<dictionary class="NSMutableDictionary" key="actions">
|
||||
<string key="editPassword:">id</string>
|
||||
<string key="exportDatabase:">id</string>
|
||||
<string key="lock:">id</string>
|
||||
<string key="showDatabaseSettings:">id</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="actionInfosByName">
|
||||
@@ -1418,6 +1443,10 @@
|
||||
<string key="name">exportDatabase:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="lock:">
|
||||
<string key="name">lock:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="showDatabaseSettings:">
|
||||
<string key="name">showDatabaseSettings:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MPActionType) {
|
||||
MPUnkownAction, // Netural element to be used for returns
|
||||
MPActionAddEntry, // Add an new entry
|
||||
MPActionAddGroup, // Add a new group
|
||||
MPActionEdit, // Edit entry or group
|
||||
MPActionDelete, // Delete entry or group
|
||||
MPActionCopyUsername, // copy username to pasteboard
|
||||
MPActionCopyPassword, // copy password to pasteboard
|
||||
@@ -25,5 +25,6 @@ typedef NS_ENUM(NSUInteger, MPActionType) {
|
||||
@interface MPActionHelper : NSObject
|
||||
|
||||
+ (SEL)actionOfType:(MPActionType)type;
|
||||
+ (MPActionType)typeForAction:(SEL)action;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,25 +10,42 @@
|
||||
|
||||
@implementation MPActionHelper
|
||||
|
||||
+ (SEL)actionOfType:(MPActionType)type {
|
||||
+ (NSDictionary *)_actionDictionary {
|
||||
static NSDictionary *actionDict;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
actionDict = @{
|
||||
@(MPActionAddEntry) : @"createEntry:",
|
||||
@(MPActionAddGroup) : @"createGroup:",
|
||||
@(MPActionCopyPassword) : @"copyPassword:",
|
||||
@(MPActionCopyURL) : @"copyURL:",
|
||||
@(MPActionCopyUsername) : @"copyUsername:",
|
||||
@(MPActionDelete) : @"deleteNode:",
|
||||
@(MPActionEdit) : @"editEntry:",
|
||||
@(MPActionOpenURL) : @"openURL:",
|
||||
@(MPActionToggleInspector) : @"toggleInspector:",
|
||||
@(MPActionLock) : @"lock:",
|
||||
@(MPActionEmptyTrash) : @"emptyTrash:"
|
||||
};
|
||||
@(MPActionAddEntry) : @"createEntry:",
|
||||
@(MPActionAddGroup) : @"createGroup:",
|
||||
@(MPActionCopyPassword) : @"copyPassword:",
|
||||
@(MPActionCopyURL) : @"copyURL:",
|
||||
@(MPActionCopyUsername) : @"copyUsername:",
|
||||
@(MPActionDelete) : @"deleteNode:",
|
||||
@(MPActionOpenURL) : @"openURL:",
|
||||
@(MPActionToggleInspector) : @"toggleInspector:",
|
||||
@(MPActionLock) : @"lock:",
|
||||
@(MPActionEmptyTrash) : @"emptyTrash:"
|
||||
};
|
||||
});
|
||||
return actionDict;
|
||||
}
|
||||
|
||||
+ (SEL)actionOfType:(MPActionType)type {
|
||||
NSDictionary *actionDict = [self _actionDictionary];
|
||||
return NSSelectorFromString(actionDict[@(type)]);
|
||||
}
|
||||
|
||||
+ (MPActionType)typeForAction:(SEL)action {
|
||||
NSString *selectorString = NSStringFromSelector(action);
|
||||
NSArray *selectors = [[self _actionDictionary] allValues];
|
||||
NSUInteger index = [selectors indexOfObject:selectorString];
|
||||
if(index == NSNotFound) {
|
||||
return MPUnkownAction;
|
||||
}
|
||||
NSArray *keys = [[self _actionDictionary] allKeysForObject:selectorString];
|
||||
NSAssert([keys count] == 1, @"There should only be one object for the specified key");
|
||||
return [[keys lastObject] integerValue];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -42,6 +42,7 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
||||
@property (strong, readonly, nonatomic) KdbTree *tree;
|
||||
@property (weak, readonly, nonatomic) KdbGroup *root;
|
||||
@property (readonly, strong) MPRootAdapter *rootAdapter;
|
||||
@property (weak, readonly) KdbGroup *trash;
|
||||
|
||||
@property (nonatomic, copy) NSString *password;
|
||||
@property (nonatomic, strong) NSURL *key;
|
||||
@@ -68,6 +69,8 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
||||
- (void)useGroupAsTrash:(KdbGroup *)group;
|
||||
- (void)useGroupAsTemplate:(KdbGroup *)group;
|
||||
|
||||
- (BOOL)isItemTrashed:(id)item;
|
||||
|
||||
#pragma mark Export
|
||||
- (void)writeXMLToURL:(NSURL *)url;
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||
@property (strong) NSURL *lockFileURL;
|
||||
|
||||
@property (readonly) BOOL useTrash;
|
||||
@property (weak, readonly) KdbGroup *trash;
|
||||
@property (strong) IBOutlet NSView *warningView;
|
||||
@property (weak) IBOutlet NSImageView *warningViewImage;
|
||||
|
||||
@@ -307,6 +306,26 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isItemTrashed:(id)item {
|
||||
BOOL validItem = [item isKindOfClass:[KdbEntry class]] || [item isKindOfClass:[KdbGroup class]];
|
||||
if(!item) {
|
||||
return NO;
|
||||
}
|
||||
if(item == self.trash) {
|
||||
return NO; // No need to look further as this is the trashcan
|
||||
}
|
||||
if(validItem) {
|
||||
BOOL isTrashed = NO;
|
||||
id parent = [item parent];
|
||||
while( parent && !isTrashed ) {
|
||||
isTrashed = (parent == self.trash);
|
||||
parent = [parent parent];
|
||||
}
|
||||
return isTrashed;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)useGroupAsTrash:(KdbGroup *)group {
|
||||
if(self.useTrash) {
|
||||
Kdb4Group *groupv4 = (Kdb4Group *)group;
|
||||
@@ -449,6 +468,9 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)emptyTrash:(id)sender {
|
||||
if(self.version != MPDatabaseVersion4) {
|
||||
return; // We have no trash on those file types
|
||||
}
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
[alert setMessageText:NSLocalizedString(@"WARNING_ON_EMPTY_TRASH_TITLE", "")];
|
||||
@@ -474,6 +496,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||
BOOL hasEntries = [self.trash.entries count] > 0;
|
||||
return (hasEntries || hasGroups);
|
||||
}
|
||||
|
||||
return [super validateUserInterfaceItem:anItem];
|
||||
}
|
||||
|
||||
@@ -517,7 +540,24 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||
for(KdbGroup *group in [self.trash childGroups]) {
|
||||
[[self undoManager] removeAllActionsWithTarget:group];
|
||||
}
|
||||
[self _cleanTrashedBinaries];
|
||||
[self.trash clear];
|
||||
}
|
||||
|
||||
- (void)_cleanTrashedBinaries {
|
||||
NSMutableSet *clearKeys = [[NSMutableSet alloc] initWithCapacity:20];
|
||||
NSMutableArray *clearBinaries = [[NSMutableArray alloc] initWithCapacity:[self.treeV4.binaries count]];
|
||||
for(Kdb4Entry *entry in [self.trash childEntries]) {
|
||||
for(BinaryRef *binaryRef in entry.binaries) {
|
||||
[clearKeys addObject:@(binaryRef.ref)];
|
||||
}
|
||||
}
|
||||
for(Binary *binary in self.treeV4.binaries) {
|
||||
if([clearKeys containsObject:@(binary.binaryId)]) {
|
||||
[clearBinaries addObject:binary];
|
||||
}
|
||||
}
|
||||
[self.treeV4.binaries removeObjectsInArray:clearBinaries];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -32,6 +32,12 @@ APPKIT_EXTERN NSString *const MPCurrentItemChangedNotification;
|
||||
@property (readonly, unsafe_unretained) KdbGroup *currentGroup;
|
||||
@property (readonly, unsafe_unretained) KdbEntry *currentEntry;
|
||||
|
||||
/**
|
||||
@param action The action that should be validatet
|
||||
@param item The item that the action affects. Pass nil to fall back for default item
|
||||
@returns YES if the action is valid, NO otherwise
|
||||
*/
|
||||
- (BOOL)validateAction:(SEL)action forItem:(id)item;
|
||||
|
||||
- (void)showEntries;
|
||||
- (void)showPasswordInput;
|
||||
@@ -40,7 +46,7 @@ APPKIT_EXTERN NSString *const MPCurrentItemChangedNotification;
|
||||
- (IBAction)showDatabaseSettings:(id)sender;
|
||||
- (IBAction)exportDatabase:(id)sender;
|
||||
|
||||
- (void)lock:(id)sender;
|
||||
- (IBAction)lock:(id)sender;
|
||||
|
||||
- (void)createGroup:(id)sender;
|
||||
- (void)toggleInspector:(id)sender;
|
||||
|
||||
@@ -192,6 +192,9 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
|
||||
if(itemAction == @selector(exportDatabase:)) {
|
||||
enabled = (nil != document.treeV4);
|
||||
}
|
||||
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
|
||||
enabled &= (nil != _currentItem) && (_currentItem != document.trash);
|
||||
}
|
||||
|
||||
enabled &= !( !document.decrypted || document.isLocked || document.isReadOnly );
|
||||
return enabled;
|
||||
@@ -202,20 +205,55 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
|
||||
if(!document.decrypted || document.isLocked || document.isReadOnly) {
|
||||
return NO;
|
||||
}
|
||||
SEL itemAction = [theItem action];
|
||||
if( itemAction == [MPActionHelper actionOfType:MPActionLock]) {
|
||||
return document.hasPasswordOrKey;
|
||||
MPActionType actionType = [MPActionHelper typeForAction:[theItem action]];
|
||||
switch (actionType) {
|
||||
case MPActionAddGroup:
|
||||
case MPActionAddEntry:
|
||||
return (nil != _outlineViewController.selectedGroup);
|
||||
case MPActionDelete: {
|
||||
BOOL valid = (nil != _currentItem);
|
||||
valid &= (_currentItem != document.trash);
|
||||
valid &= ![document isItemTrashed:_currentItem];
|
||||
return valid;
|
||||
}
|
||||
case MPActionLock:
|
||||
return document.hasPasswordOrKey;
|
||||
|
||||
case MPActionToggleInspector:
|
||||
return (nil != [_splitView superview]);
|
||||
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
if(itemAction == [MPActionHelper actionOfType:MPActionAddEntry]) {
|
||||
return (nil != _outlineViewController.selectedGroup);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)validateAction:(SEL)action forItem:(id)item {
|
||||
MPDocument *document = [self document];
|
||||
if(!document.decrypted || document.isLocked || document.isReadOnly) {
|
||||
return NO;
|
||||
}
|
||||
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
|
||||
return (nil != _currentItem);
|
||||
MPActionType actionType = [MPActionHelper typeForAction:action];
|
||||
switch (actionType) {
|
||||
case MPActionAddGroup:
|
||||
case MPActionAddEntry:
|
||||
// test if Group is in trash
|
||||
return (nil != _outlineViewController.selectedGroup);
|
||||
case MPActionDelete: {
|
||||
BOOL valid = (nil != _currentItem);
|
||||
valid &= (_currentItem != document.trash);
|
||||
valid &= ![document isItemTrashed:_currentItem];
|
||||
return valid;
|
||||
}
|
||||
case MPActionLock:
|
||||
return document.hasPasswordOrKey;
|
||||
|
||||
case MPActionToggleInspector:
|
||||
return (nil != [_splitView superview]);
|
||||
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
if(itemAction == [MPActionHelper actionOfType:MPActionToggleInspector]) {
|
||||
return (nil != [_splitView superview]);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -235,7 +273,7 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
|
||||
[self _showDatabaseSetting:MPDatabaseSettingsTabGeneral];
|
||||
}
|
||||
|
||||
- (void)lock:(id)sender {
|
||||
- (IBAction)lock:(id)sender {
|
||||
MPDocument *document = [self document];
|
||||
if(!document.hasPasswordOrKey) {
|
||||
return; // Document needs a password/keyfile to be lockable
|
||||
|
||||
@@ -513,6 +513,11 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
[document deleteEntry:entry];
|
||||
}
|
||||
|
||||
#pragma mark Validation
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)_toggleFilterSpace:(id)sender {
|
||||
NSButton *button = sender;
|
||||
NSNumber *value = self.filterButtonToMode[[button identifier]];
|
||||
|
||||
@@ -137,6 +137,29 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Validation
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
|
||||
MPActionType actionType = [MPActionHelper typeForAction:[menuItem action]];
|
||||
switch(actionType) {
|
||||
case MPActionAddEntry:
|
||||
case MPActionAddGroup:
|
||||
case MPActionDelete: {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
id selected = [self _clickedOrSelectedGroup];
|
||||
if(!selected) {
|
||||
return NO;
|
||||
}
|
||||
if(selected == document.trash) {
|
||||
return NO;
|
||||
}
|
||||
return ![document isItemTrashed:selected];
|
||||
}
|
||||
default:
|
||||
return YES; // We are only validated for three targets
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Actions
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
NSString *const MPToolbarItemLock = @"TOOLBAR_LOCK";
|
||||
NSString *const MPToolbarItemAddGroup = @"TOOLBAR_ADD_GROUP";
|
||||
NSString *const MPToolbarItemAddEntry = @"TOOLBAR_ADD_ENTRY";
|
||||
NSString *const MPToolbarItemEdit = @"TOOLBAR_EDIT";
|
||||
NSString *const MPToolbarItemDelete =@"TOOLBAR_DELETE";
|
||||
NSString *const MPToolbarItemAction = @"TOOLBAR_ACTION";
|
||||
NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
|
||||
@@ -135,7 +134,6 @@ NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
|
||||
MPToolbarItemAddEntry: NSLocalizedString(@"ADD_ENTRY", @""),
|
||||
MPToolbarItemAddGroup: NSLocalizedString(@"ADD_GROUP", @""),
|
||||
MPToolbarItemDelete: NSLocalizedString(@"DELETE", @""),
|
||||
MPToolbarItemEdit: NSLocalizedString(@"EDIT", @""),
|
||||
MPToolbarItemInspector: NSLocalizedString(@"INSPECTOR", @"")
|
||||
};
|
||||
return labelDict[identifier];
|
||||
@@ -146,7 +144,6 @@ NSString *const MPToolbarItemInspector = @"TOOLBAR_INSPECTOR";
|
||||
MPToolbarItemAddEntry: @(MPActionAddEntry),
|
||||
MPToolbarItemAddGroup: @(MPActionAddGroup),
|
||||
MPToolbarItemDelete: @(MPActionDelete),
|
||||
MPToolbarItemEdit: @(MPActionEdit),
|
||||
MPToolbarItemInspector: @(MPActionToggleInspector)
|
||||
};
|
||||
MPActionType actionType = (MPActionType)[actionDict[identifier] integerValue];
|
||||
|
||||
Reference in New Issue
Block a user