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:
michael starke
2013-09-01 02:16:27 +02:00
parent 319d165141
commit 5e4254b45f
70 changed files with 498 additions and 2521 deletions

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:)

View File

@@ -9,9 +9,6 @@
#import "MPAttachmentTableDataSource.h"
#import "MPDocument.h"
#import "Kdb3Entry+KVOAdditions.h"
#import "Kdb4Entry+KVOAdditions.h"
@implementation MPAttachmentTableDataSource
- (NSDragOperation)tableView:(NSTableView *)tableView

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -14,9 +14,6 @@
@class MPPasswordInputController;
@class MPOutlineViewController;
@class KdbGroup;
@class KdbEntry;
@interface MPDocumentWindowController : NSWindowController
@property (readonly, strong) MPPasswordInputController *passwordInputController;

View File

@@ -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);
}

View File

@@ -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")];
}

View File

@@ -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];
}
}

View File

@@ -8,7 +8,6 @@
#import "MPViewController.h"
@class KdbEntry;
@class HNHRoundedSecureTextField;
@class MPDocument;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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];
}

View File

@@ -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];

View File

@@ -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];

View File

@@ -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];
}

View File

@@ -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;

View File

@@ -11,7 +11,6 @@
APPKIT_EXTERN NSString *const MPOutlineViewDidChangeGroupSelection;
@class MPOutlineViewDelegate;
@class KdbGroup;
@class HNHGradientView;
@class MPDocumentWindowController;

View File

@@ -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

View File

@@ -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"]];

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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