mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-24 08:49:42 +00:00
Started Move to KeePassKit - Project compiles but does NOT work properly
Removed MiniKeePass Categories. Moved Random streams form MiniKeePass to KeePassKit Changed MacPass to use KeePassKit
This commit is contained in:
15
MacPass/KPKNode+IconImage.h
Normal file
15
MacPass/KPKNode+IconImage.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// KPKNode+IconImage.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 31.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KPKNode.h"
|
||||
|
||||
@interface KPKNode (IconImage)
|
||||
|
||||
@property (nonatomic, readonly) NSImage *iconImage;
|
||||
|
||||
@end
|
||||
26
MacPass/KPKNode+IconImage.m
Normal file
26
MacPass/KPKNode+IconImage.m
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// KPKNode+IconImage.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 31.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KPKNode+IconImage.h"
|
||||
|
||||
#import "KPKIcon.h"
|
||||
|
||||
#import "MPIconHelper.h"
|
||||
|
||||
@implementation KPKNode (IconImage)
|
||||
|
||||
- (NSImage *)iconImage {
|
||||
if([self respondsToSelector:@selector(customIconUuid)]) {
|
||||
// find the custom icon
|
||||
}
|
||||
if(self.customIcon) {
|
||||
return self.customIcon.image;
|
||||
}
|
||||
return [MPIconHelper icon:(MPIconType)self.icon];
|
||||
}
|
||||
@end
|
||||
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// Kdb3Entry+KVOAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb3Node.h"
|
||||
|
||||
@interface Kdb3Entry (KVOAdditions)
|
||||
|
||||
- (NSUInteger)countOfBinaries;
|
||||
- (id)objectInBinariesAtIndex:(NSUInteger)index;
|
||||
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index;
|
||||
- (void)insertObject:(id)binary inBinariesAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,31 +0,0 @@
|
||||
//
|
||||
// Kdb3Entry+KVOAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb3Entry+KVOAdditions.h"
|
||||
|
||||
@implementation Kdb3Entry (KVOAdditions)
|
||||
|
||||
- (NSUInteger)countOfBinaries {
|
||||
return (self.binary != nil ? 1 : 0);
|
||||
}
|
||||
- (id)objectInBinariesAtIndex:(NSUInteger)index {
|
||||
return self.binary;
|
||||
}
|
||||
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index {
|
||||
if(self.binary ) {
|
||||
self.binary = nil;
|
||||
self.binaryDesc = nil;
|
||||
}
|
||||
}
|
||||
- (void)insertObject:(id)binary inBinariesAtIndex:(NSUInteger)index {
|
||||
return;//
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Kdb3Tree+NewTree.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 21.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb3Node.h"
|
||||
|
||||
@interface Kdb3Tree (NewTree)
|
||||
|
||||
+ (Kdb3Tree *)templateTree;
|
||||
|
||||
@end
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// Kdb3Tree+NewTree.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 21.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb3Tree+NewTree.h"
|
||||
|
||||
@implementation Kdb3Tree (NewTree)
|
||||
|
||||
+ (Kdb3Tree *)templateTree {
|
||||
Kdb3Tree *tree = [[Kdb3Tree alloc] init];
|
||||
|
||||
Kdb3Group *rootGroup = [[Kdb3Group alloc] init];
|
||||
rootGroup.name = @"%ROOT%";
|
||||
tree.root = rootGroup;
|
||||
|
||||
KdbGroup *parentGroup = [tree createGroup:rootGroup];
|
||||
parentGroup.name = NSLocalizedString(@"GENERAL", "General");
|
||||
parentGroup.image = 48;
|
||||
[rootGroup addGroup:parentGroup];
|
||||
|
||||
KdbGroup *group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"WINDOWS", "Windows");
|
||||
group.image = 38;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"NETWORK", "Network");
|
||||
group.image = 3;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"INTERNET", "Internet");
|
||||
group.image = 1;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"EMAIL", "EMail");
|
||||
group.image = 19;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"HOMEBANKING", "Homebanking");
|
||||
group.image = 37;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Kdb4Entry+KVOAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 28.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface Kdb4Entry (KVOAdditions)
|
||||
|
||||
- (NSUInteger)countOfStringFields;
|
||||
- (StringField *)objectInStringFieldsAtIndex:(NSUInteger)index;
|
||||
- (void)removeObjectFromStringFieldsAtIndex:(NSUInteger)anIndex;
|
||||
- (void)insertObject:(StringField *)stringfield inStringFieldsAtIndex:(NSUInteger)anIndex;
|
||||
|
||||
- (NSUInteger)countOfBinaries;
|
||||
- (BinaryRef *)objectInBinariesAtIndex:(NSUInteger)index;
|
||||
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index;
|
||||
- (void)insertObject:(BinaryRef *)binary inBinariesAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,47 +0,0 @@
|
||||
//
|
||||
// Kdb4Entry+KVOAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 28.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Entry+KVOAdditions.h"
|
||||
|
||||
@implementation Kdb4Entry (KVOAdditions)
|
||||
|
||||
/* Entries */
|
||||
- (NSUInteger)countOfStringFields {
|
||||
return [self.stringFields count];
|
||||
}
|
||||
|
||||
- (StringField *)objectInStringFieldsAtIndex:(NSUInteger)index {
|
||||
return (self.stringFields)[index];
|
||||
}
|
||||
|
||||
- (void)insertObject:(StringField *)stringfield inStringFieldsAtIndex:(NSUInteger)anIndex {
|
||||
[self.stringFields insertObject:stringfield atIndex:anIndex];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromStringFieldsAtIndex:(NSUInteger)anIndex {
|
||||
[self.stringFields removeObjectAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/* Binaries */
|
||||
- (NSUInteger)countOfBinaries {
|
||||
return [self.binaries count];
|
||||
}
|
||||
|
||||
- (BinaryRef *)objectInBinariesAtIndex:(NSUInteger)index {
|
||||
return (self.binaries)[index];
|
||||
}
|
||||
|
||||
- (void)insertObject:(BinaryRef *)binary inBinariesAtIndex:(NSUInteger)index {
|
||||
[self.binaries insertObject:binary atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromBinariesAtIndex:(NSUInteger)index {
|
||||
[self.binaries removeObjectAtIndex:index];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Kdb4Entry+MPAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface Kdb4Entry (MPAdditions)
|
||||
|
||||
- (NSString *)uniqueKeyForProposal:(NSString *)key;
|
||||
|
||||
@end
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// Kdb4Entry+MPAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Entry+MPAdditions.h"
|
||||
|
||||
@implementation Kdb4Entry (MPAdditions)
|
||||
|
||||
- (NSString *)uniqueKeyForProposal:(NSString *)key {
|
||||
|
||||
if(key == nil) {
|
||||
key = NSLocalizedString(@"DEFAULT_CUSTOM_FIELD_TITLE", @"Default Titel for new Custom-Fields");
|
||||
}
|
||||
|
||||
NSArray *defaultKeys = @[ FIELD_TITLE,
|
||||
FIELD_USER_NAME,
|
||||
FIELD_PASSWORD,
|
||||
FIELD_URL,
|
||||
FIELD_NOTES ];
|
||||
NSMutableSet *keys = [[NSMutableSet alloc] initWithArray:defaultKeys];
|
||||
for(StringField *field in self.stringFields) {
|
||||
[keys addObject:field.key];
|
||||
}
|
||||
NSUInteger counter = 1;
|
||||
NSString *base = key;
|
||||
while([keys containsObject:key]) {
|
||||
key = [NSString stringWithFormat:@"%@-%ld", base, counter++];
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Kdb4Group+Undo.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface Kdb4Group (Undo)
|
||||
|
||||
- (NSString *)notesUndoable;
|
||||
- (void)setNotesUndoable:(NSString *)newNotes;
|
||||
|
||||
@end
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// Kdb4Group+Undo.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Group+Undo.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
|
||||
@implementation Kdb4Group (Undo)
|
||||
|
||||
- (NSString *)notesUndoable {
|
||||
return self.notes;
|
||||
}
|
||||
|
||||
- (void)setNotesUndoable:(NSString *)newNotes {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setNotesUndoable:) object:self.notes];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"SET_NOTES", "")];
|
||||
self.notes = newNotes;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,19 +0,0 @@
|
||||
//
|
||||
// Kdb4Tree+KVOAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 27.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface Kdb4Tree (KVOAdditions)
|
||||
|
||||
- (void)insertObject:(Binary *)binary inBinariesAtIndex:(NSUInteger)index;
|
||||
- (void)insertObject:(CustomIcon *)icon inCustomIconsAtIndex:(NSUInteger)index;
|
||||
|
||||
- (CustomIcon *)objectInCustomIconsAtIndex:(NSUInteger)index;
|
||||
- (Binary *)objectInBinariesAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,29 +0,0 @@
|
||||
//
|
||||
// Kdb4Tree+KVOAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 27.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Tree+KVOAdditions.h"
|
||||
|
||||
@implementation Kdb4Tree (KVOAdditions)
|
||||
|
||||
- (void)insertObject:(Binary *)binary inBinariesAtIndex:(NSUInteger)index {
|
||||
[self.binaries insertObject:binary atIndex:index];
|
||||
}
|
||||
|
||||
- (void)insertObject:(CustomIcon *)icon inCustomIconsAtIndex:(NSUInteger)index {
|
||||
[self.customIcons insertObject:icon atIndex:index];
|
||||
}
|
||||
|
||||
- (Binary *)objectInBinariesAtIndex:(NSUInteger)index {
|
||||
return (self.binaries)[index];
|
||||
}
|
||||
|
||||
- (CustomIcon *)objectInCustomIconsAtIndex:(NSUInteger)index {
|
||||
return (self.customIcons)[index];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Kdb4Tree+NewTree.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 21.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface Kdb4Tree (NewTree)
|
||||
|
||||
+(Kdb4Tree *)templateTree;
|
||||
+(Kdb4Tree *)demoTree;
|
||||
|
||||
@end
|
||||
@@ -1,123 +0,0 @@
|
||||
//
|
||||
// Kdb4Tree+NewTree.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 21.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Tree+NewTree.h"
|
||||
|
||||
@implementation Kdb4Tree (NewTree)
|
||||
|
||||
+ (Kdb4Tree *)templateTree {
|
||||
NSDate *currentTime = [NSDate date];
|
||||
|
||||
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
|
||||
tree.generator = @"MacPass";
|
||||
tree.databaseName = NSLocalizedString(@"DATABASE", "");
|
||||
tree.databaseNameChanged = currentTime;
|
||||
tree.databaseDescription = @"";
|
||||
tree.databaseDescriptionChanged = currentTime;
|
||||
tree.defaultUserName = @"";
|
||||
tree.defaultUserNameChanged = currentTime;
|
||||
tree.maintenanceHistoryDays = 365;
|
||||
tree.color = @"";
|
||||
tree.masterKeyChanged = currentTime;
|
||||
tree.masterKeyChangeRec = -1;
|
||||
tree.masterKeyChangeForce = -1;
|
||||
tree.protectTitle = NO;
|
||||
tree.protectUserName = NO;
|
||||
tree.protectPassword = YES;
|
||||
tree.protectUrl = NO;
|
||||
tree.protectNotes = NO;
|
||||
tree.recycleBinEnabled = YES;
|
||||
tree.recycleBinUuid = [UUID nullUuid];
|
||||
tree.recycleBinChanged = currentTime;
|
||||
tree.entryTemplatesGroup = [UUID nullUuid];
|
||||
tree.entryTemplatesGroupChanged = currentTime;
|
||||
tree.historyMaxItems = 10;
|
||||
tree.historyMaxSize = 6 * 1024 * 1024; // 6 MB
|
||||
tree.lastSelectedGroup = [UUID nullUuid];
|
||||
tree.lastTopVisibleGroup = [UUID nullUuid];
|
||||
|
||||
KdbGroup *parentGroup = [tree createGroup:nil];
|
||||
parentGroup.name = NSLocalizedString(@"GENERAL", "General");
|
||||
parentGroup.image = 48;
|
||||
tree.root = parentGroup;
|
||||
|
||||
KdbGroup *group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"WINDOWS", "Windows");
|
||||
group.image = 38;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"NETWORK", "Network");
|
||||
group.image = 3;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"INTERNET", "Internet");
|
||||
group.image = 1;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"EMAIL", "EMail");
|
||||
group.image = 19;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
group = [tree createGroup:parentGroup];
|
||||
group.name = NSLocalizedString(@"HOMEBANKING", "Homebanking");
|
||||
group.image = 37;
|
||||
[parentGroup addGroup:group];
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
+ (Kdb4Tree *)demoTree {
|
||||
NSDate *currentTime = [NSDate date];
|
||||
|
||||
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
|
||||
tree.generator = @"MacPass";
|
||||
tree.databaseName = @"Icon Demonstation";
|
||||
tree.databaseNameChanged = currentTime;
|
||||
tree.databaseDescription = @"This database just has all default icons as groups in the tree";
|
||||
tree.databaseDescriptionChanged = currentTime;
|
||||
tree.defaultUserName = @"";
|
||||
tree.defaultUserNameChanged = currentTime;
|
||||
tree.maintenanceHistoryDays = 365;
|
||||
tree.color = @"";
|
||||
tree.masterKeyChanged = currentTime;
|
||||
tree.masterKeyChangeRec = -1;
|
||||
tree.masterKeyChangeForce = -1;
|
||||
tree.protectTitle = NO;
|
||||
tree.protectUserName = NO;
|
||||
tree.protectPassword = YES;
|
||||
tree.protectUrl = NO;
|
||||
tree.protectNotes = NO;
|
||||
tree.recycleBinEnabled = YES;
|
||||
tree.recycleBinUuid = [UUID nullUuid];
|
||||
tree.recycleBinChanged = currentTime;
|
||||
tree.entryTemplatesGroup = [UUID nullUuid];
|
||||
tree.entryTemplatesGroupChanged = currentTime;
|
||||
tree.historyMaxItems = 10;
|
||||
tree.historyMaxSize = 6 * 1024 * 1024; // 6 MB
|
||||
tree.lastSelectedGroup = [UUID nullUuid];
|
||||
tree.lastTopVisibleGroup = [UUID nullUuid];
|
||||
|
||||
KdbGroup *parentGroup = [tree createGroup:nil];
|
||||
parentGroup.name = @"General";
|
||||
parentGroup.image = 48;
|
||||
tree.root = parentGroup;
|
||||
|
||||
for(NSUInteger iImageIndex = 0; iImageIndex < 69; iImageIndex++) {
|
||||
KdbGroup *group = [tree createGroup:parentGroup];
|
||||
group.name = [NSString stringWithFormat:@"Group %ld", iImageIndex];
|
||||
group.image = iImageIndex;
|
||||
[parentGroup addGroup:group];
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// KdbEntry+MPAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface KdbEntry (MPAdditions)
|
||||
|
||||
@property (nonatomic, readonly) NSImage *icon;
|
||||
|
||||
@end
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// KdbEntry+MPAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbEntry+MPAdditions.h"
|
||||
#import "Kdb3Node.h"
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
#import "MPIconHelper.h"
|
||||
|
||||
@implementation KdbEntry (MPAdditions)
|
||||
|
||||
- (NSImage *)icon {
|
||||
return [MPIconHelper icon:(MPIconType)self.image];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// KdbEntry+MPTreeTools.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 10.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface KdbEntry (MPTreeTools)
|
||||
|
||||
- (NSUInteger)indexInParent;
|
||||
|
||||
@end
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// KdbEntry+MPTreeTools.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 10.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbEntry+MPTreeTools.h"
|
||||
|
||||
@implementation KdbEntry (MPTreeTools)
|
||||
|
||||
- (NSUInteger)indexInParent {
|
||||
if(self.parent) {
|
||||
return [self.parent.entries indexOfObject:self];
|
||||
}
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,29 +0,0 @@
|
||||
//
|
||||
// KdbEntry+Undo.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 12.05.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface KdbEntry (Undo)
|
||||
|
||||
- (NSString *)titleUndoable;
|
||||
- (NSString *)usernameUndoable;
|
||||
- (NSString *)passwordUndoable;
|
||||
- (NSString *)urlUndoable;
|
||||
- (NSString *)notesUndoable;
|
||||
|
||||
- (void)setTitleUndoable:(NSString *)title;
|
||||
- (void)setUsernameUndoable:(NSString *)username;
|
||||
- (void)setPasswordUndoable:(NSString *)password;
|
||||
- (void)setUrlUndoable:(NSString *)url;
|
||||
- (void)setNotesUndoable:(NSString *)notes;
|
||||
|
||||
- (void)deleteUndoable;
|
||||
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
|
||||
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,139 +0,0 @@
|
||||
//
|
||||
// KdbEntry+Undo.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 12.05.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbEntry+Undo.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
#import "KdbGroup+KVOAdditions.h"
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
|
||||
#ifndef MPSetActionName
|
||||
#define MPSetActionName(key, comment) \
|
||||
if(![[self undoManager] isUndoing]) {\
|
||||
[[self undoManager] setActionName:[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]];\
|
||||
}
|
||||
#endif
|
||||
|
||||
@implementation KdbEntry (Undo)
|
||||
|
||||
- (NSUndoManager *)undoManager {
|
||||
return [[[NSDocumentController sharedDocumentController] currentDocument] undoManager];
|
||||
}
|
||||
|
||||
- (NSString *)titleUndoable {
|
||||
return [self title];
|
||||
}
|
||||
|
||||
- (NSString *)usernameUndoable {
|
||||
return [self username];
|
||||
}
|
||||
|
||||
- (NSString *)passwordUndoable {
|
||||
return [self password];
|
||||
}
|
||||
|
||||
- (NSString *)urlUndoable {
|
||||
return [self url];
|
||||
}
|
||||
|
||||
- (NSString *)notesUndoable {
|
||||
return [self notes];
|
||||
}
|
||||
|
||||
- (void)setTitleUndoable:(NSString *)title {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setTitleUndoable:) object:self.title];
|
||||
MPSetActionName(@"SET_TITLE", "");
|
||||
|
||||
[self _touchModifcationDate];
|
||||
[self setTitle:title];
|
||||
}
|
||||
|
||||
- (void)setUsernameUndoable:(NSString *)username {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setUsernameUndoable:) object:self.username];
|
||||
MPSetActionName(@"SET_USERNAME", "");
|
||||
|
||||
[self _touchModifcationDate];
|
||||
[self setUsername:username];
|
||||
}
|
||||
|
||||
- (void)setPasswordUndoable:(NSString *)password {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setPasswordUndoable:) object:self.password];
|
||||
MPSetActionName(@"SET_PASSWORT", "Undo set password");
|
||||
|
||||
[self _touchModifcationDate];
|
||||
[self setPassword:password];
|
||||
}
|
||||
|
||||
- (void)setUrlUndoable:(NSString *)url {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setUrlUndoable:) object:self.url];
|
||||
MPSetActionName(@"SET_URL", "Undo set URL");
|
||||
|
||||
[self _touchModifcationDate];
|
||||
[self setUrl:url];
|
||||
}
|
||||
|
||||
- (void)setNotesUndoable:(NSString *)notes {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setNotesUndoable:) object:self.notes];
|
||||
MPSetActionName(@"SET_NOTES", "Set Notes");
|
||||
|
||||
[self _touchModifcationDate];
|
||||
[self setNotes:notes];
|
||||
}
|
||||
|
||||
- (void)deleteUndoable {
|
||||
if(!self.parent) {
|
||||
return; // No parent to be removed from
|
||||
}
|
||||
NSUInteger oldIndex = [self.parent.entries indexOfObject:self];
|
||||
if(oldIndex == NSNotFound) {
|
||||
return; // We're not in our parents entries list
|
||||
}
|
||||
[[[self undoManager] prepareWithInvocationTarget:self.parent] addEntryUndoable:self atIndex:oldIndex];
|
||||
|
||||
MPSetActionName(@"DELETE_ENTRY", "");
|
||||
|
||||
//[[NSNotificationCenter defaultCenter] postNotificationName:@"" object:self userInfo:nil];
|
||||
[self.parent removeObjectFromEntriesAtIndex:oldIndex];
|
||||
}
|
||||
|
||||
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
|
||||
[self _moveToGroup:group atIndex:index actionName:NSLocalizedString(@"MOVE_ENTRY", "Move Group")];
|
||||
}
|
||||
|
||||
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index {
|
||||
[self _moveToGroup:trash atIndex:index actionName:NSLocalizedString(@"TRASH_ENTRY", "Move Entry to Trash")];
|
||||
}
|
||||
|
||||
- (void)_moveToGroup:(KdbGroup *)group atIndex:(NSUInteger)index actionName:(NSString *)name {
|
||||
if(!group || !self.parent) {
|
||||
return; // Nothing to be moved about
|
||||
}
|
||||
NSUInteger oldIndex = [self.parent.entries indexOfObject:self];
|
||||
if(oldIndex == NSNotFound) {
|
||||
return; // Not found in entries of parent!
|
||||
}
|
||||
[[[self undoManager] prepareWithInvocationTarget:self] _moveToGroup:self.parent atIndex:oldIndex actionName:name];
|
||||
|
||||
MPSetActionName(name, "");
|
||||
|
||||
[self.parent removeObjectFromEntriesAtIndex:oldIndex];
|
||||
// Old indices might be wrong, correct them if necessary
|
||||
index = MIN(index, [group.entries count]);
|
||||
[group insertObject:self inEntriesAtIndex:index];
|
||||
if([self respondsToSelector:@selector(setLocationChanged:)]) {
|
||||
id entry = self;
|
||||
[entry setLocationChanged:[NSDate date]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_touchModifcationDate {
|
||||
self.lastModificationTime = [NSDate date];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// KdbGroup+KVOAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 08.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface KdbGroup (KVOAdditions)
|
||||
|
||||
/* KVO Accesors for the entries */
|
||||
- (KdbEntry *)objectInEntriesAtIndex:(NSUInteger)index;
|
||||
- (NSUInteger)countOfEntries;
|
||||
- (void)insertObject:(KdbEntry *)entry inEntriesAtIndex:(NSUInteger)index;
|
||||
- (void)removeObjectFromEntriesAtIndex:(NSUInteger)index;
|
||||
|
||||
/* KVO Accessors for the groups */
|
||||
- (KdbGroup *)objectInGroupsAtIndex:(NSUInteger)index;
|
||||
- (NSUInteger)countOfGroups;
|
||||
- (void)insertObject:(KdbGroup *)group inGroupsAtIndex:(NSUInteger)index;
|
||||
- (void)removeObjectFromGroupsAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,51 +0,0 @@
|
||||
//
|
||||
// KdbGroup+KVOAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 08.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbGroup+KVOAdditions.h"
|
||||
|
||||
@implementation KdbGroup (KVOAdditions)
|
||||
|
||||
- (void)insertObject:(KdbEntry *)entry inEntriesAtIndex:(NSUInteger)index {
|
||||
entry.parent = self;
|
||||
[_entries insertObject:entry atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromEntriesAtIndex:(NSUInteger)index {
|
||||
KdbEntry *entry = _entries[index];
|
||||
[_entries removeObjectAtIndex:index];
|
||||
entry.parent = nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfEntries {
|
||||
return [self.entries count];
|
||||
}
|
||||
|
||||
- (KdbEntry *)objectInEntriesAtIndex:(NSUInteger)index {
|
||||
return self.entries[index];
|
||||
}
|
||||
|
||||
- (KdbGroup *)objectInGroupsAtIndex:(NSUInteger)index {
|
||||
return self.groups[index];
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfGroups {
|
||||
return [self.groups count];
|
||||
}
|
||||
|
||||
- (void)insertObject:(KdbGroup *)group inGroupsAtIndex:(NSUInteger)index {
|
||||
group.parent = self;
|
||||
[_groups insertObject:group atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromGroupsAtIndex:(NSUInteger)index {
|
||||
KdbGroup *group = (self.groups)[index];
|
||||
[_groups removeObjectAtIndex:index];
|
||||
group.parent = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// KdbGroup+MPAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface KdbGroup (MPAdditions)
|
||||
|
||||
/* Adapter to load images based on icon index */
|
||||
@property (nonatomic, readonly) NSImage *icon;
|
||||
|
||||
/* Walks the tree up to the root element */
|
||||
- (KdbGroup *)root;
|
||||
|
||||
/* Removes all Groups and Entries from this group*/
|
||||
- (void)clear;
|
||||
|
||||
@end
|
||||
@@ -1,40 +0,0 @@
|
||||
//
|
||||
// KdbGroup+MPAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 01.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbGroup+MPAdditions.h"
|
||||
#import "KdbGroup+KVOAdditions.h"
|
||||
#import "MPIconHelper.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@implementation KdbGroup (MPAdditions)
|
||||
|
||||
- (NSImage *)icon {
|
||||
if([self respondsToSelector:@selector(customIconUuid)]) {
|
||||
}
|
||||
return [MPIconHelper icon:(MPIconType)self.image];
|
||||
}
|
||||
|
||||
- (KdbGroup *)root {
|
||||
if(self.parent) {
|
||||
return [self.parent root];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)clear {
|
||||
NSUInteger groupCount = [_groups count];
|
||||
for(NSInteger index = (groupCount - 1); index > -1; index--) {
|
||||
[self removeObjectFromGroupsAtIndex:index];
|
||||
}
|
||||
NSUInteger entryCount = [_entries count];
|
||||
for(NSInteger index = (entryCount - 1); index > -1; index--) {
|
||||
[self removeObjectFromEntriesAtIndex:index];
|
||||
}
|
||||
}
|
||||
@end
|
||||
@@ -1,33 +0,0 @@
|
||||
//
|
||||
// KdbGroup+MPTreeTools.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by michael starke on 19.02.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
@class UUID;
|
||||
|
||||
@interface KdbGroup (MPTreeTools)
|
||||
|
||||
/* Returns all groups under this group and it's subgroups */
|
||||
- (NSArray *)childGroups;
|
||||
/* Returns all entries under this group and it's subgroups */
|
||||
- (NSArray *)childEntries;
|
||||
/* Returns the entry with the UUID */
|
||||
- (KdbEntry *)entryForUUID:(UUID *)uuid;
|
||||
/**
|
||||
* Searches through all subgroups and loactes the Group with the given UUID
|
||||
* @param uuid UUID of the searched group
|
||||
* @return group with matching UUID, otherwise nil
|
||||
*/
|
||||
- (KdbGroup *)groupForUUID:(UUID *)uuid;
|
||||
/**
|
||||
* Determines, if the reciever is an anchestor of the given group
|
||||
* @param group The group to test for anchestry
|
||||
* @return YES, if the receiver is an anchestor of group
|
||||
*/
|
||||
- (BOOL)isAnchestorOfGroup:(KdbGroup *)group;
|
||||
|
||||
@end
|
||||
@@ -1,66 +0,0 @@
|
||||
//
|
||||
// KdbGroup+MPTreeTools.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by michael starke on 19.02.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb3Node.h"
|
||||
|
||||
@implementation KdbGroup (MPTreeTools)
|
||||
|
||||
- (NSArray *)childGroups {
|
||||
NSMutableArray *childGroups = [NSMutableArray arrayWithCapacity:[self.groups count]];
|
||||
[childGroups addObjectsFromArray:self.groups];
|
||||
for(KdbGroup *childGroup in self.groups) {
|
||||
[childGroups addObjectsFromArray:[childGroup childGroups]];
|
||||
}
|
||||
return childGroups;
|
||||
}
|
||||
|
||||
- (NSArray *)childEntries {
|
||||
NSMutableArray *childEntries = [NSMutableArray arrayWithCapacity:[self.groups count] + [self.entries count]];
|
||||
[childEntries addObjectsFromArray:self.entries];
|
||||
for( KdbGroup *childGroup in self.groups) {
|
||||
[childEntries addObjectsFromArray:[childGroup childEntries]];
|
||||
}
|
||||
return childEntries;
|
||||
}
|
||||
|
||||
- (KdbEntry *)entryForUUID:(UUID *)uuid {
|
||||
NSArray *childEntries = [self childEntries];
|
||||
NSArray *filterdEntries = [childEntries filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
|
||||
return [uuid isEqual:(UUID *)[evaluatedObject uuid]];
|
||||
}]];
|
||||
NSAssert([filterdEntries count] <= 1, @"UUID hast to be unique");
|
||||
return [filterdEntries lastObject];
|
||||
}
|
||||
|
||||
- (KdbGroup *)groupForUUID:(UUID *)uuid {
|
||||
NSArray *childGroups = [self childGroups];
|
||||
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
|
||||
return [uuid isEqual:(UUID *)[evaluatedObject uuid]];
|
||||
}];
|
||||
NSArray *filteredGroups = [childGroups filteredArrayUsingPredicate:predicate];
|
||||
NSAssert([filteredGroups count] <= 1, @"UUID hast to be unique");
|
||||
return [filteredGroups lastObject];
|
||||
}
|
||||
|
||||
- (BOOL)isAnchestorOfGroup:(KdbGroup *)group {
|
||||
if(group == nil) {
|
||||
return NO;
|
||||
}
|
||||
KdbGroup *ancestor = group.parent;
|
||||
while(ancestor) {
|
||||
if(ancestor == self) {
|
||||
return YES;
|
||||
}
|
||||
ancestor = ancestor.parent;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// KdbGroup+Undo.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 18.05.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
APPKIT_EXTERN NSString *const MPGroupNameUndoableKey;
|
||||
|
||||
@interface KdbGroup (Undo)
|
||||
|
||||
- (NSUndoManager *)undoManager;
|
||||
|
||||
- (NSString *)nameUndoable;
|
||||
- (void)setNameUndoable:(NSString *)newName;
|
||||
|
||||
- (void)deleteUndoable;
|
||||
- (void)addGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
|
||||
- (void)addEntryUndoable:(KdbEntry *)entry atIndex:(NSUInteger)index;
|
||||
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index;
|
||||
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
@@ -1,114 +0,0 @@
|
||||
//
|
||||
// KdbGroup+Undo.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 18.05.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbGroup+Undo.h"
|
||||
#import "KdbGroup+KVOAdditions.h"
|
||||
#import "KdbEntry+Undo.h"
|
||||
|
||||
NSString *const MPGroupNameUndoableKey = @"nameUndoable";
|
||||
|
||||
@implementation KdbGroup (Undo)
|
||||
|
||||
- (NSUndoManager *)undoManager {
|
||||
return [[[NSDocumentController sharedDocumentController] currentDocument] undoManager];
|
||||
}
|
||||
|
||||
- (NSString *)nameUndoable {
|
||||
return [self name];
|
||||
}
|
||||
|
||||
- (void)setNameUndoable:(NSString *)newName {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setNameUndoable:) object:self.name];
|
||||
|
||||
if(![[self undoManager] isUndoing]) {
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"SET_NAME", "Set Name")];
|
||||
}
|
||||
|
||||
self.name = newName;
|
||||
}
|
||||
|
||||
- (void)deleteUndoable {
|
||||
if(!self.parent) {
|
||||
return;
|
||||
}
|
||||
NSUInteger oldIndex = [self.parent.groups indexOfObject:self];
|
||||
if(oldIndex == NSNotFound) {
|
||||
return; // Inconsistent data
|
||||
}
|
||||
[[[self undoManager] prepareWithInvocationTarget:self.parent] addGroupUndoable:self atIndex:oldIndex];
|
||||
|
||||
if(![[self undoManager] isUndoing]) {
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"DELETE_GROUP", "Delete Group")];
|
||||
}
|
||||
|
||||
[self.parent removeObjectFromGroupsAtIndex:oldIndex];
|
||||
}
|
||||
|
||||
- (void)addGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
|
||||
if(!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
[[[self undoManager] prepareWithInvocationTarget:group] deleteUndoable];
|
||||
|
||||
if(![[self undoManager] isUndoing]) {
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"ADD_GROUP", "Add Group")];
|
||||
}
|
||||
|
||||
index = MIN(index, [group.groups count]);
|
||||
[self insertObject:group inGroupsAtIndex:index];
|
||||
}
|
||||
|
||||
- (void)addEntryUndoable:(KdbEntry *)entry atIndex:(NSUInteger)index {
|
||||
if(!entry) {
|
||||
return;
|
||||
}
|
||||
index = MIN(index, [self.entries count]);
|
||||
[[[self undoManager] prepareWithInvocationTarget:entry] deleteUndoable];
|
||||
|
||||
if(![[self undoManager] isUndoing]) {
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"ADD_ENTRY", "Add Entry")];
|
||||
}
|
||||
|
||||
[self insertObject:entry inEntriesAtIndex:index];
|
||||
}
|
||||
|
||||
- (void)moveToGroupUndoable:(KdbGroup *)group atIndex:(NSUInteger)index {
|
||||
[self _moveToGroup:group atIndex:index actionName:NSLocalizedString(@"MOVE_GROUP", "Move Group" )];
|
||||
}
|
||||
|
||||
- (void)moveToTrashUndoable:(KdbGroup *)trash atIndex:(NSUInteger)index {
|
||||
[self _moveToGroup:trash atIndex:index actionName:NSLocalizedString(@"TRASH_GROUP", "Move Group to Trash")];
|
||||
}
|
||||
|
||||
- (void)_moveToGroup:(KdbGroup *)group atIndex:(NSUInteger)index actionName:(NSString *)actionName {
|
||||
if(!self.parent || !group) {
|
||||
return; // No target or origin
|
||||
}
|
||||
if(self.parent == group) {
|
||||
// Correct the index to accomodate the removal
|
||||
index--;
|
||||
}
|
||||
|
||||
NSUInteger oldIndex = [self.parent.groups indexOfObject:self];
|
||||
if(oldIndex == NSNotFound) {
|
||||
return; // We aren't in our parents groups list.
|
||||
}
|
||||
[[[self undoManager] prepareWithInvocationTarget:self] moveToGroupUndoable:self.parent atIndex:oldIndex];
|
||||
|
||||
if(![[self undoManager] isUndoing]) {
|
||||
[[self undoManager] setActionName:actionName];
|
||||
}
|
||||
|
||||
[self.parent removeObjectFromGroupsAtIndex:oldIndex];
|
||||
index = MIN(index, [group.groups count]);
|
||||
index = MAX(index, 0 );
|
||||
[group insertObject:self inGroupsAtIndex:index];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// KdbTree+MPAdditions.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by michael starke on 20.02.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb.h"
|
||||
|
||||
@class BinaryRef;
|
||||
@class Binary;
|
||||
|
||||
@interface KdbTree (MPAdditions)
|
||||
|
||||
- (NSArray *)allEntries;
|
||||
|
||||
- (NSArray *)allGroups;
|
||||
|
||||
@end
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// KdbTree+MPAdditions.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by michael starke on 20.02.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "KdbTree+MPAdditions.h"
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
|
||||
#import "NSMutableData+Base64.h"
|
||||
#import "Kdb3Node.h"
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@implementation KdbTree (MPAdditions)
|
||||
|
||||
- (NSArray *)allGroups {
|
||||
return [self.root childGroups];
|
||||
}
|
||||
|
||||
- (NSArray *)allEntries {
|
||||
return [self.root childEntries];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -11,7 +11,8 @@
|
||||
#import "MPDocumentWindowController.h"
|
||||
#import "MPActionHelper.h"
|
||||
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKGroup.h"
|
||||
|
||||
#define EDIT_TEMPLATES_ITEM_TAG 10;
|
||||
|
||||
@@ -31,7 +32,7 @@
|
||||
[menu addItemWithTitle:NSLocalizedString(@"EDIT_TEMPLATE_GROUP", "") action:[MPActionHelper actionOfType:MPActionEditTemplateGroup] keyEquivalent:@""];
|
||||
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
for(KdbEntry *entry in [document.templates childEntries]) {
|
||||
for(KPKEntry *entry in [document.templates childEntries]) {
|
||||
NSString *templateMask = NSLocalizedString(@"NEW_ENTRY_WITH_TEMPLATE_%@", "");
|
||||
NSMenuItem *templateItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[NSString stringWithFormat:templateMask, entry.title]
|
||||
action:@selector(createEntryFromTemplate:)
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
#import "MPAttachmentTableDataSource.h"
|
||||
#import "MPDocument.h"
|
||||
|
||||
#import "Kdb3Entry+KVOAdditions.h"
|
||||
#import "Kdb4Entry+KVOAdditions.h"
|
||||
|
||||
@implementation MPAttachmentTableDataSource
|
||||
|
||||
- (NSDragOperation)tableView:(NSTableView *)tableView
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#import "MPDocument.h"
|
||||
#import "MPSelectedAttachmentTableCellView.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb3Node.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKBinary.h"
|
||||
|
||||
#import "HNHTableRowView.h"
|
||||
|
||||
@@ -22,16 +22,8 @@
|
||||
NSTableView *tableView = [notification object];
|
||||
MPDocument *document = [[[tableView window] windowController] document];
|
||||
NSIndexSet *allColumns = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[tableView tableColumns] count])];
|
||||
if([document.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
Kdb4Entry *entryv4 = (Kdb4Entry *)document.selectedEntry;
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [entryv4.binaries count] )];
|
||||
[tableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
|
||||
}
|
||||
if([document.selectedEntry isKindOfClass:[Kdb3Entry class]]) {
|
||||
Kdb3Entry *entryv3 = (Kdb3Entry *)document.selectedEntry;
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, (entryv3.binary ? 1 : 0 ))];
|
||||
[tableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
|
||||
}
|
||||
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [document.selectedEntry.binaries count] )];
|
||||
[tableView reloadDataForRowIndexes:indexSet columnIndexes:allColumns];
|
||||
}
|
||||
|
||||
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
|
||||
@@ -54,17 +46,11 @@
|
||||
view = [tableView makeViewWithIdentifier:@"NormalCell" owner:tableView];
|
||||
}
|
||||
/* Bind view */
|
||||
if([document.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
Kdb4Entry *entry = (Kdb4Entry *)document.selectedEntry;
|
||||
BinaryRef *binaryRef = entry.binaries[row];
|
||||
[[view textField] bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
|
||||
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[binaryRef.key pathExtension]]];
|
||||
}
|
||||
else {
|
||||
Kdb3Entry *entry= (Kdb3Entry *)document.selectedEntry;
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"binaryDesc" options:nil];
|
||||
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[entry.binaryDesc pathExtension]]];
|
||||
}
|
||||
KPKEntry *entry = document.selectedEntry;
|
||||
NSAssert([entry.binaries count] > row, @"Indes needs to be valid for binaries");
|
||||
KPKBinary *binary = entry.binaries[row];
|
||||
[[view textField] bind:NSValueBinding toObject:binary withKeyPath:@"name" options:nil];
|
||||
[[view imageView] setImage:[[NSWorkspace sharedWorkspace] iconForFileType:[binary.name pathExtension]]];
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
FOUNDATION_EXPORT NSString *const MPPasteBoardType;
|
||||
FOUNDATION_EXPORT NSString *const MPEntryUTI;
|
||||
FOUNDATION_EXPORT NSString *const MPGroupUTI;
|
||||
FOUNDATION_EXTERN NSString *const MPUUIDUTI;
|
||||
FOUNDATION_EXPORT NSString *const MPErrorDomain;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,3 @@
|
||||
|
||||
NSString *const MPPasteBoardType = @"com.hicknhack.macpass.pasteboard";
|
||||
NSString *const MPErrorDomain = @"com.hicknhack.macpass.error";
|
||||
NSString *const MPEntryUTI = @"com.hicknhack.macpass.entry";
|
||||
NSString *const MPGroupUTI = @"com.hicknhack.macpass.group";
|
||||
NSString *const MPUUIDUTI = @"com.hicknhack.macpass.UUID";
|
||||
@@ -10,28 +10,31 @@
|
||||
#import "MPDocument.h"
|
||||
#import "MPCustomFieldTableCellView.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
#import "StringField+Undo.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKAttribute.h"
|
||||
|
||||
@implementation MPCustomFieldTableViewDelegate
|
||||
|
||||
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
|
||||
MPDocument *document = [[[tableView window] windowController] document];
|
||||
if(![document.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
return nil;
|
||||
}
|
||||
Kdb4Entry *entry = (Kdb4Entry *)document.selectedEntry;
|
||||
|
||||
KPKEntry *entry = document.selectedEntry;
|
||||
MPCustomFieldTableCellView *view = [tableView makeViewWithIdentifier:@"SelectedCell" owner:tableView];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_customFieldFrameChanged:) name:NSViewFrameDidChangeNotification object:view];
|
||||
if([document.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
StringField *stringField = entry.stringFields[row];
|
||||
NSDictionary *validateOptions = @{ NSValidatesImmediatelyBindingOption: @YES };
|
||||
[view.labelTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldKeyUndoableKey options:validateOptions];
|
||||
[view.valueTextField bind:NSValueBinding toObject:stringField withKeyPath:MPStringFieldValueUndoableKey options:nil];
|
||||
[view.removeButton setTarget:self.viewController];
|
||||
[view.removeButton setAction:@selector(removeCustomField:)];
|
||||
[view.removeButton setTag:row];
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_customFieldFrameChanged:)
|
||||
name:NSViewFrameDidChangeNotification
|
||||
object:view];
|
||||
|
||||
NSAssert([entry.customAttributes count] > row, @"Count of custom attributes must match row");
|
||||
KPKAttribute *attribute = entry.customAttributes[row];
|
||||
NSDictionary *validateOptions = @{ NSValidatesImmediatelyBindingOption: @YES };
|
||||
[view.labelTextField bind:NSValueBinding toObject:attribute withKeyPath:@"key" options:validateOptions];
|
||||
[view.valueTextField bind:NSValueBinding toObject:attribute withKeyPath:@"value" options:nil];
|
||||
[view.removeButton setTarget:self.viewController];
|
||||
[view.removeButton setAction:@selector(removeCustomField:)];
|
||||
[view.removeButton setTag:row];
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,14 +13,16 @@
|
||||
#import "MPIconHelper.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKTree.h"
|
||||
#import "KPKMetaData.h"
|
||||
#import "KPKNode+IconImage.h"
|
||||
|
||||
#import "HNHRoundedTextField.h"
|
||||
#import "HNHRoundedSecureTextField.h"
|
||||
|
||||
#import "NSString+Empty.h"
|
||||
|
||||
#import "Kdb.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "KdbGroup+MPAdditions.h"
|
||||
|
||||
@interface MPDatabaseSettingsWindowController () {
|
||||
MPDocument *_document;
|
||||
@@ -56,19 +58,20 @@
|
||||
|
||||
- (IBAction)save:(id)sender {
|
||||
/* General */
|
||||
_document.treeV4.databaseDescription = [self.databaseDescriptionTextView string];
|
||||
_document.treeV4.databaseName = [self.databaseNameTextField stringValue];
|
||||
KPKMetaData *metaData = _document.tree.metaData;
|
||||
metaData.databaseDescription = [self.databaseDescriptionTextView string];
|
||||
metaData.databaseName = [self.databaseNameTextField stringValue];
|
||||
|
||||
/* Display */
|
||||
|
||||
/* Advanced */
|
||||
_document.treeV4.recycleBinEnabled = self.trashEnabled;
|
||||
metaData.recycleBinEnabled = self.trashEnabled;
|
||||
NSMenuItem *trashMenuItem = [self.selectRecycleBinGroupPopUpButton selectedItem];
|
||||
KdbGroup *trashGroup = [trashMenuItem representedObject];
|
||||
KPKGroup *trashGroup = [trashMenuItem representedObject];
|
||||
[_document useGroupAsTrash:trashGroup];
|
||||
|
||||
NSMenuItem *templateMenuItem = [self.templateGroupPopUpButton selectedItem];
|
||||
KdbGroup *templateGroup = [templateMenuItem representedObject];
|
||||
KPKGroup *templateGroup = [templateMenuItem representedObject];
|
||||
[_document useGroupAsTemplate:templateGroup];
|
||||
|
||||
BOOL protectNotes = [self.protectNotesCheckButton state] == NSOnState;
|
||||
@@ -77,24 +80,22 @@
|
||||
BOOL protectURL = [self.protectURLCheckButton state] == NSOnState;
|
||||
BOOL protectUsername = [self.protectUserNameCheckButton state] == NSOnState;
|
||||
|
||||
if(_document.version == MPDatabaseVersion4) {
|
||||
_document.treeV4.protectNotes = protectNotes;
|
||||
_document.treeV4.protectPassword = protectPassword;
|
||||
_document.treeV4.protectTitle = protectTitle;
|
||||
_document.treeV4.protectUrl = protectURL;
|
||||
_document.treeV4.protectUserName = protectUsername;
|
||||
_document.treeV4.defaultUserName = [self.defaultUsernameTextField stringValue];
|
||||
metaData.protectNotes = protectNotes;
|
||||
metaData.protectPassword = protectPassword;
|
||||
metaData.protectTitle = protectTitle;
|
||||
metaData.protectUrl = protectURL;
|
||||
metaData.protectUserName = protectUsername;
|
||||
metaData.defaultUserName = [self.defaultUsernameTextField stringValue];
|
||||
|
||||
}
|
||||
else {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
/*
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setBool:protectNotes forKey:kMPSettingsKeyLegacyHideNotes];
|
||||
[defaults setBool:protectPassword forKey:kMPSettingsKeyLegacyHidePassword];
|
||||
[defaults setBool:protectTitle forKey:kMPSettingsKeyLegacyHideTitle];
|
||||
[defaults setBool:protectURL forKey:kMPSettingsKeyLegacyHideURL];
|
||||
[defaults setBool:protectUsername forKey:kMPSettingsKeyLegacyHideUsername];
|
||||
[defaults synchronize];
|
||||
}
|
||||
*/
|
||||
[self close:nil];
|
||||
}
|
||||
|
||||
@@ -108,11 +109,11 @@
|
||||
return;
|
||||
}
|
||||
/* Update all stuff that might have changed */
|
||||
Kdb4Tree *tree = _document.treeV4;
|
||||
[self _setupDatabase:tree];
|
||||
[self _setupProtectionTab:tree];
|
||||
[self _setupAdvancedTab:tree];
|
||||
[self _setupTemplatesTab:tree];
|
||||
KPKMetaData *metaData = _document.tree.metaData;
|
||||
[self _setupDatabase:metaData];
|
||||
[self _setupProtectionTab:metaData];
|
||||
[self _setupAdvancedTab:_document.tree];
|
||||
[self _setupTemplatesTab:_document.tree];
|
||||
self.isDirty = NO;
|
||||
}
|
||||
|
||||
@@ -142,7 +143,8 @@
|
||||
case MPDatabaseSettingsTabAdvanced:
|
||||
case MPDatabaseSettingsTabGeneral:
|
||||
case MPDatabaseSettingsTabTemplates:
|
||||
return (_document.version == MPDatabaseVersion4);
|
||||
return YES;
|
||||
//return (_document.version == MPDatabaseVersion4);
|
||||
|
||||
default:
|
||||
return NO;
|
||||
@@ -150,61 +152,29 @@
|
||||
}
|
||||
|
||||
#pragma mark Private Helper
|
||||
- (void)_setupDatabase:(Kdb4Tree *)tree {
|
||||
BOOL isKdbx = (nil != tree);
|
||||
[self.databaseDescriptionTextView setEditable:isKdbx];
|
||||
[self.databaseNameTextField setEnabled:isKdbx];
|
||||
if(isKdbx) {
|
||||
[self.databaseNameTextField setStringValue:tree.databaseName];
|
||||
[self.databaseDescriptionTextView setString:tree.databaseDescription];
|
||||
}
|
||||
else {
|
||||
[self.databaseNameTextField setStringValue:_missingFeature];
|
||||
[self.databaseDescriptionTextView setString:_missingFeature];
|
||||
}
|
||||
- (void)_setupDatabase:(KPKMetaData *)metaData {
|
||||
[self.databaseNameTextField setStringValue:metaData.databaseName];
|
||||
[self.databaseDescriptionTextView setString:metaData.databaseDescription];
|
||||
}
|
||||
|
||||
- (void)_setupProtectionTab:(Kdb4Tree *)tree {
|
||||
BOOL isKdbX = (nil != tree);
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
BOOL protectNotes = isKdbX ? tree.protectNotes : [defaults boolForKey:kMPSettingsKeyLegacyHideNotes];
|
||||
BOOL protectPassword = isKdbX ? tree.protectPassword : [defaults boolForKey:kMPSettingsKeyLegacyHidePassword];
|
||||
BOOL protectTitle = isKdbX ? tree.protectTitle : [defaults boolForKey:kMPSettingsKeyLegacyHideTitle];
|
||||
BOOL protectUrl = isKdbX ? tree.protectUrl : [defaults boolForKey:kMPSettingsKeyLegacyHideURL];
|
||||
BOOL protectUsername = isKdbX ? tree.protectUserName : [defaults boolForKey:kMPSettingsKeyLegacyHideUsername];
|
||||
|
||||
[self.protectNotesCheckButton setState:protectNotes ? NSOnState : NSOffState ];
|
||||
[self.protectPasswortCheckButton setState:protectPassword ? NSOnState : NSOffState];
|
||||
[self.protectTitleCheckButton setState:protectTitle ? NSOnState : NSOffState];
|
||||
[self.protectURLCheckButton setState:protectUrl ? NSOnState : NSOffState];
|
||||
[self.protectUserNameCheckButton setState:protectUsername ? NSOnState : NSOffState];
|
||||
- (void)_setupProtectionTab:(KPKMetaData *)metaData {
|
||||
[self.protectNotesCheckButton setState:metaData.protectNotes ? NSOnState : NSOffState ];
|
||||
[self.protectPasswortCheckButton setState:metaData.protectPassword ? NSOnState : NSOffState];
|
||||
[self.protectTitleCheckButton setState:metaData.protectTitle ? NSOnState : NSOffState];
|
||||
[self.protectURLCheckButton setState:metaData.protectUrl ? NSOnState : NSOffState];
|
||||
[self.protectUserNameCheckButton setState:metaData.protectUserName ? NSOnState : NSOffState];
|
||||
}
|
||||
|
||||
- (void)_setupAdvancedTab:(Kdb4Tree *)tree {
|
||||
BOOL isKdbX = (nil != tree);
|
||||
|
||||
self.trashEnabled = isKdbX ? tree.recycleBinEnabled : NO;
|
||||
|
||||
- (void)_setupAdvancedTab:(KPKTree *)tree {
|
||||
[self.enableRecycleBinCheckButton bind:NSValueBinding toObject:self withKeyPath:@"trashEnabled" options:nil];
|
||||
[self.enableRecycleBinCheckButton setEnabled:isKdbX];
|
||||
[self.selectRecycleBinGroupPopUpButton bind:NSEnabledBinding toObject:self withKeyPath:@"trashEnabled" options:nil];
|
||||
if(isKdbX) {
|
||||
[self _updateTrashFolders:tree];
|
||||
}
|
||||
[self _updateTrashFolders:tree];
|
||||
}
|
||||
|
||||
- (void)_setupTemplatesTab:(Kdb4Tree *)tree {
|
||||
if(tree) {
|
||||
[self.defaultUsernameTextField setStringValue:tree.defaultUserName];
|
||||
[self.defaultUsernameTextField setEditable:YES];
|
||||
[self _updateTemplateGroup:tree];
|
||||
}
|
||||
else {
|
||||
[self.defaultUsernameTextField setStringValue:_missingFeature];
|
||||
[self.defaultUsernameTextField setEditable:NO];
|
||||
}
|
||||
- (void)_setupTemplatesTab:(KPKTree *)tree {
|
||||
[self.defaultUsernameTextField setStringValue:tree.metaData.defaultUserName];
|
||||
[self.defaultUsernameTextField setEditable:YES];
|
||||
[self _updateTemplateGroup:tree];
|
||||
}
|
||||
|
||||
- (void)_updateFirstResponder {
|
||||
@@ -229,18 +199,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_updateTrashFolders:(Kdb4Tree *)tree {
|
||||
- (void)_updateTrashFolders:(KPKTree *)tree {
|
||||
NSMenu *menu = [self _buildTrashTreeMenu:tree];
|
||||
[self.selectRecycleBinGroupPopUpButton setMenu:menu];
|
||||
}
|
||||
|
||||
- (void)_updateTemplateGroup:(Kdb4Tree *)tree {
|
||||
- (void)_updateTemplateGroup:(KPKTree *)tree {
|
||||
NSMenu *menu = [self _buildTemplateTreeMenu:tree];
|
||||
[self.templateGroupPopUpButton setMenu:menu];
|
||||
}
|
||||
|
||||
- (NSMenu *)_buildTrashTreeMenu:(Kdb4Tree *)tree {
|
||||
NSMenu *menu = [self _buildTreeMenu:tree preselect:tree.recycleBinUuid];
|
||||
- (NSMenu *)_buildTrashTreeMenu:(KPKTree *)tree {
|
||||
NSMenu *menu = [self _buildTreeMenu:tree preselect:tree.metaData.recycleBinUuid];
|
||||
|
||||
NSMenuItem *selectItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"AUTOCREATE_TRASH_FOLDER", @"Menu item for automatic trash creation")
|
||||
action:NULL
|
||||
@@ -251,8 +221,8 @@
|
||||
return menu;
|
||||
}
|
||||
|
||||
- (NSMenu *)_buildTemplateTreeMenu:(Kdb4Tree *)tree {
|
||||
NSMenu *menu = [self _buildTreeMenu:tree preselect:tree.entryTemplatesGroup];
|
||||
- (NSMenu *)_buildTemplateTreeMenu:(KPKTree *)tree {
|
||||
NSMenu *menu = [self _buildTreeMenu:tree preselect:tree.metaData.entryTemplatesGroup];
|
||||
|
||||
NSMenuItem *selectItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"NO_TEMPLATE_GROUP", @"Menu item to reset the template groups")
|
||||
action:NULL
|
||||
@@ -264,18 +234,16 @@
|
||||
}
|
||||
|
||||
|
||||
- (NSMenu *)_buildTreeMenu:(Kdb4Tree *)tree preselect:(UUID *)uuid {
|
||||
- (NSMenu *)_buildTreeMenu:(KPKTree *)tree preselect:(NSUUID *)uuid {
|
||||
NSMenu *menu = [[NSMenu alloc] init];
|
||||
[menu setAutoenablesItems:NO];
|
||||
|
||||
|
||||
/*
|
||||
Trash and Templates can be nested, so wee need to adhere to this :(
|
||||
*/
|
||||
|
||||
for(Kdb4Group *group in tree.root.groups) {
|
||||
for(KPKGroup *group in tree.root.groups) {
|
||||
NSMenuItem *groupItem = [[NSMenuItem alloc] init];
|
||||
[groupItem setImage:group.icon];
|
||||
[groupItem setImage:group.iconImage];
|
||||
[groupItem setTitle:group.name];
|
||||
[groupItem setRepresentedObject:group];
|
||||
[groupItem setEnabled:YES];
|
||||
|
||||
@@ -8,169 +8,21 @@
|
||||
|
||||
#import "MPDocument.h"
|
||||
|
||||
#import "NSMutableData+Base64.h"
|
||||
#import "NSData+Gzip.h"
|
||||
|
||||
#import "Kdb3Node.h"
|
||||
#import "Kdb3Entry+KVOAdditions.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb4Entry+KVOAdditions.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKBinary.h"
|
||||
|
||||
@implementation MPDocument (Attachments)
|
||||
|
||||
- (void)addAttachment:(NSURL *)location toEntry:(KdbEntry *)anEntry {
|
||||
- (void)addAttachment:(NSURL *)location toEntry:(KPKEntry *)anEntry {
|
||||
NSError *error = nil;
|
||||
NSDictionary *resourceKeys = [location resourceValuesForKeys:@[NSURLIsDirectoryKey] error:&error];
|
||||
if([resourceKeys[ NSURLIsDirectoryKey ] boolValue] == YES ) {
|
||||
return; // We do not add whol directories
|
||||
return; // We do not add whole directories
|
||||
}
|
||||
NSString *fileName = [location lastPathComponent];
|
||||
if([anEntry isKindOfClass:[Kdb3Entry class]]) {
|
||||
Kdb3Entry *entry = (Kdb3Entry *)anEntry;
|
||||
NSData *binaryData = [NSData dataWithContentsOfURL:location options:NSDataReadingUncached error:&error];
|
||||
if(!binaryData) {
|
||||
[NSApp presentError:error];
|
||||
binaryData = nil;
|
||||
error = nil;
|
||||
return; // failed
|
||||
}
|
||||
entry.binary = binaryData;
|
||||
entry.binaryDesc = fileName;
|
||||
[entry insertObject:@"" inBinariesAtIndex:1];
|
||||
KPKBinary *binary = [[KPKBinary alloc] initWithContentsOfURL:location];
|
||||
if(binary) {
|
||||
[anEntry addBinary:binary];
|
||||
}
|
||||
if( [anEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
Kdb4Entry *entry = (Kdb4Entry *)anEntry;
|
||||
NSData *fileData = [NSData dataWithContentsOfURL:location options:NSDataReadingMappedIfSafe error:&error];
|
||||
if(!fileData) {
|
||||
[NSApp presentError:error];
|
||||
fileData = nil;
|
||||
error = nil;
|
||||
return; // failed
|
||||
}
|
||||
Binary *binary = [[Binary alloc] init];
|
||||
NSUInteger nextId = [self nextBinaryId];
|
||||
if(nextId == NSNotFound) {
|
||||
binary = nil;
|
||||
return; // No id found. Something went wrong
|
||||
}
|
||||
binary.binaryId = nextId;
|
||||
binary.compressed = (self.treeV4.compressionAlgorithm != KPLCompressionNone);
|
||||
NSData *encodedData;
|
||||
if(binary.compressed) {
|
||||
switch(self.treeV4.compressionAlgorithm) {
|
||||
case KPLCompressionGzip: {
|
||||
NSData *compressedData = [fileData gzipDeflate];
|
||||
encodedData = [NSMutableData mutableDataWithBase64EncodedData:compressedData];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NSAssert(NO, @"Unsupported Compression Algorithm");
|
||||
binary = nil;
|
||||
encodedData = nil;
|
||||
fileData = nil;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
encodedData = fileData;
|
||||
}
|
||||
binary.data = [[NSString alloc] initWithData:encodedData encoding:NSUTF8StringEncoding];
|
||||
|
||||
[self.treeV4.binaries addObject:binary];
|
||||
BinaryRef *ref = [[BinaryRef alloc] init];
|
||||
ref.key = fileName;
|
||||
ref.ref = binary.binaryId;
|
||||
[entry insertObject:ref inBinariesAtIndex:[entry.binaries count]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeAttachment:(BinaryRef *)reference fromEntry:(KdbEntry *)anEntry {
|
||||
if(self.version != MPDatabaseVersion4) {
|
||||
return; // Wrong Database version;
|
||||
}
|
||||
Binary *binary = [self findBinary:reference];
|
||||
Kdb4Entry *entry = (Kdb4Entry *)anEntry;
|
||||
NSUInteger index = [entry.binaries indexOfObject:reference];
|
||||
if(index == NSNotFound) {
|
||||
return; // No Reference for this entry found
|
||||
}
|
||||
[entry removeObjectFromBinariesAtIndex:index];
|
||||
[self.treeV4.binaries removeObject:binary];
|
||||
}
|
||||
|
||||
- (void)removeAttachmentFromEntry:(KdbEntry *)anEntry {
|
||||
if(self.version != MPDatabaseVersion3) {
|
||||
return;
|
||||
}
|
||||
Kdb3Entry *entry = (Kdb3Entry *)anEntry;
|
||||
[entry removeObjectFromBinariesAtIndex:0];
|
||||
}
|
||||
|
||||
- (Binary *)findBinary:(BinaryRef *)reference {
|
||||
if(self.version != MPDatabaseVersion4) {
|
||||
return nil;
|
||||
}
|
||||
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
|
||||
Binary *binaryFile = evaluatedObject;
|
||||
return (binaryFile.binaryId == reference.ref);
|
||||
}];
|
||||
NSArray *filteredBinary = [self.treeV4.binaries filteredArrayUsingPredicate:filterPredicate];
|
||||
return [filteredBinary lastObject];
|
||||
}
|
||||
|
||||
- (void)saveAttachmentForItem:(id)item toLocation:(NSURL *)location {
|
||||
NSData *fileData = [self attachmentDataForItem:item];
|
||||
if(!fileData) {
|
||||
return; // No data to save;
|
||||
}
|
||||
NSError *error = nil;
|
||||
if( ![fileData writeToURL:location options:NSDataWritingAtomic error:&error] ) {
|
||||
[NSApp presentError:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)attachmentDataForItem:(id)item {
|
||||
if([item isKindOfClass:[Kdb3Entry class]]) {
|
||||
Kdb3Entry *entry = (Kdb3Entry *)item;
|
||||
return entry.binary;
|
||||
}
|
||||
else if([item isKindOfClass:[BinaryRef class]]) {
|
||||
Binary *binary = [self findBinary:item];
|
||||
NSData *rawData = nil;
|
||||
if(binary) {
|
||||
if(binary.compressed) {
|
||||
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
rawData = [rawData gzipInflate];
|
||||
}
|
||||
else {
|
||||
rawData = [NSMutableData mutableDataWithBase64DecodedData:[binary.data dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
return rawData;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)attachmenFileNameForItem:(id)item {
|
||||
if([item isKindOfClass:[Kdb3Entry class]]) {
|
||||
Kdb3Entry *entry = (Kdb3Entry *)item;
|
||||
return entry.binaryDesc;
|
||||
}
|
||||
else if([item isKindOfClass:[BinaryRef class]]) {
|
||||
return ((BinaryRef *)item).key;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)nextBinaryId {
|
||||
if(self.version != MPDatabaseVersion4) {
|
||||
return NSNotFound;
|
||||
}
|
||||
NSUInteger maxKey = 0;
|
||||
for(Binary *binary in self.treeV4.binaries) {
|
||||
maxKey = MAX(binary.binaryId, maxKey);
|
||||
}
|
||||
return (maxKey + 1);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,17 +22,11 @@ APPKIT_EXTERN NSString *const MPDocumentDidChangeCurrentGroupNotication;
|
||||
APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
|
||||
*/
|
||||
|
||||
@class KdbGroup;
|
||||
@class KdbEntry;
|
||||
@class KdbTree;
|
||||
@class Kdb4Tree;
|
||||
@class Kdb3Tree;
|
||||
@class Kdb4Entry;
|
||||
@class UUID;
|
||||
@class Binary;
|
||||
@class BinaryRef;
|
||||
@class StringField;
|
||||
@class MPRootAdapter;
|
||||
@class KPKGroup;
|
||||
@class KPKEntry;
|
||||
@class KPKTree;
|
||||
@class KPKBinary;
|
||||
@class KPKAttribute;
|
||||
|
||||
@interface MPDocument : NSDocument
|
||||
|
||||
@@ -42,24 +36,22 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
|
||||
@property (assign, nonatomic) BOOL locked;
|
||||
@property (assign, readonly) BOOL decrypted;
|
||||
|
||||
@property (strong, readonly, nonatomic) KdbTree *tree;
|
||||
@property (weak, readonly, nonatomic) KdbGroup *root;
|
||||
@property (readonly, strong) MPRootAdapter *rootAdapter;
|
||||
@property (weak, readonly) KdbGroup *trash;
|
||||
@property (weak, readonly) KdbGroup *templates;
|
||||
@property (strong, readonly, nonatomic) KPKTree *tree;
|
||||
@property (weak, readonly, nonatomic) KPKGroup *root;
|
||||
@property (weak, readonly) KPKGroup *trash;
|
||||
@property (weak, readonly) KPKGroup *templates;
|
||||
|
||||
@property (nonatomic, copy) NSString *password;
|
||||
@property (nonatomic, strong) NSURL *key;
|
||||
|
||||
@property (assign, readonly) MPDatabaseVersion version;
|
||||
@property (assign, readonly, getter = isReadOnly) BOOL readOnly;
|
||||
|
||||
|
||||
/*
|
||||
State (active group/entry)
|
||||
*/
|
||||
@property (nonatomic, weak) KdbEntry *selectedEntry;
|
||||
@property (nonatomic, weak) KdbGroup *selectedGroup;
|
||||
@property (nonatomic, weak) KPKEntry *selectedEntry;
|
||||
@property (nonatomic, weak) KPKGroup *selectedGroup;
|
||||
@property (nonatomic, weak) id selectedItem;
|
||||
|
||||
|
||||
@@ -73,14 +65,11 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
|
||||
/*
|
||||
Returns the entry for the given UUID, nil if none was found
|
||||
*/
|
||||
- (KdbEntry *)findEntry:(UUID *)uuid;
|
||||
- (KdbGroup *)findGroup:(UUID *)uuid;
|
||||
- (KPKEntry *)findEntry:(NSUUID *)uuid;
|
||||
- (KPKGroup *)findGroup:(NSUUID *)uuid;
|
||||
|
||||
- (Kdb4Tree *)treeV4;
|
||||
- (Kdb3Tree *)treeV3;
|
||||
|
||||
- (void)useGroupAsTrash:(KdbGroup *)group;
|
||||
- (void)useGroupAsTemplate:(KdbGroup *)group;
|
||||
- (void)useGroupAsTrash:(KPKGroup *)group;
|
||||
- (void)useGroupAsTemplate:(KPKGroup *)group;
|
||||
|
||||
- (BOOL)isItemTrashed:(id)item;
|
||||
|
||||
@@ -89,16 +78,12 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
|
||||
|
||||
#pragma mark Undo Data Manipulation
|
||||
/* Undoable Intiialization of elements */
|
||||
- (KdbGroup *)createGroup:(KdbGroup *)parent;
|
||||
- (KdbEntry *)createEntry:(KdbGroup *)parent;
|
||||
- (StringField *)createStringField:(KdbEntry *)entry;
|
||||
- (KPKGroup *)createGroup:(KPKGroup *)parent;
|
||||
- (KPKEntry *)createEntry:(KPKGroup *)parent;
|
||||
- (KPKAttribute *)createCustomAttribute:(KPKEntry *)entry;
|
||||
|
||||
/* TODO in UNDO auslagen */
|
||||
- (void)addStringField:(StringField *)field toEntry:(Kdb4Entry *)entry atIndex:(NSUInteger)index;
|
||||
- (void)removeStringField:(StringField *)field formEntry:(Kdb4Entry *)entry;
|
||||
|
||||
- (void)deleteGroup:(KdbGroup *)group;
|
||||
- (void)deleteEntry:(KdbEntry *)entry;
|
||||
- (void)deleteGroup:(KPKGroup *)group;
|
||||
- (void)deleteEntry:(KPKEntry *)entry;
|
||||
|
||||
- (IBAction)emptyTrash:(id)sender;
|
||||
- (IBAction)createEntryFromTemplate:(id)sender;
|
||||
@@ -106,16 +91,6 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
|
||||
|
||||
@interface MPDocument (Attachments)
|
||||
|
||||
- (void)addAttachment:(NSURL *)location toEntry:(KdbEntry *)anEntry;
|
||||
/**
|
||||
item can be either a BinaryRef or an Kdb3Entry.
|
||||
*/
|
||||
- (void)saveAttachmentForItem:(id)item toLocation:(NSURL *)location;
|
||||
- (NSData *)attachmentDataForItem:(id)item;
|
||||
- (NSString *)attachmenFileNameForItem:(id)item;
|
||||
- (void)removeAttachment:(BinaryRef *)reference fromEntry:(KdbEntry *)anEntry;
|
||||
- (void)removeAttachmentFromEntry:(KdbEntry *)anEntry;
|
||||
- (NSUInteger)nextBinaryId;
|
||||
- (Binary *)findBinary:(BinaryRef *)reference;
|
||||
- (void)addAttachment:(NSURL *)location toEntry:(KPKEntry *)anEntry;
|
||||
|
||||
@end
|
||||
@@ -9,36 +9,21 @@
|
||||
#import "MPDocument.h"
|
||||
#import "MPDocumentWindowController.h"
|
||||
#import "MPDatabaseVersion.h"
|
||||
#import "MPRootAdapter.h"
|
||||
#import "MPIconHelper.h"
|
||||
#import "MPActionHelper.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
#import "MPNotifications.h"
|
||||
#import "MPSavePanelAccessoryViewController.h"
|
||||
|
||||
#import "KdbLib.h"
|
||||
#import "Kdb3Node.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb4Persist.h"
|
||||
#import "KdbPassword.h"
|
||||
|
||||
#import "KdbGroup+KVOAdditions.h"
|
||||
#import "Kdb4Entry+KVOAdditions.h"
|
||||
|
||||
#import "KdbEntry+Undo.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
|
||||
#import "Kdb3Tree+NewTree.h"
|
||||
#import "Kdb4Tree+NewTree.h"
|
||||
#import "Kdb4Entry+MPAdditions.h"
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
#import "KdbGroup+MPAdditions.h"
|
||||
|
||||
#import "DataOutputStream.h"
|
||||
#import "DDXMLNode.h"
|
||||
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKTree.h"
|
||||
#import "KPKTree+Serializing.h"
|
||||
#import "KPKPassword.h"
|
||||
#import "KPKMetaData.h"
|
||||
#import "KPKAttribute.h"
|
||||
|
||||
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
|
||||
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
|
||||
@@ -54,15 +39,13 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
@interface MPDocument () {
|
||||
@private
|
||||
BOOL _didLockFile;
|
||||
NSData *_fileData;
|
||||
NSData *_encryptedData;
|
||||
}
|
||||
|
||||
@property (strong, nonatomic) MPSavePanelAccessoryViewController *savePanelViewController;
|
||||
|
||||
@property (strong, nonatomic) KdbTree *tree;
|
||||
@property (weak, nonatomic) KdbGroup *root;
|
||||
@property (weak, nonatomic, readonly) KdbPassword *passwordHash;
|
||||
@property (assign) MPDatabaseVersion version;
|
||||
@property (strong, nonatomic) KPKTree *tree;
|
||||
@property (weak, nonatomic) KPKGroup *root;
|
||||
|
||||
@property (assign, nonatomic) BOOL hasPasswordOrKey;
|
||||
@property (assign) BOOL decrypted;
|
||||
@@ -90,27 +73,13 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
- (id)initWithVersion:(MPDatabaseVersion)version {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
_fileData = nil;
|
||||
_encryptedData = nil;
|
||||
_didLockFile = NO;
|
||||
_decrypted = YES;
|
||||
_hasPasswordOrKey = NO;
|
||||
_locked = NO;
|
||||
_readOnly = NO;
|
||||
_rootAdapter = [[MPRootAdapter alloc] init];
|
||||
_version = version;
|
||||
[[self undoManager] setLevelsOfUndo:10];
|
||||
switch(_version) {
|
||||
case MPDatabaseVersion3:
|
||||
self.tree = [Kdb3Tree templateTree];
|
||||
break;
|
||||
case MPDatabaseVersion4:
|
||||
self.tree = [Kdb4Tree templateTree];
|
||||
//self.tree = [Kdb4Tree demoTree];
|
||||
break;
|
||||
default:
|
||||
self = nil;
|
||||
return nil;
|
||||
}
|
||||
self.tree = [KPKTree templateTree];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -133,10 +102,10 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
/*
|
||||
Move this to data:ofType: method with KeePassKit
|
||||
*/
|
||||
NSError *error = nil;
|
||||
[KdbWriterFactory persist:self.tree fileURL:url withPassword:self.passwordHash error:&error];
|
||||
if(error) {
|
||||
NSLog(@"%@", [error localizedDescription]);
|
||||
KPKPassword *password = nil;
|
||||
NSData *treeData = [self.tree encryptWithPassword:password forVersion:KPKXmlVersion error:outError];
|
||||
if([treeData writeToURL:url options:NSDataWritingAtomic error:outError]) {
|
||||
NSLog(@"%@", [*outError localizedDescription]);
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
@@ -158,7 +127,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
Delete our old Tree, and just grab the data
|
||||
*/
|
||||
self.tree = nil;
|
||||
_fileData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:outError];
|
||||
_encryptedData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:outError];
|
||||
self.decrypted = NO;
|
||||
return YES;
|
||||
}
|
||||
@@ -193,57 +162,42 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
}
|
||||
|
||||
- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel {
|
||||
/*
|
||||
|
||||
Save as different format doesn work without KeePassKit
|
||||
hence disabled for now
|
||||
|
||||
if(!self.savePanelViewController) {
|
||||
self.savePanelViewController = [[MPSavePanelAccessoryViewController alloc] init];
|
||||
}
|
||||
self.savePanelViewController.savePanel = savePanel;
|
||||
self.savePanelViewController.document = self;
|
||||
[savePanel setAccessoryView:[self.savePanelViewController view]];
|
||||
*/
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)writeXMLToURL:(NSURL *)url {
|
||||
DataOutputStream *outputStream = [[DataOutputStream alloc] init];
|
||||
Kdb4Persist *persist = [[Kdb4Persist alloc] initWithTree:self.treeV4 outputStream:outputStream randomStream:nil];
|
||||
[persist persistWithOptions:DDXMLNodeCompactEmptyElement|DDXMLNodePrettyPrint];
|
||||
[outputStream.data writeToURL:url atomically:YES];
|
||||
NSData *xmlData = [self.tree xmlData];
|
||||
[xmlData writeToURL:url atomically:YES];
|
||||
}
|
||||
|
||||
#pragma mark Lock/Unlock/Decrypt
|
||||
|
||||
- (BOOL)unlockWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL {
|
||||
/*
|
||||
KPKPassword *passwordData = [[KPKPassword alloc] initWithPassword:password key:keyFileURL];
|
||||
KPKTree *tree = [[KPKTree alloc] initWithData:_fileData password:passwordData error:NULL];
|
||||
*/
|
||||
|
||||
self.key = keyFileURL;
|
||||
self.password = [password length] > 0 ? password : nil;
|
||||
@try {
|
||||
self.tree = [KdbReaderFactory load:[[self fileURL] path] withPassword:self.passwordHash];
|
||||
NSError *error;
|
||||
self.tree = [[KPKTree alloc] initWithData:_encryptedData password:passwordData error:&error];
|
||||
if(self.tree) {
|
||||
self.decrypted = YES;
|
||||
return YES;
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if([self.tree isKindOfClass:[Kdb4Tree class]]) {
|
||||
self.version = MPDatabaseVersion4;
|
||||
}
|
||||
else if( [self.tree isKindOfClass:[Kdb3Tree class]]) {
|
||||
self.version = MPDatabaseVersion3;
|
||||
}
|
||||
self.decrypted = YES;
|
||||
return YES;
|
||||
self.decrypted = NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)lockDatabase:(id)sender {
|
||||
// Persist Tree into data
|
||||
KPKPassword *password = [[KPKPassword alloc] initWithPassword:self.password key:self.key];
|
||||
NSError *error;
|
||||
/* Locking needs to be lossless hence just use the XML format */
|
||||
_encryptedData = [self.tree encryptWithPassword:password forVersion:KPKXmlVersion error:&error];
|
||||
self.tree = nil;
|
||||
self.locked = YES;
|
||||
}
|
||||
@@ -263,18 +217,14 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
}
|
||||
}
|
||||
|
||||
- (KdbPassword *)passwordHash {
|
||||
return [[KdbPassword alloc] initWithPassword:self.password passwordEncoding:NSUTF8StringEncoding keyFileURL:self.key];
|
||||
}
|
||||
|
||||
- (void)setSelectedGroup:(KdbGroup *)selectedGroup {
|
||||
- (void)setSelectedGroup:(KPKGroup *)selectedGroup {
|
||||
if(_selectedGroup != selectedGroup) {
|
||||
_selectedGroup = selectedGroup;
|
||||
}
|
||||
self.selectedItem = _selectedGroup;
|
||||
}
|
||||
|
||||
- (void)setSelectedEntry:(KdbEntry *)selectedEntry {
|
||||
- (void)setSelectedEntry:(KPKEntry *)selectedEntry {
|
||||
if(_selectedEntry != selectedEntry) {
|
||||
_selectedEntry = selectedEntry;
|
||||
}
|
||||
@@ -289,85 +239,52 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
}
|
||||
|
||||
#pragma mark Data Accesors
|
||||
- (void)setTree:(KdbTree *)tree {
|
||||
- (void)setTree:(KPKTree *)tree {
|
||||
if(_tree != tree) {
|
||||
_tree = tree;
|
||||
self.rootAdapter.tree = _tree;
|
||||
_tree.undoManager = [self undoManager];
|
||||
}
|
||||
}
|
||||
|
||||
- (KdbGroup *)root {
|
||||
- (KPKGroup *)root {
|
||||
return self.tree.root;
|
||||
}
|
||||
|
||||
- (KdbEntry *)findEntry:(UUID *)uuid {
|
||||
- (KPKEntry *)findEntry:(NSUUID *)uuid {
|
||||
return [self.root entryForUUID:uuid];
|
||||
}
|
||||
|
||||
- (KdbGroup *)findGroup:(UUID *)uuid {
|
||||
- (KPKGroup *)findGroup:(NSUUID *)uuid {
|
||||
return [self.root groupForUUID:uuid];
|
||||
}
|
||||
|
||||
- (Kdb3Tree *)treeV3 {
|
||||
switch (_version) {
|
||||
case MPDatabaseVersion3:
|
||||
NSAssert(self.tree == nil || [self.tree isKindOfClass:[Kdb3Tree class]], @"Tree has to be Version3");
|
||||
return (Kdb3Tree *)self.tree;
|
||||
case MPDatabaseVersion4:
|
||||
return nil;
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (Kdb4Tree *)treeV4 {
|
||||
switch (_version) {
|
||||
case MPDatabaseVersion3:
|
||||
return nil;
|
||||
case MPDatabaseVersion4:
|
||||
NSAssert(self.tree == nil || [self.tree isKindOfClass:[Kdb4Tree class]], @"Tree has to be Version4");
|
||||
return (Kdb4Tree *)self.tree;
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)useTrash {
|
||||
if(self.treeV4) {
|
||||
return self.treeV4.recycleBinEnabled;
|
||||
}
|
||||
return NO;
|
||||
return self.tree.metaData.recycleBinEnabled;
|
||||
}
|
||||
|
||||
- (KdbGroup *)trash {
|
||||
static KdbGroup *_trash = nil;
|
||||
- (KPKGroup *)trash {
|
||||
static KPKGroup *_trash = nil;
|
||||
if(self.useTrash) {
|
||||
BOOL trashValid = [((Kdb4Group *)_trash).uuid isEqual:self.treeV4.recycleBinUuid];
|
||||
BOOL trashValid = [_trash.uuid isEqual:self.tree.metaData.recycleBinUuid];
|
||||
if(!trashValid) {
|
||||
_trash = [self findGroup:self.treeV4.recycleBinUuid];
|
||||
_trash = [self findGroup:self.tree.metaData.recycleBinUuid];
|
||||
}
|
||||
return _trash;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (KdbGroup *)templates {
|
||||
static KdbGroup *_templates = nil;
|
||||
if(self.version == MPDatabaseVersion3) {
|
||||
return nil;
|
||||
}
|
||||
BOOL templateValid = [((Kdb4Group *)_templates).uuid isEqual:self.treeV4.entryTemplatesGroup];
|
||||
- (KPKGroup *)templates {
|
||||
static KPKGroup *_templates = nil;
|
||||
BOOL templateValid = [_templates.uuid isEqual:self.tree.metaData.entryTemplatesGroup];
|
||||
if(!templateValid) {
|
||||
_templates = [self findGroup:self.treeV4.entryTemplatesGroup];
|
||||
_templates = [self findGroup:self.tree.metaData.entryTemplatesGroup];
|
||||
}
|
||||
return _templates;
|
||||
}
|
||||
|
||||
- (BOOL)isItemTrashed:(id)item {
|
||||
if(self.version == MPDatabaseVersion3) {
|
||||
return NO;
|
||||
}
|
||||
BOOL validItem = [item isKindOfClass:[KdbEntry class]] || [item isKindOfClass:[KdbGroup class]];
|
||||
BOOL validItem = [item isKindOfClass:[KPKEntry class]] || [item isKindOfClass:[KPKGroup class]];
|
||||
if(!item) {
|
||||
return NO;
|
||||
}
|
||||
@@ -386,27 +303,22 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)useGroupAsTrash:(KdbGroup *)group {
|
||||
- (void)useGroupAsTrash:(KPKGroup *)group {
|
||||
if(self.useTrash) {
|
||||
Kdb4Group *groupv4 = (Kdb4Group *)group;
|
||||
if(![self.treeV4.recycleBinUuid isEqual:groupv4.uuid]) {
|
||||
self.treeV4.recycleBinUuid = groupv4.uuid;
|
||||
if(![self.tree.metaData.recycleBinUuid isEqual:group.uuid]) {
|
||||
self.tree.metaData.recycleBinUuid = group.uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)useGroupAsTemplate:(KdbGroup *)group {
|
||||
if(self.version != MPDatabaseVersion4) {
|
||||
return; // wrong database version
|
||||
}
|
||||
Kdb4Group *groupv4 = (Kdb4Group *)group;
|
||||
if(![self.treeV4.entryTemplatesGroup isEqual:groupv4.uuid]) {
|
||||
self.treeV4.entryTemplatesGroup = groupv4.uuid;
|
||||
- (void)useGroupAsTemplate:(KPKGroup *)group {
|
||||
if(![self.tree.metaData.entryTemplatesGroup isEqual:group.uuid]) {
|
||||
self.tree.metaData.entryTemplatesGroup = group.uuid;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Data manipulation
|
||||
- (KdbEntry *)createEntry:(KdbGroup *)parent {
|
||||
- (KPKEntry *)createEntry:(KPKGroup *)parent {
|
||||
if(!parent) {
|
||||
return nil; // No parent
|
||||
}
|
||||
@@ -416,16 +328,16 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
if([self isItemTrashed:parent]) {
|
||||
return nil;
|
||||
}
|
||||
KdbEntry *newEntry = [self.tree createEntry:parent];
|
||||
KPKEntry *newEntry = [self.tree createEntry:parent];
|
||||
newEntry.title = NSLocalizedString(@"DEFAULT_ENTRY_TITLE", @"Title for a newly created entry");
|
||||
if(self.treeV4 && ([self.treeV4.defaultUserName length] > 0)) {
|
||||
newEntry.title = self.treeV4.defaultUserName;
|
||||
if([self.tree.metaData.defaultUserName length] > 0) {
|
||||
newEntry.title = self.tree.metaData.defaultUserName;
|
||||
}
|
||||
[parent addEntryUndoable:newEntry atIndex:[parent.entries count]];
|
||||
[parent addEntry:newEntry];
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
- (KdbGroup *)createGroup:(KdbGroup *)parent {
|
||||
- (KPKGroup *)createGroup:(KPKGroup *)parent {
|
||||
if(!parent) {
|
||||
return nil; // no parent!
|
||||
}
|
||||
@@ -435,29 +347,25 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
if([self isItemTrashed:parent]) {
|
||||
return nil;
|
||||
}
|
||||
KdbGroup *newGroup = [self.tree createGroup:parent];
|
||||
KPKGroup *newGroup = [self.tree createGroup:parent];
|
||||
newGroup.name = NSLocalizedString(@"DEFAULT_GROUP_NAME", @"Title for a newly created group");
|
||||
newGroup.image = MPIconFolder;
|
||||
[parent addGroupUndoable:newGroup atIndex:[parent.groups count]];
|
||||
newGroup.icon = MPIconFolder;
|
||||
[parent addGroup:newGroup];
|
||||
NSDictionary *userInfo = @{ MPDocumentGroupKey : newGroup };
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidAddGroupNotification object:self userInfo:userInfo];
|
||||
return newGroup;
|
||||
}
|
||||
|
||||
- (StringField *)createStringField:(KdbEntry *)entry {
|
||||
if(![entry isKindOfClass:[Kdb4Entry class]]) {
|
||||
return nil;
|
||||
}
|
||||
Kdb4Entry *entryV4 = (Kdb4Entry *)entry;
|
||||
- (KPKAttribute *)createCustomAttribute:(KPKEntry *)entry {
|
||||
NSString *title = NSLocalizedString(@"DEFAULT_CUSTOM_FIELD_TITLE", @"Default Titel for new Custom-Fields");
|
||||
NSString *value = NSLocalizedString(@"DEFAULT_CUSTOM_FIELD_VALUE", @"Default Value for new Custom-Fields");
|
||||
title = [entryV4 uniqueKeyForProposal:title];
|
||||
StringField *newStringField = [StringField stringFieldWithKey:title andValue:value];
|
||||
[self addStringField:newStringField toEntry:entryV4 atIndex:[entryV4.stringFields count]];
|
||||
return newStringField;
|
||||
title = [entry proposedKeyForAttributeKey:title];
|
||||
KPKAttribute *newAttribute = [[KPKAttribute alloc] initWithKey:title value:value];
|
||||
[entry addCustomAttribute:newAttribute];
|
||||
return newAttribute;
|
||||
}
|
||||
|
||||
- (void)deleteEntry:(KdbEntry *)entry {
|
||||
- (void)deleteEntry:(KPKEntry *)entry {
|
||||
if(self.useTrash) {
|
||||
if(!self.trash) {
|
||||
[self _createTrashGroup];
|
||||
@@ -465,15 +373,17 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
if([self isItemTrashed:entry]) {
|
||||
return; // Entry is already trashed
|
||||
}
|
||||
[entry moveToTrashUndoable:self.trash atIndex:[self.trash.entries count]];
|
||||
[entry moveToGroup:self.trash atIndex:[self.trash.entries count]];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"TRASH_ENTRY", "Move Entry to Trash")];
|
||||
}
|
||||
else {
|
||||
[entry deleteUndoable];
|
||||
[entry remove];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"DELETE_ENTRY", "")];
|
||||
}
|
||||
self.selectedEntry = nil;
|
||||
}
|
||||
|
||||
- (void)deleteGroup:(KdbGroup *)group {
|
||||
- (void)deleteGroup:(KPKGroup *)group {
|
||||
if(self.useTrash) {
|
||||
if(!self.trash) {
|
||||
[self _createTrashGroup];
|
||||
@@ -481,38 +391,18 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
if( (group == self.trash) || [self isItemTrashed:group] ) {
|
||||
return; //Groups already trashed cannot be deleted
|
||||
}
|
||||
[group moveToTrashUndoable:self.trash atIndex:[self.trash.groups count]];
|
||||
[group moveToGroup:self.trash atIndex:[self.trash.groups count]];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"TRASH_GROUP", "Move Group to Trash")];
|
||||
}
|
||||
else {
|
||||
[group deleteUndoable];
|
||||
[group remove];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"DELETE_GROUP", "Delete Group")];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark CustomFields
|
||||
- (void)addStringField:(StringField *)field toEntry:(Kdb4Entry *)entry atIndex:(NSUInteger)index {
|
||||
[[[self undoManager] prepareWithInvocationTarget:self] removeStringField:field formEntry:entry];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_ADD_STRING_FIELD", @"Add Stringfield Undo")];
|
||||
field.entry = entry;
|
||||
[entry insertObject:field inStringFieldsAtIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeStringField:(StringField *)field formEntry:(Kdb4Entry *)entry {
|
||||
NSInteger index = [entry.stringFields indexOfObject:field];
|
||||
if(NSNotFound == index) {
|
||||
return; // Nothing found to be removed
|
||||
}
|
||||
[[[self undoManager] prepareWithInvocationTarget:self] addStringField:field toEntry:entry atIndex:index];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_DELETE_STRING_FIELD", @"Delte Stringfield undo")];
|
||||
field.entry = nil;
|
||||
[entry removeObjectFromStringFieldsAtIndex:index];
|
||||
}
|
||||
|
||||
#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", "")];
|
||||
@@ -534,7 +424,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
|
||||
- (void)createEntryFromTemplate:(id)sender {
|
||||
NSMenuItem *item = sender;
|
||||
KdbEntry *entry = [item representedObject];
|
||||
KPKEntry *entry = [item representedObject];
|
||||
if(entry) {
|
||||
// Create Entry from template;
|
||||
}
|
||||
@@ -565,50 +455,32 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
|
||||
}
|
||||
}
|
||||
|
||||
- (KdbGroup *)_createTrashGroup {
|
||||
- (KPKGroup *)_createTrashGroup {
|
||||
/* Maybe push the stuff to the Tree? */
|
||||
if(self.version == MPDatabaseVersion3) {
|
||||
return nil;
|
||||
KPKGroup *trash = [self.tree createGroup:self.tree.root];
|
||||
trash.name = NSLocalizedString(@"TRASH", @"Name for the trash group");
|
||||
trash.icon = MPIconTrash;
|
||||
BOOL registrationEnable = [[self undoManager] isUndoRegistrationEnabled];
|
||||
if(registrationEnable) {
|
||||
[[self undoManager] disableUndoRegistration];
|
||||
}
|
||||
else if(self.version == MPDatabaseVersion4) {
|
||||
KdbGroup *trash = [self.tree createGroup:self.tree.root];
|
||||
trash.name = NSLocalizedString(@"TRASH", @"Name for the trash group");
|
||||
trash.image = MPIconTrash;
|
||||
[self.tree.root insertObject:trash inGroupsAtIndex:[self.tree.root.groups count]];
|
||||
self.treeV4.recycleBinUuid = ((Kdb4Group *)trash).uuid;
|
||||
return trash;
|
||||
}
|
||||
else {
|
||||
NSAssert(NO, @"Database with unknown version: %ld", _version);
|
||||
return nil;
|
||||
[self.tree.root addGroup:trash];
|
||||
if(registrationEnable) {
|
||||
[[self undoManager] enableUndoRegistration];
|
||||
}
|
||||
|
||||
self.tree.metaData.recycleBinUuid = trash.uuid;
|
||||
return trash;
|
||||
}
|
||||
|
||||
- (void)_emptyTrash {
|
||||
for(KdbEntry *entry in [self.trash childEntries]) {
|
||||
for(KPKEntry *entry in [self.trash childEntries]) {
|
||||
[[self undoManager] removeAllActionsWithTarget:entry];
|
||||
}
|
||||
for(KdbGroup *group in [self.trash childGroups]) {
|
||||
for(KPKGroup *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
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class KdbEntry;
|
||||
@class KPKEntry;
|
||||
|
||||
@interface MPDocumentQueryService : NSObject
|
||||
|
||||
+ (MPDocumentQueryService *)defaultService;
|
||||
|
||||
- (KdbEntry *)configurationEntry;
|
||||
- (KdbEntry *)createConfigurationEntry;
|
||||
- (KPKEntry *)configurationEntry;
|
||||
- (KPKEntry *)createConfigurationEntry;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
|
||||
#import "MPDocumentQueryService.h"
|
||||
#import "MPDocument.h"
|
||||
#import "UUID.h"
|
||||
|
||||
#import "NSUUID+KeePassKit.h"
|
||||
|
||||
@interface MPDocumentQueryService () {
|
||||
@private
|
||||
UUID *rootUuid;
|
||||
NSUUID *rootUuid;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -36,20 +37,20 @@
|
||||
0x9f, 0x36, 0x89, 0x7d, 0x62, 0x3e, 0xcb, 0x31
|
||||
};
|
||||
NSData *data = [NSData dataWithBytes:uuidBytes length:16];
|
||||
rootUuid = [[UUID alloc] initWithData:data];
|
||||
rootUuid = [[NSUUID alloc] initWithData:data];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (KdbEntry *)configurationEntry {
|
||||
- (KPKEntry *)configurationEntry {
|
||||
/*
|
||||
We are looking in all document,
|
||||
but only store the key in one.
|
||||
*/
|
||||
NSArray *documents = [[NSDocumentController sharedDocumentController] documents];
|
||||
for(MPDocument *document in documents) {
|
||||
KdbEntry *entry = [document findEntry:rootUuid];
|
||||
KPKEntry *entry = [document findEntry:rootUuid];
|
||||
if(entry) {
|
||||
return entry;
|
||||
}
|
||||
@@ -57,7 +58,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (KdbEntry *)createConfigurationEntry {
|
||||
- (KPKEntry *)createConfigurationEntry {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
@class MPPasswordInputController;
|
||||
@class MPOutlineViewController;
|
||||
|
||||
@class KdbGroup;
|
||||
@class KdbEntry;
|
||||
|
||||
@interface MPDocumentWindowController : NSWindowController
|
||||
|
||||
@property (readonly, strong) MPPasswordInputController *passwordInputController;
|
||||
|
||||
@@ -184,9 +184,6 @@
|
||||
}
|
||||
|
||||
BOOL enabled = YES;
|
||||
if(itemAction == @selector(exportDatabase:)) {
|
||||
enabled = (nil != document.treeV4);
|
||||
}
|
||||
if(itemAction == [MPActionHelper actionOfType:MPActionDelete]) {
|
||||
enabled &= (nil != document.selectedItem) && (document.selectedItem != document.trash);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#import "MPDocumentWindowDelegate.h"
|
||||
#import "MPDocument.h"
|
||||
#import "Kdb.h"
|
||||
#import "KdbEntry+Undo.h"
|
||||
|
||||
#import "KPKEntry.h"
|
||||
|
||||
@implementation MPDocumentWindowDelegate
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
BOOL ok = NO;
|
||||
if(document.selectedGroup) {
|
||||
[[document undoManager] beginUndoGrouping];
|
||||
KdbEntry *entry = [document createEntry:document.selectedGroup];
|
||||
KPKEntry *entry = [document createEntry:document.selectedGroup];
|
||||
ok = (nil != entry);
|
||||
entry.urlUndoable = [url absoluteString];
|
||||
entry.url = [url absoluteString];
|
||||
[[document undoManager] endUndoGrouping];
|
||||
[[document undoManager] setActionName:NSLocalizedString(@"IMPORT_URL", @"Imports a dragged URL for a new entry")];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#import "MPEntryContextMenuDelegate.h"
|
||||
#import "MPDocument.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKAttribute.h"
|
||||
|
||||
static NSUInteger const kMPCustomFieldMenuItem = 1000;
|
||||
static NSUInteger const kMPAttachmentsMenuItem = 2000;
|
||||
@@ -25,29 +26,28 @@ static NSUInteger const kMPAttachmentsMenuItem = 2000;
|
||||
if(attachmentsMenu) {
|
||||
[menu removeItem:attachmentsMenu];
|
||||
}
|
||||
|
||||
|
||||
NSMenuItem *lastItem = [[menu itemArray] lastObject];
|
||||
if([lastItem isSeparatorItem]) {
|
||||
[menu removeItem:lastItem];
|
||||
}
|
||||
MPDocument *document = [[NSDocumentController sharedDocumentController] currentDocument];
|
||||
if([document.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
Kdb4Entry *entry = (Kdb4Entry *)document.selectedEntry;
|
||||
if([entry.stringFields count] > 0) {
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
NSMenuItem *customFieldsItem = [[NSMenuItem alloc] init];
|
||||
NSMenu *submenu = [[NSMenu alloc] initWithTitle:@"Fields"];
|
||||
[customFieldsItem setTitle:NSLocalizedString(@"COPY_CUSTOM_FIELDS", "Submenu to Copy custom fields")];
|
||||
[customFieldsItem setTag:kMPCustomFieldMenuItem];
|
||||
for (StringField *field in entry.stringFields) {
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"COPY_FIELD_%@", "Mask for title to copy field value"), field.key];
|
||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:@selector(copyCustomField:) keyEquivalent:@""];
|
||||
[item setTag:[entry.stringFields indexOfObject:field]];
|
||||
[submenu addItem:item];
|
||||
}
|
||||
[customFieldsItem setSubmenu:submenu];
|
||||
[menu addItem:customFieldsItem];
|
||||
|
||||
KPKEntry *entry = document.selectedEntry;
|
||||
if([entry.customAttributes count] > 0) {
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
NSMenuItem *attributeItem = [[NSMenuItem alloc] init];
|
||||
NSMenu *submenu = [[NSMenu alloc] initWithTitle:@"Fields"];
|
||||
[attributeItem setTitle:NSLocalizedString(@"COPY_CUSTOM_FIELDS", "Submenu to Copy custom fields")];
|
||||
[attributeItem setTag:kMPCustomFieldMenuItem];
|
||||
for (KPKAttribute *attribute in entry.customAttributes) {
|
||||
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"COPY_FIELD_%@", "Mask for title to copy field value"), attribute.key];
|
||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:@selector(copyCustomAttribute:) keyEquivalent:@""];
|
||||
[item setTag:[entry.customAttributes indexOfObject:attribute]];
|
||||
[submenu addItem:item];
|
||||
}
|
||||
[attributeItem setSubmenu:submenu];
|
||||
[menu addItem:attributeItem];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#import "MPViewController.h"
|
||||
|
||||
@class KdbEntry;
|
||||
@class HNHRoundedSecureTextField;
|
||||
@class MPDocument;
|
||||
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#import "MPDocument.h"
|
||||
#import "MPIconHelper.h"
|
||||
|
||||
#import "Kdb.h"
|
||||
#import "Kdb3Node.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "KdbEntry+Undo.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKBinary.h"
|
||||
|
||||
#import "HNHScrollView.h"
|
||||
#import "HNHRoundedSecureTextField.h"
|
||||
@@ -43,7 +41,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
@property (nonatomic, assign) MPEntryTab activeTab;
|
||||
@property (strong) NSPopover *activePopover;
|
||||
|
||||
@property (nonatomic, weak) KdbEntry *entry;
|
||||
@property (nonatomic, weak) KPKEntry *entry;
|
||||
|
||||
@end
|
||||
|
||||
@@ -54,23 +52,23 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
}
|
||||
|
||||
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
if (self) {
|
||||
_showPassword = NO;
|
||||
_attachmentsController = [[NSArrayController alloc] init];
|
||||
_customFieldsController = [[NSArrayController alloc] init];
|
||||
_attachmentTableDelegate = [[MPAttachmentTableViewDelegate alloc] init];
|
||||
_customFieldTableDelegate = [[MPCustomFieldTableViewDelegate alloc] init];
|
||||
_attachmentDataSource = [[MPAttachmentTableDataSource alloc] init];
|
||||
_attachmentTableDelegate.viewController = self;
|
||||
_customFieldTableDelegate.viewController = self;
|
||||
_activeTab = MPEntryTabGeneral;
|
||||
}
|
||||
return self;
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
if (self) {
|
||||
_showPassword = NO;
|
||||
_attachmentsController = [[NSArrayController alloc] init];
|
||||
_customFieldsController = [[NSArrayController alloc] init];
|
||||
_attachmentTableDelegate = [[MPAttachmentTableViewDelegate alloc] init];
|
||||
_customFieldTableDelegate = [[MPCustomFieldTableViewDelegate alloc] init];
|
||||
_attachmentDataSource = [[MPAttachmentTableDataSource alloc] init];
|
||||
_attachmentTableDelegate.viewController = self;
|
||||
_customFieldTableDelegate.viewController = self;
|
||||
_activeTab = MPEntryTabGeneral;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didLoadView {
|
||||
|
||||
|
||||
/* ScrollView setup for the General Tab */
|
||||
|
||||
HNHScrollView *scrollView = [[HNHScrollView alloc] init];
|
||||
@@ -117,7 +115,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
[_customFieldsTableView setBackgroundColor:[NSColor clearColor]];
|
||||
[_customFieldsTableView bind:NSContentBinding toObject:_customFieldsController withKeyPath:@"arrangedObjects" options:nil];
|
||||
[_customFieldsTableView setDelegate:_customFieldTableDelegate];
|
||||
|
||||
|
||||
|
||||
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
|
||||
[self.togglePassword bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
|
||||
@@ -127,7 +125,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
[self bind:@"entry" toObject:document withKeyPath:@"selectedEntry" options:nil];
|
||||
}
|
||||
|
||||
- (void)setEntry:(KdbEntry *)entry {
|
||||
- (void)setEntry:(KPKEntry *)entry {
|
||||
if(_entry != entry) {
|
||||
_entry = entry;
|
||||
[self _updateContent];
|
||||
@@ -139,36 +137,23 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
|
||||
- (IBAction)addCustomField:(id)sender {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
[document createStringField:self.entry];
|
||||
[document createCustomAttribute:self.entry];
|
||||
}
|
||||
- (IBAction)removeCustomField:(id)sender {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
NSUInteger index = [sender tag];
|
||||
Kdb4Entry *entry = (Kdb4Entry *)self.entry;
|
||||
[document removeStringField:(entry.stringFields)[index] formEntry:entry];
|
||||
KPKAttribute *attribute = self.entry.customAttributes[index];
|
||||
[self.entry removeCustomAttribute:attribute];
|
||||
}
|
||||
|
||||
- (IBAction)saveAttachment:(id)sender {
|
||||
BOOL isVersion4 = [self.entry isKindOfClass:[Kdb4Entry class]];
|
||||
id item = self.entry;
|
||||
NSString *fileName = nil;
|
||||
if(isVersion4) {
|
||||
Kdb4Entry *entry= (Kdb4Entry *)self.entry;
|
||||
item = entry.binaries[[sender tag]];
|
||||
fileName = ((BinaryRef *)item).key;
|
||||
}
|
||||
else {
|
||||
fileName = ((Kdb3Entry *)item).binaryDesc;
|
||||
}
|
||||
|
||||
KPKBinary *binary = self.entry.binaries[[sender tag]];
|
||||
NSSavePanel *savePanel = [NSSavePanel savePanel];
|
||||
[savePanel setCanCreateDirectories:YES];
|
||||
[savePanel setNameFieldStringValue:fileName];
|
||||
[savePanel setNameFieldStringValue:binary.name];
|
||||
|
||||
[savePanel beginSheetModalForWindow:[[self windowController] window] completionHandler:^(NSInteger result) {
|
||||
if(result == NSFileHandlingPanelOKButton) {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
[document saveAttachmentForItem:item toLocation:[savePanel URL]];
|
||||
[binary saveToLocation:[savePanel URL]];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -180,24 +165,17 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
[openPanel setAllowsMultipleSelection:YES];
|
||||
[openPanel beginSheetModalForWindow:[[self windowController] window] completionHandler:^(NSInteger result) {
|
||||
if(result == NSFileHandlingPanelOKButton) {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
for (NSURL *attachmentURL in [openPanel URLs]) {
|
||||
[document addAttachment:attachmentURL toEntry:self.entry];
|
||||
KPKBinary *binary = [[KPKBinary alloc] initWithContentsOfURL:attachmentURL];
|
||||
[self.entry addBinary:binary];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)removeAttachment:(id)sender {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
if(document.version == MPDatabaseVersion3) {
|
||||
[document removeAttachmentFromEntry:self.entry];
|
||||
}
|
||||
else if(document.version == MPDatabaseVersion4) {
|
||||
Kdb4Entry *entry = (Kdb4Entry *)self.entry;
|
||||
BinaryRef *reference = entry.binaries[[sender tag]];
|
||||
[document removeAttachment:reference fromEntry:self.entry];
|
||||
}
|
||||
KPKBinary *binary = self.entry.binaries[[sender tag]];
|
||||
[self.entry removeBinary:binary];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -230,7 +208,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
NSString *password = [controller generatedPassword];
|
||||
/* We should only use the password if there is actally one */
|
||||
if([password length] > 0) {
|
||||
self.entry.passwordUndoable = [controller generatedPassword];
|
||||
self.entry.password = [controller generatedPassword];
|
||||
}
|
||||
}
|
||||
/* TODO: Check for Icon wizzard */
|
||||
@@ -249,15 +227,12 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
- (void)_bindEntry {
|
||||
|
||||
if(self.entry) {
|
||||
[self.titleTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"titleUndoable" options:nil];
|
||||
[self.titleTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"title" options:nil];
|
||||
//[self.itemImageView setImage:[MPIconHelper icon:(MPIconType)self.entry.image ]];
|
||||
[self.passwordTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"passwordUndoable" options:nil];
|
||||
[self.usernameTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"usernameUndoable" options:nil];
|
||||
[self.URLTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"urlUndoable" options:nil];
|
||||
[self.notesTextView bind:NSValueBinding toObject:self.entry withKeyPath:@"notesUndoable" options:nil];
|
||||
|
||||
BOOL isKdbx = [self.entry isKindOfClass:[Kdb4Entry class]];
|
||||
[self.infoTabControl setEnabled:isKdbx forSegment:MPEntryTabCustomFields];
|
||||
[self.passwordTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"password" options:nil];
|
||||
[self.usernameTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"username" options:nil];
|
||||
[self.URLTextField bind:NSValueBinding toObject:self.entry withKeyPath:@"url" options:nil];
|
||||
[self.notesTextView bind:NSValueBinding toObject:self.entry withKeyPath:@"notes" options:nil];
|
||||
}
|
||||
else {
|
||||
[self.titleTextField unbind:NSValueBinding];
|
||||
@@ -279,13 +254,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
}
|
||||
|
||||
- (void)_bindCustomFields {
|
||||
if(self.entry && [self.entry isKindOfClass:[Kdb4Entry class]]) {
|
||||
[_customFieldsController bind:NSContentArrayBinding toObject:self.entry withKeyPath:@"stringFields" options:nil];
|
||||
}
|
||||
else if([_customFieldsController content] != nil){
|
||||
[_customFieldsController unbind:NSContentArrayBinding];
|
||||
[_customFieldsController setContent:nil];
|
||||
}
|
||||
[_customFieldsController bind:NSContentArrayBinding toObject:self.entry withKeyPath:@"customAttributes" options:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
#import "MPEntryTableDataSource.h"
|
||||
#import "MPEntryViewController.h"
|
||||
|
||||
#import "Kdb.h"
|
||||
#import "UUID+Pasterboard.h"
|
||||
|
||||
#import "MPConstants.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "NSUUID+KeePassKit.h"
|
||||
|
||||
@interface MPEntryTableDataSource ()
|
||||
|
||||
@@ -27,10 +25,10 @@
|
||||
}
|
||||
|
||||
id item = [self.viewController.entryArrayController arrangedObjects][[rowIndexes firstIndex]];
|
||||
if(![item isKindOfClass:[KdbEntry class]]) {
|
||||
if(![item isKindOfClass:[KPKEntry class]]) {
|
||||
return NO;
|
||||
}
|
||||
KdbEntry *entry = (KdbEntry *)item;
|
||||
KPKEntry *entry = (KPKEntry *)item;
|
||||
[pboard writeObjects:@[entry.uuid]];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -22,14 +22,13 @@ typedef NS_ENUM( NSUInteger, MPCopyContentTypeTag) {
|
||||
MPCopyWholeEntry,
|
||||
};
|
||||
|
||||
@class KdbGroup;
|
||||
@class KdbEntry;
|
||||
@class KPKEntry;
|
||||
@class MPOutlineViewDelegate;
|
||||
@class MPDocumentWindowController;
|
||||
|
||||
@interface MPEntryViewController : MPViewController <NSTableViewDelegate>
|
||||
|
||||
@property (readonly, weak, nonatomic) KdbEntry *selectedEntry;
|
||||
@property (readonly, weak, nonatomic) KPKEntry *selectedEntry;
|
||||
|
||||
@property (weak,readonly) NSTableView *entryTable;
|
||||
@property (readonly, strong) NSArrayController *entryArrayController;
|
||||
@@ -46,7 +45,7 @@ typedef NS_ENUM( NSUInteger, MPCopyContentTypeTag) {
|
||||
/* Copy/Paste */
|
||||
- (void)copyUsername:(id)sender;
|
||||
- (void)copyPassword:(id)sender;
|
||||
- (void)copyCustomField:(id)sender;
|
||||
- (void)copyCustomAttribute:(id)sender;
|
||||
- (void)copyURL:(id)sender;
|
||||
- (void)openURL:(id)sender;
|
||||
|
||||
|
||||
@@ -24,14 +24,15 @@
|
||||
#import "MPStripLineBreaksTransformer.h"
|
||||
#import "MPEntryContextMenuDelegate.h"
|
||||
|
||||
#import "KPKUTIs.h"
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKNode+IconImage.h"
|
||||
#import "KPKAttribute.h"
|
||||
|
||||
#import "HNHTableHeaderCell.h"
|
||||
#import "HNHGradientView.h"
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
#import "KdbEntry+Undo.h"
|
||||
|
||||
#import "MPNotifications.h"
|
||||
|
||||
#define STATUS_BAR_ANIMATION_TIME 0.15
|
||||
@@ -90,7 +91,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
@property (weak) IBOutlet NSTextField *entryCountTextField;
|
||||
|
||||
|
||||
@property (weak) KdbEntry *selectedEntry;
|
||||
@property (weak) KPKEntry *selectedEntry;
|
||||
|
||||
@property (nonatomic, strong) MPEntryTableDataSource *dataSource;
|
||||
|
||||
@@ -139,7 +140,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
[self.entryTable setDoubleAction:@selector(_columnDoubleClick:)];
|
||||
[self.entryTable setTarget:self];
|
||||
[self.entryTable setFloatsGroupRows:NO];
|
||||
[self.entryTable registerForDraggedTypes:@[MPEntryUTI]];
|
||||
[self.entryTable registerForDraggedTypes:@[KPKEntryUTI]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didBecomFirstResponder:)
|
||||
name:MPDidActivateViewNotification
|
||||
@@ -209,7 +210,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
#pragma mark NSTableViewDelgate
|
||||
|
||||
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
|
||||
KdbEntry *entry = [self.entryArrayController arrangedObjects][row];
|
||||
KPKEntry *entry = [self.entryArrayController arrangedObjects][row];
|
||||
BOOL isTitleColumn = [[tableColumn identifier] isEqualToString:MPEntryTableTitleColumnIdentifier];
|
||||
BOOL isGroupColumn = [[tableColumn identifier] isEqualToString:MPEntryTableParentColumnIdentifier];
|
||||
BOOL isPasswordColum = [[tableColumn identifier] isEqualToString:MPEntryTablePasswordColumnIdentifier];
|
||||
@@ -223,31 +224,31 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
if(isTitleColumn || isGroupColumn) {
|
||||
view = [tableView makeViewWithIdentifier:_MPTableImageCellView owner:self];
|
||||
if( isTitleColumn ) {
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"titleUndoable" options:nil];
|
||||
[[view imageView] setImage:[MPIconHelper icon:(MPIconType)entry.image]];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"title" options:nil];
|
||||
[[view imageView] setImage:entry.iconImage];
|
||||
}
|
||||
else {
|
||||
assert(entry.parent);
|
||||
[[view textField] bind:NSValueBinding toObject:entry.parent withKeyPath:MPGroupNameUndoableKey options:nil];
|
||||
[[view imageView] setImage:[MPIconHelper icon:(MPIconType)entry.parent.image]];
|
||||
[[view textField] bind:NSValueBinding toObject:entry.parent withKeyPath:entry.parent.name options:nil];
|
||||
[[view imageView] setImage:entry.iconImage];
|
||||
}
|
||||
}
|
||||
else if( isPasswordColum ) {
|
||||
view = [tableView makeViewWithIdentifier:_MPTAbleSecurCellView owner:self];
|
||||
NSDictionary *options = @{ NSValueTransformerBindingOption : [NSValueTransformer valueTransformerForName:MPStringLengthValueTransformerName] };
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"passwordUndoable" options:options];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"password" options:options];
|
||||
}
|
||||
else {
|
||||
view = [tableView makeViewWithIdentifier:_MPTableStringCellView owner:self];
|
||||
if(isURLColumn) {
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"urlUndoable" options:nil];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"url" options:nil];
|
||||
}
|
||||
else if( isUsernameColumn) {
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"usernameUndoable" options:nil];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"username" options:nil];
|
||||
}
|
||||
else if( isNotesColumn ) {
|
||||
NSDictionary *options = @{ NSValueTransformerNameBindingOption : MPStripLineBreaksTransformerName };
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"notesUndoable" options:options];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"notes" options:options];
|
||||
}
|
||||
else if( isAttachmentColumn ) {
|
||||
[[view textField] setStringValue:@""];
|
||||
@@ -258,7 +259,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
[formatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
[formatter setTimeStyle:NSDateFormatterMediumStyle];
|
||||
[[view textField] setFormatter:formatter];
|
||||
[[view textField] bind:NSValueBinding toObject:entry withKeyPath:@"lastModificationTime" options:nil];
|
||||
[[view textField] bind:NSValueBinding toObject:entry.timeInfo withKeyPath:@"lastModificationTime" options:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,13 +293,13 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
If we reselct the group, or just another group
|
||||
we clear the filter and bind to the new selected group
|
||||
*/
|
||||
if([self _showsFilterBar] && ![document.selectedItem isKindOfClass:[KdbEntry class]]) {
|
||||
if([self _showsFilterBar] && ![document.selectedItem isKindOfClass:[KPKEntry class]]) {
|
||||
[self clearFilter:nil];
|
||||
[self.entryArrayController bind:NSContentArrayBinding toObject:document.selectedGroup withKeyPath:@"entries" options:nil];
|
||||
return;
|
||||
}
|
||||
if([[self.entryArrayController content] count] > 0) {
|
||||
KdbEntry *entry = [[self.entryArrayController content] lastObject];
|
||||
KPKEntry *entry = [[self.entryArrayController content] lastObject];
|
||||
if(entry.parent == document.selectedGroup) {
|
||||
return; // we are showing the correct object right now.
|
||||
}
|
||||
@@ -593,9 +594,9 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
}
|
||||
|
||||
|
||||
#pragma makr Action Helper
|
||||
#pragma mark Action Helper
|
||||
|
||||
- (KdbEntry *)_clickedOrSelectedEntry {
|
||||
- (KPKEntry *)_clickedOrSelectedEntry {
|
||||
NSInteger activeRow = [self.entryTable clickedRow];
|
||||
/* Fallback to selection e.g. for toolbar actions */
|
||||
if(activeRow < 0 ) {
|
||||
@@ -610,39 +611,38 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)copyPassword:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
KPKEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry) {
|
||||
[self _copyToPasteboard:selectedEntry.password overlayInfo:MPOverlayInfoPassword name:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyUsername:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
KPKEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry) {
|
||||
[self _copyToPasteboard:selectedEntry.username overlayInfo:MPOverlayInfoUsername name:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyCustomField:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry && [selectedEntry isKindOfClass:[Kdb4Entry class]]) {
|
||||
Kdb4Entry *entry = (Kdb4Entry *)selectedEntry;
|
||||
- (void)copyCustomAttribute:(id)sender {
|
||||
KPKEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry && [selectedEntry isKindOfClass:[KPKEntry class]]) {
|
||||
NSUInteger index = [sender tag];
|
||||
NSAssert((index >= 0) && (index < [entry.stringFields count]), @"Index for custom field needs to be valid");
|
||||
StringField *field = entry.stringFields[index];
|
||||
[self _copyToPasteboard:field.value overlayInfo:MPOverlayInfoCustom name:field.key];
|
||||
NSAssert((index >= 0) && (index < [selectedEntry.customAttributes count]), @"Index for custom field needs to be valid");
|
||||
KPKAttribute *attribute = selectedEntry.customAttributes[index];
|
||||
[self _copyToPasteboard:attribute.value overlayInfo:MPOverlayInfoCustom name:attribute.key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyURL:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
KPKEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry) {
|
||||
[self _copyToPasteboard:selectedEntry.url overlayInfo:MPOverlayInfoURL name:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)openURL:(id)sender {
|
||||
KdbEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
KPKEntry *selectedEntry = [self _clickedOrSelectedEntry];
|
||||
if(selectedEntry && [selectedEntry.url length] > 0) {
|
||||
NSURL *webURL = [NSURL URLWithString:selectedEntry.url];
|
||||
[[NSWorkspace sharedWorkspace] openURL:webURL];
|
||||
@@ -650,7 +650,7 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
|
||||
}
|
||||
|
||||
- (void)deleteNode:(id)sender {
|
||||
KdbEntry *entry =[self _clickedOrSelectedEntry];
|
||||
KPKEntry *entry =[self _clickedOrSelectedEntry];
|
||||
MPDocument *document = [[self windowController] document];
|
||||
[document deleteEntry:entry];
|
||||
}
|
||||
|
||||
@@ -10,16 +10,14 @@
|
||||
#import "MPDocument.h"
|
||||
#import "MPPasteBoardController.h"
|
||||
|
||||
#import "Kdb.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb4Group+Undo.h"
|
||||
#import "KPKGroup.h"
|
||||
|
||||
#import "HNHScrollView.h"
|
||||
#import "HNHRoundedTextField.h"
|
||||
|
||||
@interface MPGroupInspectorViewController ()
|
||||
|
||||
@property (nonatomic, weak) KdbGroup *group;
|
||||
@property (nonatomic, weak) KPKGroup *group;
|
||||
|
||||
@end
|
||||
|
||||
@@ -66,7 +64,7 @@
|
||||
[self bind:@"group" toObject:document withKeyPath:@"selectedGroup" options:nil];
|
||||
}
|
||||
|
||||
- (void)setGroup:(KdbGroup *)group {
|
||||
- (void)setGroup:(KPKGroup *)group {
|
||||
if(_group != group) {
|
||||
_group = group;
|
||||
[self _updateBindings];
|
||||
@@ -75,14 +73,8 @@
|
||||
|
||||
- (void)_updateBindings {
|
||||
if(self.group) {
|
||||
[self.titleTextField bind:NSValueBinding toObject:self.group withKeyPath:@"nameUndoable" options:nil];
|
||||
if([self.group isKindOfClass:[Kdb4Group class]]) {
|
||||
[self.notesTextView bind:NSValueBinding toObject:self.group withKeyPath:@"notesUndoable" options:nil];
|
||||
}
|
||||
else {
|
||||
[self.notesTextView unbind:NSValueBinding];
|
||||
[self.notesTextView setString:@""];
|
||||
}
|
||||
[self.titleTextField bind:NSValueBinding toObject:self.group withKeyPath:@"name" options:nil];
|
||||
[self.notesTextView bind:NSValueBinding toObject:self.group withKeyPath:@"notes" options:nil];
|
||||
}
|
||||
else {
|
||||
[self.titleTextField unbind:NSValueBinding];
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
#import "NSDate+Humanized.h"
|
||||
|
||||
#import "KdbLib.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "Kdb3Node.h"
|
||||
|
||||
#import "HNHGradientView.h"
|
||||
#import "MPPopupImageView.h"
|
||||
@@ -162,7 +159,7 @@ typedef NS_ENUM(NSUInteger, MPContentTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.itemImageView bind:NSValueBinding toObject:item withKeyPath:@"icon" options:nil];
|
||||
[self.itemImageView bind:NSValueBinding toObject:item withKeyPath:@"iconImage" options:nil];
|
||||
|
||||
if([item respondsToSelector:@selector(title)]) {
|
||||
[self.itemNameTextField bind:NSValueBinding toObject:item withKeyPath:@"title" options:nil];
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#import "MPOutlineContextMenuDelegate.h"
|
||||
#import "MPOutlineViewController.h"
|
||||
|
||||
#import "MPRootAdapter.h"
|
||||
#import "MPDocument.h"
|
||||
|
||||
#import "MPActionHelper.h"
|
||||
#import "MPContextMenuHelper.h"
|
||||
|
||||
#import "Kdb.h"
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKTree.h"
|
||||
|
||||
NSString *const _MPOutlineMenuDefault = @"Default";
|
||||
NSString *const _MPOutlineMenuTrash = @"Trash";
|
||||
@@ -37,13 +37,16 @@ NSString *const _MPOutlineMenuTemplate = @"Template";
|
||||
*/
|
||||
|
||||
id item = [self.viewController itemUnderMouse];
|
||||
if( [item isKindOfClass:[MPRootAdapter class]]) {
|
||||
if( [item isKindOfClass:[KPKTree class]]) {
|
||||
[self _updateRootMenu:menu];
|
||||
}
|
||||
|
||||
if( [item isKindOfClass:[KdbGroup class]]) {
|
||||
KdbGroup *group = (KdbGroup *)item;
|
||||
if( [item isKindOfClass:[KPKGroup class]]) {
|
||||
KPKGroup *group = (KPKGroup *)item;
|
||||
MPDocument *document = [[NSDocumentController sharedDocumentController] currentDocument];
|
||||
if(group && document.root == group ) {
|
||||
|
||||
}
|
||||
if(group && document.trash == group) {
|
||||
[self _updateTrashMenu:menu];
|
||||
}
|
||||
|
||||
@@ -9,21 +9,17 @@
|
||||
#import "MPOutlineDataSource.h"
|
||||
#import "MPDocument.h"
|
||||
#import "MPConstants.h"
|
||||
#import "MPRootAdapter.h"
|
||||
|
||||
#import "KdbLib.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
#import "KdbEntry+Undo.h"
|
||||
#import "KdbGroup+MPTreeTools.h"
|
||||
#import "KdbEntry+MPTreeTools.h"
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKEntry.h"
|
||||
#import "KPKUTIs.h"
|
||||
|
||||
#import "UUID.h"
|
||||
#import "UUID+Pasterboard.h"
|
||||
#import "NSUUID+KeePassKit.h"
|
||||
|
||||
@interface MPOutlineDataSource ()
|
||||
|
||||
@property (weak) KdbGroup *draggedGroup;
|
||||
@property (weak) KdbEntry *draggedEntry;
|
||||
@property (weak) KPKGroup *draggedGroup;
|
||||
@property (weak) KPKEntry *draggedEntry;
|
||||
|
||||
@end
|
||||
|
||||
@@ -33,8 +29,12 @@
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard {
|
||||
self.draggedGroup = nil;
|
||||
if([items count] == 1) {
|
||||
[pasteboard setString:self.draggedGroup.name forType:MPGroupUTI];
|
||||
self.draggedGroup = [[items lastObject] representedObject];
|
||||
id item = [[items lastObject] representedObject];
|
||||
if(![item isKindOfClass:[KPKGroup class]]) {
|
||||
return NO;
|
||||
}
|
||||
[pasteboard setString:self.draggedGroup.name forType:KPKGroupUTI];
|
||||
self.draggedGroup = item;
|
||||
return (nil != self.draggedGroup.parent);
|
||||
}
|
||||
return NO;
|
||||
@@ -50,25 +50,25 @@
|
||||
oprationMask = NSDragOperationCopy;
|
||||
}
|
||||
*/
|
||||
id targetItem = [item representedObject];
|
||||
if(targetItem == nil || [targetItem isKindOfClass:[MPRootAdapter class]]) {
|
||||
return NSDragOperationNone; // no Target
|
||||
}
|
||||
|
||||
NSPasteboard *pasteBoard = [info draggingPasteboard];
|
||||
NSArray *types = [pasteBoard types];
|
||||
if([types count] > 1 || [types count] == 0) {
|
||||
return NSDragOperationNone; // We cannot work with more than one type
|
||||
}
|
||||
|
||||
|
||||
id targetItem = [item representedObject];
|
||||
if( ![targetItem isKindOfClass:[KPKGroup class]] && ![targetItem isKindOfClass:[KPKEntry class]]) {
|
||||
return NSDragOperationNone; // Block all unknown types
|
||||
}
|
||||
MPDocument *document = [[[outlineView window] windowController] document];
|
||||
NSString *draggedType = [types lastObject];
|
||||
if([draggedType isEqualToString:MPGroupUTI]) {
|
||||
if([draggedType isEqualToString:KPKGroupUTI]) {
|
||||
// dragging group
|
||||
self.draggedEntry = nil;
|
||||
}
|
||||
else if([draggedType isEqualToString:MPUUIDUTI]) {
|
||||
NSArray *uuids = [pasteBoard readObjectsForClasses:@[[UUID class]] options:nil];
|
||||
else if([draggedType isEqualToString:KPKUUIDUTI]) {
|
||||
NSArray *uuids = [pasteBoard readObjectsForClasses:@[[NSUUID class]] options:nil];
|
||||
if([uuids count] != 1) {
|
||||
return NSDragOperationNone; // NO entry readable
|
||||
}
|
||||
@@ -79,7 +79,7 @@
|
||||
return NSDragOperationNone; // unkonw type
|
||||
}
|
||||
|
||||
KdbGroup *targetGroup = targetItem;
|
||||
KPKGroup *targetGroup = targetItem;
|
||||
BOOL validTarget = YES;
|
||||
if(self.draggedGroup) {
|
||||
if( self.draggedGroup == targetGroup ) {
|
||||
@@ -108,19 +108,19 @@
|
||||
}
|
||||
|
||||
id targetItem = [item representedObject];
|
||||
if(![targetItem isKindOfClass:[KdbGroup class]]) {
|
||||
if(![targetItem isKindOfClass:[KPKGroup class]]) {
|
||||
return NO; // Wrong
|
||||
}
|
||||
|
||||
KdbGroup *targetGroup = (KdbGroup *)targetItem;
|
||||
KPKGroup *targetGroup = (KPKGroup *)targetItem;
|
||||
|
||||
NSString *draggedType = [types lastObject];
|
||||
if([draggedType isEqualToString:MPGroupUTI]) {
|
||||
[self.draggedGroup moveToGroupUndoable:targetGroup atIndex:index];
|
||||
if([draggedType isEqualToString:KPKGroupUTI]) {
|
||||
[self.draggedGroup moveToGroup:targetGroup atIndex:index];
|
||||
return YES;
|
||||
}
|
||||
else if([draggedType isEqualToString:MPUUIDUTI]) {
|
||||
[self.draggedEntry moveToGroupUndoable:targetGroup atIndex:index];
|
||||
else if([draggedType isEqualToString:KPKUUIDUTI]) {
|
||||
[self.draggedEntry moveToGroup:targetGroup atIndex:index];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
APPKIT_EXTERN NSString *const MPOutlineViewDidChangeGroupSelection;
|
||||
|
||||
@class MPOutlineViewDelegate;
|
||||
@class KdbGroup;
|
||||
@class HNHGradientView;
|
||||
@class MPDocumentWindowController;
|
||||
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
#import "MPActionHelper.h"
|
||||
#import "MPIconHelper.h"
|
||||
#import "MPUppercaseStringValueTransformer.h"
|
||||
#import "MPRootAdapter.h"
|
||||
#import "MPNotifications.h"
|
||||
#import "MPOutlineContextMenuDelegate.h"
|
||||
|
||||
#import "KdbLib.h"
|
||||
#import "Kdb4Node.h"
|
||||
#import "KdbGroup+Undo.h"
|
||||
#import "KPKTree.h"
|
||||
#import "KPKGroup.h"
|
||||
#import "KPKNode+IconImage.h"
|
||||
#import "KPKMetaData.h"
|
||||
#import "KPKUTIs.h"
|
||||
|
||||
#import "HNHGradientView.h"
|
||||
|
||||
@@ -72,7 +73,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
[_outlineView setMenu:[self _contextMenu]];
|
||||
[_outlineView setAllowsEmptySelection:YES];
|
||||
[_outlineView setFloatsGroupRows:NO];
|
||||
[_outlineView registerForDraggedTypes:@[ MPGroupUTI, MPEntryUTI, MPUUIDUTI ]];
|
||||
[_outlineView registerForDraggedTypes:@[ KPKGroupUTI, KPKUUIDUTI ]];
|
||||
[_outlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
|
||||
[_bottomBar setBorderType:HNHBorderTop];
|
||||
[_addGroupButton setAction:[MPActionHelper actionOfType:MPActionAddGroup]];
|
||||
@@ -89,11 +90,9 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
if(!_bindingEstablished) {
|
||||
MPDocument *document = [[self windowController] document];
|
||||
[_treeController setChildrenKeyPath:@"groups"];
|
||||
[_treeController bind:NSContentBinding toObject:document withKeyPath:@"rootAdapter" options:nil];
|
||||
[_treeController bind:NSContentBinding toObject:document withKeyPath:@"tree" options:nil];
|
||||
[_outlineView bind:NSContentBinding toObject:_treeController withKeyPath:@"arrangedObjects" options:nil];
|
||||
if([document.tree respondsToSelector:@selector(databaseName)]) {
|
||||
[self bind:@"databaseNameWrapper" toObject:document.tree withKeyPath:@"databaseName" options:nil];
|
||||
}
|
||||
[self bind:@"databaseNameWrapper" toObject:document.tree.metaData withKeyPath:@"databaseName" options:nil];
|
||||
[_outlineView setDataSource:self.datasource];
|
||||
_bindingEstablished = YES;
|
||||
}
|
||||
@@ -103,7 +102,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
|
||||
- (void)_expandItems:(NSTreeNode *)node {
|
||||
id nodeItem = [node representedObject];
|
||||
if([nodeItem isKindOfClass:[MPRootAdapter class]]) {
|
||||
if([nodeItem isKindOfClass:[KPKTree class]]) {
|
||||
[self.outlineView expandItem:node expandChildren:NO];
|
||||
}
|
||||
else if([nodeItem respondsToSelector:@selector(isExpanded)]) {
|
||||
@@ -200,7 +199,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
#pragma mark Actions
|
||||
|
||||
- (void)createGroup:(id)sender {
|
||||
KdbGroup *group = [self _clickedOrSelectedGroup];
|
||||
KPKGroup *group = [self _clickedOrSelectedGroup];
|
||||
MPDocument *document = [[self windowController] document];
|
||||
if(!group) {
|
||||
group = document.root;
|
||||
@@ -220,17 +219,17 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
#pragma mark NSOutlineViewDelegate
|
||||
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
|
||||
NSTableCellView *view;
|
||||
if( [self _itemIsRootNodeAdapter:item] ) {
|
||||
if( [self _itemIsRootNode:item] ) {
|
||||
//NSDictionary *options = @{ NSValueTransformerBindingOption : [NSValueTransformer valueTransformerForName:MPUppsercaseStringValueTransformerName] };
|
||||
view = [outlineView makeViewWithIdentifier:_MPOutlinveViewHeaderViewIdentifier owner:self];
|
||||
[view.textField bind:NSValueBinding toObject:self withKeyPath:@"databaseNameWrapper" options:nil];
|
||||
}
|
||||
else {
|
||||
KdbGroup *group = [item representedObject];
|
||||
KPKGroup *group = [item representedObject];
|
||||
view = [outlineView makeViewWithIdentifier:_MPOutlineViewDataViewIdentifier owner:self];
|
||||
NSImage *icon = [MPIconHelper icon:(MPIconType)[group image]];
|
||||
[view.imageView setImage:icon];
|
||||
[view.textField bind:NSValueBinding toObject:group withKeyPath:MPGroupNameUndoableKey options:nil];
|
||||
|
||||
[view.imageView setImage:group.iconImage];
|
||||
[view.textField bind:NSValueBinding toObject:group withKeyPath:@"name" options:nil];
|
||||
[view.textField bind:@"count" toObject:group withKeyPath:@"entries.@count" options:nil];
|
||||
}
|
||||
|
||||
@@ -238,31 +237,31 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
|
||||
return [self _itemIsRootNodeAdapter:item];
|
||||
return [self _itemIsRootNode:item];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item {
|
||||
return ![self _itemIsRootNodeAdapter:item];
|
||||
return ![self _itemIsRootNode:item];
|
||||
}
|
||||
|
||||
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
|
||||
NSTreeNode *treeNode = [_outlineView itemAtRow:[_outlineView selectedRow]];
|
||||
KdbGroup *selectedGroup = [treeNode representedObject];
|
||||
KPKGroup *selectedGroup = [treeNode representedObject];
|
||||
MPDocument *document = [[self windowController] document];
|
||||
document.selectedGroup = selectedGroup;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
|
||||
return ![self _itemIsRootNodeAdapter:item];
|
||||
return ![self _itemIsRootNode:item];
|
||||
}
|
||||
|
||||
- (void)outlineViewItemDidExpand:(NSNotification *)notification {
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
id item = userInfo[@"NSObject"];
|
||||
id representedObject = [item representedObject];
|
||||
NSLog(@"expanded:%@",representedObject);
|
||||
if([representedObject isKindOfClass:[Kdb4Group class]]) {
|
||||
Kdb4Group *group = (Kdb4Group *)representedObject;
|
||||
if([representedObject isKindOfClass:[KPKGroup class]]) {
|
||||
NSLog(@"expanded:%@",representedObject);
|
||||
KPKGroup *group = (KPKGroup *)representedObject;
|
||||
group.isExpanded = YES;
|
||||
}
|
||||
}
|
||||
@@ -270,9 +269,9 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
NSDictionary *userInfo = [notification userInfo];
|
||||
id item = userInfo[@"NSObject"];
|
||||
id representedObject = [item representedObject];
|
||||
NSLog(@"collapsed:%@",representedObject);
|
||||
if([representedObject isKindOfClass:[Kdb4Group class]]) {
|
||||
Kdb4Group *group = (Kdb4Group *)representedObject;
|
||||
if([representedObject isKindOfClass:[KPKGroup class]]) {
|
||||
NSLog(@"collapsed:%@",representedObject);
|
||||
KPKGroup *group = (KPKGroup *)representedObject;
|
||||
group.isExpanded = NO;
|
||||
}
|
||||
}
|
||||
@@ -280,7 +279,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
#pragma mark -
|
||||
#pragma mark Private
|
||||
|
||||
- (KdbGroup *)_clickedOrSelectedGroup {
|
||||
- (KPKGroup *)_clickedOrSelectedGroup {
|
||||
NSInteger row = [self.outlineView clickedRow];
|
||||
if( row < 0 ) {
|
||||
row = [self.outlineView selectedRow];
|
||||
@@ -294,9 +293,9 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
||||
return menu;
|
||||
}
|
||||
|
||||
- (BOOL)_itemIsRootNodeAdapter:(id)item {
|
||||
- (BOOL)_itemIsRootNode:(id)item {
|
||||
id node = [item representedObject];
|
||||
return [node isKindOfClass:[MPRootAdapter class]];
|
||||
return [node isKindOfClass:[KPKTree class]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#import "NSString+Empty.h"
|
||||
#import "NSData+Keyfile.h"
|
||||
|
||||
#import "KPKTree.h"
|
||||
|
||||
@interface MPPasswordEditWindowController () {
|
||||
MPDocument * __unsafe_unretained _document;
|
||||
}
|
||||
@@ -93,7 +95,7 @@
|
||||
}
|
||||
|
||||
- (IBAction)generateKey:(id)sender {
|
||||
NSData *data = [NSData generateKeyfiledataForVersion:(KPKVersion)(_document.version + 1)];
|
||||
NSData *data = [NSData generateKeyfiledataForVersion:_document.tree.minimumVersion];
|
||||
if(data) {
|
||||
NSSavePanel *savePanel = [NSSavePanel savePanel];
|
||||
[savePanel setAllowedFileTypes:@[@"key", @"xml"]];
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// MPRootAdapter.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 26.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class KdbTree;
|
||||
|
||||
@interface MPRootAdapter : NSObject
|
||||
|
||||
@property (readonly, strong) NSArray *groups;
|
||||
@property (nonatomic, strong) KdbTree *tree;
|
||||
/* Subs to support interface */
|
||||
@property (weak, readonly, nonatomic) NSArray *entries;
|
||||
|
||||
@end
|
||||
@@ -1,36 +0,0 @@
|
||||
//
|
||||
// MPRootAdapter.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 26.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPRootAdapter.h"
|
||||
#import "Kdb.h"
|
||||
|
||||
@interface MPRootAdapter ()
|
||||
|
||||
@property (strong) NSArray *groups;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPRootAdapter
|
||||
|
||||
|
||||
- (void)setTree:(KdbTree *)tree {
|
||||
if(_tree != tree) {
|
||||
_tree = tree;
|
||||
if(_tree) {
|
||||
self.groups = @[_tree.root];
|
||||
}
|
||||
else {
|
||||
self.groups = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)entries {
|
||||
return nil;
|
||||
}
|
||||
@end
|
||||
@@ -9,6 +9,9 @@
|
||||
#import "MPSavePanelAccessoryViewController.h"
|
||||
#import "MPDocument.h"
|
||||
|
||||
#import "KPKUTIs.h"
|
||||
#import "KPKTree.h"
|
||||
|
||||
@interface MPSavePanelAccessoryViewController ()
|
||||
|
||||
@end
|
||||
@@ -42,7 +45,7 @@
|
||||
|
||||
- (IBAction)setFileType:(id)sender {
|
||||
NSString *uti = [[self.fileTypePopupButton selectedItem] representedObject];
|
||||
BOOL showInfoText = (self.document.version == MPDatabaseVersion4) && [uti isEqualToString:@"com.hicknhack.macpass.kdb"];
|
||||
BOOL showInfoText = (self.document.tree.minimumVersion == KPKLegacyVersion && [uti isEqualToString:@"com.hicknhack.macpass.kdb"]);
|
||||
[self.infoTextField setHidden:!showInfoText];
|
||||
[self.savePanel setAllowedFileTypes:@[uti]];
|
||||
}
|
||||
@@ -55,13 +58,16 @@
|
||||
}
|
||||
|
||||
- (void)_updateView {
|
||||
switch(self.document.version) {
|
||||
case MPDatabaseVersion3:
|
||||
switch(self.document.tree.minimumVersion) {
|
||||
case KPKLegacyVersion:
|
||||
[self.fileTypePopupButton selectItemAtIndex:1];
|
||||
break;
|
||||
case MPDatabaseVersion4:
|
||||
case KPKXmlVersion:
|
||||
[self.fileTypePopupButton selectItemAtIndex:0];
|
||||
break;
|
||||
case KPKUnknownVersion:
|
||||
NSAssert(NO, @"Minimum Version should always be valid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// StringField+Undo.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 28.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
APPKIT_EXTERN NSString *const MPStringFieldKeyUndoableKey;
|
||||
APPKIT_EXTERN NSString *const MPStringFieldValueUndoableKey;
|
||||
|
||||
@interface StringField (Undo)
|
||||
|
||||
|
||||
- (NSString *)keyUndoable;
|
||||
- (NSString *)valueUndoable;
|
||||
|
||||
- (void)setKeyUndoable:(NSString *)key;
|
||||
- (void)setValueUndoable:(NSString *)value;
|
||||
|
||||
@end
|
||||
@@ -1,44 +0,0 @@
|
||||
//
|
||||
// StringField+Undo.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 28.06.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "StringField+Undo.h"
|
||||
|
||||
NSString *const MPStringFieldKeyUndoableKey = @"keyUndoable";
|
||||
NSString *const MPStringFieldValueUndoableKey = @"valueUndoable";
|
||||
|
||||
@implementation StringField (Undo)
|
||||
|
||||
- (NSUndoManager *)undoManager {
|
||||
return [[[NSDocumentController sharedDocumentController] currentDocument] undoManager];
|
||||
}
|
||||
|
||||
- (NSString *)keyUndoable {
|
||||
return self.key;
|
||||
}
|
||||
|
||||
- (NSString *)valueUndoable {
|
||||
return self.value;
|
||||
}
|
||||
|
||||
- (void)setKeyUndoable:(NSString *)key {
|
||||
if(![self.key isEqualToString:key]) {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setKeyUndoable:) object:self.key];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_SET_STRINGFILED_KEY", @"Set StringField key")];
|
||||
self.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setValueUndoable:(NSString *)value {
|
||||
if(![self.value isEqualToString:value]) {
|
||||
[[self undoManager] registerUndoWithTarget:self selector:@selector(setValueUndoable:) object:self.value];
|
||||
[[self undoManager] setActionName:NSLocalizedString(@"UNDO_SET_STRINGFIELD_VALUE", @"Set StringField value")];
|
||||
self.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// StringField+Validation.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kdb4Node.h"
|
||||
|
||||
@interface StringField (Validation)
|
||||
|
||||
@end
|
||||
@@ -1,19 +0,0 @@
|
||||
//
|
||||
// StringField+Validation.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 19.07.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "StringField+Validation.h"
|
||||
#import "Kdb4Entry+MPAdditions.h"
|
||||
|
||||
@implementation StringField (Validation)
|
||||
|
||||
- (BOOL)validateValue:(inout __autoreleasing id *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing *)outError {
|
||||
*ioValue = [self.entry uniqueKeyForProposal:*ioValue];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// UUID+Pasterboard.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 04.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UUID.h"
|
||||
|
||||
@interface UUID (Pasterboard) <NSPasteboardReading, NSPasteboardWriting, NSCoding>
|
||||
|
||||
@end
|
||||
@@ -1,49 +0,0 @@
|
||||
//
|
||||
// UUID+Pasterboard.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 04.08.13.
|
||||
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UUID+Pasterboard.h"
|
||||
#import "MPConstants.h"
|
||||
|
||||
@implementation UUID (Pasterboard)
|
||||
|
||||
#pragma mark NSCoding
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
NSData *data = [aDecoder decodeObjectForKey:@"data"];
|
||||
self = [self initWithData:data];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeObject:[self getData] forKey:@"data"];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSPasteboardReading
|
||||
|
||||
+ (NSArray *)readableTypesForPasteboard:(NSPasteboard *)pasteboard {
|
||||
return @[ MPUUIDUTI ];
|
||||
}
|
||||
|
||||
+ (NSPasteboardReadingOptions)readingOptionsForType:(NSString *)type pasteboard:(NSPasteboard *)pasteboard {
|
||||
NSAssert([type isEqualToString:MPUUIDUTI], @"Only MPUUID type is supported");
|
||||
return NSPasteboardReadingAsKeyedArchive;
|
||||
}
|
||||
#pragma mark -
|
||||
#pragma mark NSPasteboardWriting
|
||||
|
||||
- (id)pasteboardPropertyListForType:(NSString *)type {
|
||||
NSAssert([type isEqualToString:MPUUIDUTI], @"Only MPUUID type is supported");
|
||||
return [NSKeyedArchiver archivedDataWithRootObject:self];
|
||||
}
|
||||
|
||||
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
|
||||
return @[ MPUUIDUTI ];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user