Restrucutred Settings and extracts Password edit

Introduced custom save palen accessory view to enable save in different formats (unfunctional for now)
Started reworking drag and drop of entries and groups
This commit is contained in:
michael starke
2013-08-11 17:58:39 +02:00
parent 116b3b3253
commit 86e97ad767
22 changed files with 2919 additions and 1559 deletions

View File

@@ -11,7 +11,12 @@
4C01C2421764D8980016D5D0 /* MPContextMenuHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C01C2411764D8980016D5D0 /* MPContextMenuHelper.m */; };
4C01C245176500C40016D5D0 /* HNHLevelIndicatorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C01C244176500C40016D5D0 /* HNHLevelIndicatorCell.m */; };
4C055E74179620BF00BD2BAB /* NSString+CommandString.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C055E73179620BF00BD2BAB /* NSString+CommandString.m */; };
4C0728BA17B5B7A4005A7DD9 /* PasswordEditWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C0728B917B5B7A4005A7DD9 /* PasswordEditWindow.xib */; };
4C0728BD17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0728BC17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m */; };
4C0728BF17B68ED0005A7DD9 /* SavePanelAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C0728BE17B68ED0005A7DD9 /* SavePanelAccessoryView.xib */; };
4C08C3AE17B3022400BBBC95 /* KPKLegacyHeaderWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C08C3AD17B3022400BBBC95 /* KPKLegacyHeaderWriter.m */; };
4C0F647817B6B65E00D9522A /* MPSheetWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0F647717B6B65E00D9522A /* MPSheetWindowController.m */; };
4C0F647B17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */; };
4C10412C178CDD44001B5239 /* NSDate+Humanized.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C10412B178CDD44001B5239 /* NSDate+Humanized.m */; };
4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C17D8E417A1C780006C8C1E /* MPDocumentWindowDelegate.m */; };
4C1842AB179B027800E2F5BC /* KPKDeletedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1842AA179B027800E2F5BC /* KPKDeletedNode.m */; };
@@ -292,9 +297,17 @@
4C01C244176500C40016D5D0 /* HNHLevelIndicatorCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHLevelIndicatorCell.m; sourceTree = "<group>"; };
4C055E72179620BF00BD2BAB /* NSString+CommandString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+CommandString.h"; sourceTree = "<group>"; };
4C055E73179620BF00BD2BAB /* NSString+CommandString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+CommandString.m"; sourceTree = "<group>"; };
4C0728B917B5B7A4005A7DD9 /* PasswordEditWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordEditWindow.xib; sourceTree = "<group>"; };
4C0728BB17B5B7F7005A7DD9 /* MPPasswordEditWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordEditWindowController.h; sourceTree = "<group>"; };
4C0728BC17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordEditWindowController.m; sourceTree = "<group>"; };
4C0728BE17B68ED0005A7DD9 /* SavePanelAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SavePanelAccessoryView.xib; sourceTree = "<group>"; };
4C08C3AC17B3022400BBBC95 /* KPKLegacyHeaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KPKLegacyHeaderWriter.h; sourceTree = "<group>"; };
4C08C3AD17B3022400BBBC95 /* KPKLegacyHeaderWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KPKLegacyHeaderWriter.m; sourceTree = "<group>"; };
4C08C3AF17B3036500BBBC95 /* KPKLegacyFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = KPKLegacyFormat.h; path = Format/KPKLegacyFormat.h; sourceTree = "<group>"; };
4C0F647617B6B65E00D9522A /* MPSheetWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSheetWindowController.h; sourceTree = "<group>"; };
4C0F647717B6B65E00D9522A /* MPSheetWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSheetWindowController.m; sourceTree = "<group>"; };
4C0F647917B6BC9C00D9522A /* MPSavePanelAccessoryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSavePanelAccessoryViewController.h; sourceTree = "<group>"; };
4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSavePanelAccessoryViewController.m; sourceTree = "<group>"; };
4C10412A178CDD44001B5239 /* NSDate+Humanized.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+Humanized.h"; sourceTree = "<group>"; };
4C10412B178CDD44001B5239 /* NSDate+Humanized.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+Humanized.m"; sourceTree = "<group>"; };
4C13904C17ADD1A300A62934 /* KPKTreeCrypting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKTreeCrypting.h; sourceTree = "<group>"; };
@@ -750,7 +763,6 @@
4CD884B615BD47080042BBF8 /* DocumentWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DocumentWindow.xib; sourceTree = "<group>"; };
4CDB5C401794AA4F0017667E /* KPKTree+Serializing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPKTree+Serializing.h"; sourceTree = "<group>"; };
4CDB5C411794AA4F0017667E /* KPKTree+Serializing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "KPKTree+Serializing.m"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
4CDE28D0179C8E010036C771 /* MPDatabaseSettingsDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPDatabaseSettingsDelegate.h; sourceTree = "<group>"; };
4CDF01A116D1B76700D0AC08 /* MPEntryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntryViewController.h; sourceTree = "<group>"; };
4CDF01A216D1B76700D0AC08 /* MPEntryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEntryViewController.m; sourceTree = "<group>"; };
4CE298E91795FC2A00DF7BDB /* MPEntryContextMenuDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEntryContextMenuDelegate.h; sourceTree = "<group>"; };
@@ -848,6 +860,7 @@
4CE39AC016ECE359000FE29D /* IconSelection.xib */,
4C2C8B331787500E009649F3 /* UnprotectedWarningView.xib */,
4C4B7EE817A45EC5000234C7 /* DatePickingView.xib */,
4C0728BE17B68ED0005A7DD9 /* SavePanelAccessoryView.xib */,
4C74DD05177BD1640034A9DB /* MPCustomFieldView.h */,
4C74DD06177BD1640034A9DB /* MPCustomFieldView.m */,
4CE8247316E2F2B900573141 /* MPOverlayView.h */,
@@ -1458,14 +1471,14 @@
4CA0B2F115BCAEE600654E32 /* View Controller */ = {
isa = PBXGroup;
children = (
4C2E382416D1470200037A9D /* MPViewController.h */,
4C2E382516D1470200037A9D /* MPViewController.m */,
4CA0B2F715BCAF6700654E32 /* MPGeneralSettingsController.h */,
4CA0B2F815BCAF6700654E32 /* MPGeneralSettingsController.m */,
4CF78062176E75AD0032EE71 /* MPServerSettingsController.h */,
4CF78063176E75AD0032EE71 /* MPServerSettingsController.m */,
4CD7223917A7CB0700F5A1E1 /* MPWorkflowSettingsController.h */,
4CD7223A17A7CB0700F5A1E1 /* MPWorkflowSettingsController.m */,
4C2E382416D1470200037A9D /* MPViewController.h */,
4C2E382516D1470200037A9D /* MPViewController.m */,
4C65FAE616D16DDB006E0577 /* MPPasswordInputController.h */,
4C65FAE716D16DDB006E0577 /* MPPasswordInputController.m */,
4C5A11FB1708DE8700223D8A /* MPPasswordCreatorViewController.h */,
@@ -1484,6 +1497,8 @@
4C4B7EEC17A467E1000234C7 /* MPGroupInspectorViewController.m */,
4C4B7EF017A467FC000234C7 /* MPEntryInspectorViewController.h */,
4C4B7EF117A467FC000234C7 /* MPEntryInspectorViewController.m */,
4C0F647917B6BC9C00D9522A /* MPSavePanelAccessoryViewController.h */,
4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */,
);
name = "View Controller";
sourceTree = "<group>";
@@ -1493,7 +1508,6 @@
children = (
4CF6C715176F5183007A811D /* MPServerRequestHandler.h */,
4CA0B30D15BCB6FD00654E32 /* MPSettingsTab.h */,
4CDE28D0179C8E010036C771 /* MPDatabaseSettingsDelegate.h */,
);
name = Protocolls;
sourceTree = "<group>";
@@ -1702,6 +1716,8 @@
4CE8247016E2E96500573141 /* Window Controller */ = {
isa = PBXGroup;
children = (
4C0F647617B6B65E00D9522A /* MPSheetWindowController.h */,
4C0F647717B6B65E00D9522A /* MPSheetWindowController.m */,
4CA0B2FA15BCAF8600654E32 /* MPSettingsWindowController.h */,
4CA0B2FB15BCAF8600654E32 /* MPSettingsWindowController.m */,
4C83814015BF4677001AE468 /* MPDocumentWindowController.h */,
@@ -1710,6 +1726,8 @@
4CE8246E16E2E93400573141 /* MPOverlayWindowController.m */,
4CD5D703177A5F3300100649 /* MPDatabaseSettingsWindowController.h */,
4CD5D704177A5F3300100649 /* MPDatabaseSettingsWindowController.m */,
4C0728BB17B5B7F7005A7DD9 /* MPPasswordEditWindowController.h */,
4C0728BC17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m */,
);
name = "Window Controller";
sourceTree = "<group>";
@@ -1731,6 +1749,7 @@
4C431BCE16E2BAB000700A81 /* OverlayWindow.xib */,
4C1DDCDC1711ECEB00C98DA3 /* PasswordCreatorWindow.xib */,
4CD5D701177A5EE400100649 /* DatabaseSettingsWindow.xib */,
4C0728B917B5B7A4005A7DD9 /* PasswordEditWindow.xib */,
);
name = Windows;
sourceTree = "<group>";
@@ -1891,6 +1910,8 @@
4C4B7EEF17A467E1000234C7 /* GroupInspectorView.xib in Resources */,
4C4B7EF417A467FC000234C7 /* EntryInspectorView.xib in Resources */,
4CD7223817A7C9EA00F5A1E1 /* WorkflowSettings.xib in Resources */,
4C0728BA17B5B7A4005A7DD9 /* PasswordEditWindow.xib in Resources */,
4C0728BF17B68ED0005A7DD9 /* SavePanelAccessoryView.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2136,6 +2157,9 @@
4CF4FEE017AEA4A400712774 /* UUID+Pasterboard.m in Sources */,
4C6366AC17AF1E0100AAF17D /* NSColor+KeePassKit.m in Sources */,
4C08C3AE17B3022400BBBC95 /* KPKLegacyHeaderWriter.m in Sources */,
4C0728BD17B5B7F7005A7DD9 /* MPPasswordEditWindowController.m in Sources */,
4C0F647817B6B65E00D9522A /* MPSheetWindowController.m in Sources */,
4C0F647B17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
//
// MPDatabaseSettingsDelegate.h
// MacPass
//
// Created by Michael Starke on 21.07.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol MPDatabaseSettingsDelegate <NSObject>
@optional
- (void)didCancelDatabaseSettings;
- (void)didSaveDatabaseSettings;
@end

View File

@@ -7,11 +7,10 @@
//
#import <Cocoa/Cocoa.h>
#import "MPDatabaseSettingsDelegate.h"
#import "MPSheetWindowController.h"
typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
MPDatabaseSettingsTabGeneral,
MPDatabaseSettingsTabPassword,
MPDatabaseSettingsTabDisplay,
MPDatabaseSettingsTabAdvanced,
MPDatabaseSettingsTabTemplates,
@@ -19,31 +18,15 @@ typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
@class MPDocument;
@class HNHRoundedTextField;
@class HNHRoundedSecureTextField;
@interface MPDatabaseSettingsWindowController : NSWindowController <NSTextFieldDelegate, NSTabViewDelegate>
@property (nonatomic,weak) id<MPDatabaseSettingsDelegate> delegate;
@interface MPDatabaseSettingsWindowController : MPSheetWindowController <NSTextFieldDelegate, NSTabViewDelegate>
@property (weak) IBOutlet NSTabView *sectionTabView;
@property (weak) IBOutlet NSButton *saveButton;
@property (weak) IBOutlet NSButton *cancelButton;
/* General Tab */
@property (weak) IBOutlet NSTextField *databaseNameTextField;
@property (unsafe_unretained) IBOutlet NSTextView *databaseDescriptionTextView;
/* Protection */
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordRepeatTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
@property (weak) IBOutlet NSButton *togglePasswordButton;
@property (weak) IBOutlet NSTextField *errorTextField;
- (IBAction)clearKey:(id)sender;
- (IBAction)generateKey:(id)sender;
/* Display Tab */
@property (weak) IBOutlet NSButton *protectTitleCheckButton;
@property (weak) IBOutlet NSButton *protectUserNameCheckButton;
@@ -66,9 +49,6 @@ typedef NS_ENUM(NSUInteger, MPDatabaseSettingsTab) {
- (void)showSettingsTab:(MPDatabaseSettingsTab)tab;
- (void)update;
@end

View File

@@ -26,26 +26,21 @@
MPDocument *_document;
NSString *_missingFeature;
}
@property (nonatomic,assign) BOOL trashEnabled;
@property (nonatomic,assign) BOOL showPassword;
@property (nonatomic,assign) BOOL hasValidPasswordOrKey;
@property (nonatomic,weak) NSURL *keyURL;
@end
@implementation MPDatabaseSettingsWindowController
- (id)init {
return [self initWithDocument:nil];
self = [self initWithDocument:nil];
return self;
}
- (id)initWithDocument:(MPDocument *)document {
self = [super initWithWindowNibName:@"DatabaseSettingsWindow"];
if(self) {
_document = document;
_showPassword = NO;
_hasValidPasswordOrKey = NO;
_missingFeature = NSLocalizedString(@"KDBX_ONLY_FEATURE", "Feature only available in kdbx databases");
}
return self;
@@ -56,31 +51,10 @@
NSAssert(_document != nil, @"Document needs to be present");
[self.saveButton bind:NSEnabledBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.sectionTabView setDelegate:self];
[self update];
}
- (void)setDelegate:(id<MPDatabaseSettingsDelegate>)delegate {
if(_delegate != delegate) {
if([delegate conformsToProtocol:@protocol(MPDatabaseSettingsDelegate)]) {
_delegate = delegate;
}
else{
NSAssert(NO, @"Delegate needs to conform to MPDatabaseSettingsDelegate protocoll");
}
}
}
- (IBAction)save:(id)sender {
/* Protection */
_document.password = [self.passwordTextField stringValue];
_document.key = [self.keyfilePathControl URL];
/* General */
_document.treeV4.databaseDescription = [self.databaseDescriptionTextView string];
_document.treeV4.databaseName = [self.databaseNameTextField stringValue];
@@ -121,37 +95,25 @@
[defaults setBool:protectUsername forKey:kMPSettingsKeyLegacyHideUsername];
[defaults synchronize];
}
[self closeDidSave:YES];
[self close:nil];
}
- (IBAction)cancel:(id)sender {
[self closeDidSave:NO];
}
- (void)closeDidSave:(BOOL)didSave {
/* Remove the window first */
- (IBAction)close:(id)sender {
[NSApp endSheet:[self window]];
[[self window] orderOut:nil];
/* Then notify the delegate */
if(self.delegate) {
if(didSave && [self.delegate respondsToSelector:@selector(didSaveDatabaseSettings)]) {
[self.delegate didSaveDatabaseSettings];
}
else if(!didSave && [self.delegate respondsToSelector:@selector(didCancelDatabaseSettings)]) {
[self.delegate didCancelDatabaseSettings];
}
}
}
- (void)update {
- (void)updateView {
if(!self.isDirty) {
return;
}
/* Update all stuff that might have changed */
Kdb4Tree *tree = _document.treeV4;
[self _setupPasswordTab:tree];
[self _setupDatabase:tree];
[self _setupProtectionTab:tree];
[self _setupAdvancedTab:tree];
[self _setupTemplatesTab:tree];
self.isDirty = NO;
}
- (void)showSettingsTab:(MPDatabaseSettingsTab)tab {
@@ -162,47 +124,18 @@
if(![self window]) {
return;
}
self.showPassword = NO;
NSTabViewItem *tabViewItem = [self.sectionTabView tabViewItemAtIndex:tab];
BOOL canSelectTab = [self tabView:self.sectionTabView shouldSelectTabViewItem:tabViewItem];
if(!canSelectTab) {
[self.sectionTabView selectTabViewItemAtIndex:MPDatabaseSettingsTabPassword];
[self.sectionTabView selectTabViewItemAtIndex:MPDatabaseSettingsTabTemplates];
}
[self.sectionTabView selectTabViewItemAtIndex:tab];
}
- (void)setShowPassword:(BOOL)showPassword {
if(_showPassword != showPassword) {
_showPassword = showPassword;
[self.passwordRepeatTextField setStringValue:@""];
[self _verifyPasswordAndKey];
}
}
- (void)setKeyURL:(NSURL *)keyURL {
_keyURL = keyURL;
[self _verifyPasswordAndKey];
}
#pragma mark Actions
- (IBAction)clearKey:(id)sender {
self.keyURL = nil;
}
- (IBAction)generateKey:(id)sender {
}
#pragma mark NSTextFieldDelegate
- (void)controlTextDidChange:(NSNotification *)obj {
[self _verifyPasswordAndKey];
}
#pragma mark NSTableViewDelegate
- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem {
NSUInteger index = [tabView indexOfTabViewItem:tabViewItem];
switch ((MPDatabaseSettingsTab)index) {
case MPDatabaseSettingsTabPassword:
case MPDatabaseSettingsTabDisplay:
return YES;
@@ -217,40 +150,6 @@
}
#pragma mark Private Helper
- (void)_verifyPasswordAndKey {
NSString *password = [self.passwordTextField stringValue];
NSString *repeat = [self.passwordRepeatTextField stringValue];
BOOL hasKey = (self.keyURL != nil);
BOOL keyOk = YES;
if(hasKey) {
keyOk = [self.keyURL checkResourceIsReachableAndReturnError:nil];
}
BOOL hasPassword = ![NSString isEmptyString:password];
BOOL passwordOk = YES;
if(hasPassword ) {
passwordOk = [password isEqualToString:repeat] || self.showPassword;
}
BOOL hasPasswordOrKey = (hasKey || hasPassword);
keyOk = hasKey ? keyOk : YES;
passwordOk = hasPassword ? passwordOk : YES;
self.hasValidPasswordOrKey = hasPasswordOrKey && passwordOk && keyOk;
if(!hasPasswordOrKey) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_NO_PASSWORD_OR_KEYFILE", "Missing Key or Password")];
return; // alldone
}
if(!passwordOk && !keyOk ) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH_INVALID_KEYFILE", "Passwords do not match, keyfile is invalid")];
}
else if(!passwordOk) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match")];
}
else {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_INVALID_KEYFILE", "Keyfile not valid")];
}
}
- (void)_setupDatabase:(Kdb4Tree *)tree {
BOOL isKdbx = (nil != tree);
[self.databaseDescriptionTextView setEditable:isKdbx];
@@ -296,25 +195,6 @@
}
}
- (void)_setupPasswordTab:(Kdb4Tree *)tree {
[self.passwordTextField setStringValue:_document.password ? _document.password : @""];
[self.passwordRepeatTextField setStringValue:[self.passwordTextField stringValue]];
self.keyURL = _document.key;
NSDictionary *negateOption = @{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName };
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
[self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:@"showPassword" options:negateOption];
[self.errorTextField bind:NSHiddenBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:@"keyURL" options:nil];
[self.passwordRepeatTextField setDelegate:self];
[self.passwordTextField setDelegate:self];
/* Manually initate the first check */
[self _verifyPasswordAndKey];
}
- (void)_setupTemplatesTab:(Kdb4Tree *)tree {
if(tree) {
[self.defaultUsernameTextField setStringValue:tree.defaultUserName];
@@ -344,10 +224,6 @@
[[self window] makeFirstResponder:self.databaseNameTextField];
break;
case MPDatabaseSettingsTabPassword:
[[self window] makeFirstResponder:self.passwordTextField];
break;
case MPDatabaseSettingsTabTemplates:
break;
}

View File

@@ -11,14 +11,11 @@
APPKIT_EXTERN NSString *const MPDocumentDidAddGroupNotification;
APPKIT_EXTERN NSString *const MPDocumentDidAddEntryNotification;
APPKIT_EXTERN NSString *const MPDocumentDidRevertNotifiation;
APPKIT_EXTERN NSString *const MPDocumentEntryKey;
APPKIT_EXTERN NSString *const MPDocumentGroupKey;
APPKIT_EXTERN NSString *const MPDocumentRequestPasswordSaveNotification;
/*
APPKIT_EXTERN NSString *const MPDocumentDidChangeCurrentItemNotification;
APPKIT_EXTERN NSString *const MPDocumentDidChangeCurrentGroupNotication;
@@ -96,10 +93,6 @@ APPKIT_EXTERN NSString *const MPDocumnetDidChangeCurrentEntryNotification;
- (KdbEntry *)createEntry:(KdbGroup *)parent;
- (StringField *)createStringField:(KdbEntry *)entry;
/*
All non-setter undoable actions
*/
/* TODO in UNDO auslagen */
- (void)addStringField:(StringField *)field toEntry:(Kdb4Entry *)entry atIndex:(NSUInteger)index;
- (void)removeStringField:(StringField *)field formEntry:(Kdb4Entry *)entry;

View File

@@ -8,13 +8,13 @@
#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"
@@ -35,14 +35,13 @@
#import "KdbGroup+MPAdditions.h"
#import "DataOutputStream.h"
#import "DDXMLNode.h"
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentDidAddEntryNotification = @"com.hicknhack.macpass.MPDocumentDidAddEntryNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
NSString *const MPDocumentRequestPasswordSaveNotification = @"com.hicknhack.macpass.MPDocumentRequestPasswordSaveNotification";
#import "KPKTree+Serializing.h"
#import "KPKPassword.h"
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";
NSString *const MPDocumentEntryKey = @"MPDocumentEntryKey";
NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
@@ -58,6 +57,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
NSData *_fileData;
}
@property (strong, nonatomic) MPSavePanelAccessoryViewController *savePanelViewController;
@property (strong, nonatomic) KdbTree *tree;
@property (weak, nonatomic) KdbGroup *root;
@@ -79,8 +79,11 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
@implementation MPDocument
- (id)init
{
+ (BOOL)autosavesInPlace {
return NO;
}
- (id)init {
return [self initWithVersion:MPDatabaseVersion4];
}
#pragma mark NSDocument essentials
@@ -127,6 +130,9 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
/*
Move this to data:ofType: method with KeePassKit
*/
NSError *error = nil;
[KdbWriterFactory persist:self.tree fileURL:url withPassword:self.passwordHash error:&error];
if(error) {
@@ -137,7 +143,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
/* FIXME: Logfile handling
/* FIXME: Lockfile handling
self.lockFileURL = [url URLByAppendingPathExtension:@"lock"];
if([[NSFileManager defaultManager] fileExistsAtPath:[_lockFileURL path]]) {
self.readOnly = YES;
@@ -182,6 +188,26 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
[super close];
}
- (BOOL)shouldRunSavePanelWithAccessoryView {
return NO;
}
- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel {
/*
Save as different format doesn work with out 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];
@@ -192,6 +218,10 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
#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;
@@ -218,9 +248,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
self.locked = YES;
}
#pragma mark Custom Setter
- (void)setPassword:(NSString *)password {
if(![_password isEqualToString:password]) {
_password = [password copy];
@@ -236,32 +264,9 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
- (KdbPassword *)passwordHash {
return [[KdbPassword alloc] initWithPassword:self.password passwordEncoding:NSUTF8StringEncoding keyFileURL:self.key];
}
+ (BOOL)autosavesInPlace
{
return NO;
}
- (void)saveDocument:(id)sender {
if(self.hasPasswordOrKey) {
[super saveDocument:sender];
}
else {
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentRequestPasswordSaveNotification object:self userInfo:nil];
}
}
- (BOOL)prepareSavePanel:(NSSavePanel *)savePanel {
if(self.hasPasswordOrKey) {
[savePanel setAccessoryView:nil];
return YES;
}
return NO;
}
- (void)setSelectedGroup:(KdbGroup *)selectedGroup {
if(_selectedGroup != selectedGroup) {
_selectedGroup = selectedGroup;
@@ -417,8 +422,6 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
newEntry.title = self.treeV4.defaultUserName;
}
[parent addEntryUndoable:newEntry atIndex:[parent.entries count]];
NSDictionary *userInfo = @{ MPDocumentEntryKey : newEntry };
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidAddEntryNotification object:self userInfo:userInfo];
return newEntry;
}
@@ -442,7 +445,6 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
- (StringField *)createStringField:(KdbEntry *)entry {
// TODO: Localize!
if(![entry isKindOfClass:[Kdb4Entry class]]) {
return nil;
}
@@ -487,7 +489,6 @@ typedef NS_ENUM(NSUInteger, MPAlertType) {
}
#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")];

View File

@@ -7,7 +7,6 @@
//
#import <Cocoa/Cocoa.h>
#import "MPDatabaseSettingsDelegate.h"
@class MPViewController;
@class MPEntryViewController;
@@ -18,7 +17,7 @@
@class KdbGroup;
@class KdbEntry;
@interface MPDocumentWindowController : NSWindowController <MPDatabaseSettingsDelegate>
@interface MPDocumentWindowController : NSWindowController
@property (readonly, strong) MPPasswordInputController *passwordInputController;
@property (readonly, strong) MPEntryViewController *entryViewController;
@@ -36,6 +35,8 @@
- (void)showPasswordInput;
- (void)performFindPanelAction:(id)sender;
- (IBAction)saveDocument:(id)sender;
- (IBAction)editPassword:(id)sender;
- (IBAction)showDatabaseSettings:(id)sender;
- (IBAction)editTemplateGroup:(id)sender;

View File

@@ -16,6 +16,7 @@
#import "MPAppDelegate.h"
#import "MPActionHelper.h"
#import "MPDatabaseSettingsWindowController.h"
#import "MPPasswordEditWindowController.h"
#import "MPConstants.h"
#import "MPSettingsHelper.h"
#import "MPDocumentWindowDelegate.h"
@@ -25,7 +26,6 @@
@interface MPDocumentWindowController () {
@private
id _firstResponder;
BOOL _saveAfterPasswordEdit; // Flag to indicat that the document needs to be saved after password edit did finish
}
@property (strong) IBOutlet NSSplitView *splitView;
@@ -38,6 +38,7 @@
@property (strong) MPInspectorViewController *inspectorViewController;
@property (strong) MPDatabaseSettingsWindowController *documentSettingsWindowController;
@property (strong) MPDocumentWindowDelegate *documentWindowDelegate;
@property (strong) MPPasswordEditWindowController *passwordEditWindowController;
@property (strong) MPToolbarDelegate *toolbarDelegate;
@@ -54,7 +55,6 @@
_entryViewController = [[MPEntryViewController alloc] init];
_inspectorViewController = [[MPInspectorViewController alloc] init];
_documentWindowDelegate = [[MPDocumentWindowDelegate alloc] init];
_saveAfterPasswordEdit = NO;
}
return self;
}
@@ -76,7 +76,6 @@
*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didRevertDocument:) name:MPDocumentDidRevertNotifiation object:[self document]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_setPasswordAndSave) name:MPDocumentRequestPasswordSaveNotification object:[self document]];
[_entryViewController setupNotifications:self];
[_inspectorViewController setupNotifications:self];
@@ -156,6 +155,13 @@
}
#pragma mark Actions
- (void)saveDocument:(id)sender {
MPDocument *document = [self document];
if(!document.hasPasswordOrKey) {
// warning if no password ist set!
}
[[self document] saveDocument:sender];
}
- (void)exportDatabase:(id)sender {
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setAllowsOtherFileTypes:YES];
@@ -255,7 +261,10 @@
}
- (void)editPassword:(id)sender {
[self _showDatabaseSetting:MPDatabaseSettingsTabPassword];
if(!self.passwordEditWindowController) {
self.passwordEditWindowController = [[MPPasswordEditWindowController alloc] initWithDocument:[self document]];
}
[NSApp beginSheet:[self.passwordEditWindowController window] modalForWindow:[self window] modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
}
- (void)showDatabaseSettings:(id)sender {
@@ -375,31 +384,11 @@
[_outlineViewController showOutline];
}
#pragma mark MPDatabaseSettingsDelegate
- (void)didCancelDatabaseSettings {
_saveAfterPasswordEdit = NO; // Just Reset the flag
}
- (void)didSaveDatabaseSettings {
if (_saveAfterPasswordEdit) {
_saveAfterPasswordEdit = NO;
[[self document] saveDocument:nil];
}
}
#pragma mark Helper
- (void)_setPasswordAndSave {
_saveAfterPasswordEdit = YES;
[self editPassword:nil];
}
- (void)_showDatabaseSetting:(MPDatabaseSettingsTab)tab {
if(!self.documentSettingsWindowController) {
_documentSettingsWindowController = [[MPDatabaseSettingsWindowController alloc] initWithDocument:[self document]];
[_documentSettingsWindowController setDelegate:self];
}
[self.documentSettingsWindowController update];
[self.documentSettingsWindowController showSettingsTab:tab];
[[NSApplication sharedApplication] beginSheet:[self.documentSettingsWindowController window]
modalForWindow:[self window]

View File

@@ -23,6 +23,7 @@
@interface MPOutlineDataSource ()
@property (weak) KdbGroup *draggedGroup;
@property (weak) KdbEntry *draggedEntry;
@end
@@ -40,75 +41,97 @@
}
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id<NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index {
/* info.animatesToDestination = YES;
NSDragOperation oprationMask = NSDragOperationMove;
if([info draggingSourceOperationMask] == NSDragOperationCopy) {
oprationMask = NSDragOperationCopy;
}
info.animatesToDestination = YES;
NSDragOperation oprationMask = NSDragOperationMove;
/*
If we can support copy on drag, this can be used
to optain the dragging modifier mask the user presses
if([info draggingSourceOperationMask] == NSDragOperationCopy) {
oprationMask = NSDragOperationCopy;
}
*/
id targetItem = [item representedObject];
if(targetItem == nil) {
return NSDragOperationNone; // no Target
}
id targetItem = [item representedObject];
if(targetItem == nil) {
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
}
MPDocument *document = [[[outlineView window] windowController] document];
NSString *draggedType = [types lastObject];
if([draggedType isEqualToString:MPGroupUTI]) {
// dragging group
self.draggedEntry = nil;
}
else if([draggedType isEqualToString:MPUUIDUTI]) {
NSArray *uuids = [pasteBoard readObjectsForClasses:@[[UUID class]] options:nil];
if([uuids count] != 1) {
return NSDragOperationNone; // NO entry readable
}
if([targetItem isKindOfClass:[MPRootAdapter class]]) {
return NSDragOperationNone; // Drag over group header
}
KdbGroup *targetGroup = targetItem;
BOOL validTarget = YES;
self.draggedEntry = [document findEntry:[uuids lastObject]];
}
else {
return NSDragOperationNone; // unkonw type
}
if(self.draggedGroup && [targetItem isKindOfClass:[MPRootAdapter class]]) {
return NSDragOperationNone; // Drag over group header
}
KdbGroup *targetGroup = targetItem;
BOOL validTarget = YES;
if(self.draggedGroup) {
NSLog(@"draggin Group %@", self.draggedGroup.name);
if( self.draggedGroup.parent == targetGroup ) {
validTarget &= index != NSOutlineViewDropOnItemIndex;
validTarget &= index != [self.draggedGroup.parent.groups indexOfObject:self.draggedGroup];
}
if( validTarget ) {
return oprationMask;
}
}
NSPasteboard *pasteBoard = [info draggingPasteboard];
NSArray *items = [pasteBoard pasteboardItems];
if([items count] > 0) {
if( index != NSOutlineViewDropOnItemIndex ) {
[outlineView setDropItem:item dropChildIndex:NSOutlineViewDropOnItemIndex];
}
return NSDragOperationMove;
}*/
self.draggedGroup = nil;
return NSDragOperationNone;
else if(self.draggedEntry) {
NSLog(@"draggin Entry %@", self.draggedEntry.title);
validTarget = self.draggedEntry.parent != targetGroup;
}
return validTarget ? oprationMask : NSDragOperationNone;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id<NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index {
self.draggedGroup = nil;
/*
KdbGroup *target = [item representedObject];
if(self.draggedGroup) {
BOOL accepted = YES;
if( self.draggedGroup.parent == target ) {
accepted &= index != NSOutlineViewDropOnItemIndex;
accepted &= index != [self.draggedGroup.parent.groups indexOfObject:self.draggedGroup];
}
accepted = ![self.draggedGroup isAnchestorOfGroup:target];
if( accepted ) {
[self.draggedGroup moveToGroupUndoable:target atIndex:index];
}
info.animatesToDestination = !accepted;
self.draggedGroup = nil;
return accepted;
}
NSPasteboard *pasteBoard = [info draggingPasteboard];
NSArray *items = [pasteBoard pasteboardItems];
if([items count] > 0) {
NSPasteboardItem *item = items[0];
UUID *uuid = [[UUID alloc] initWithString:[item stringForType:MPPasteBoardType]];
MPDocument *document = [[[outlineView window] windowController] document];
KdbGroup *rootGroup = [document root];
KdbEntry *draggedEntry = [rootGroup entryForUUID:uuid];
if(draggedEntry) {
if(draggedEntry.parent != target && index == NSOutlineViewDropOnItemIndex) {
[draggedEntry moveToGroupUndoable:target atIndex:index];
return YES;
}
}
}
*/
if(self.draggedGroup) {
BOOL accepted = YES;
if( self.draggedGroup.parent == target ) {
accepted &= index != NSOutlineViewDropOnItemIndex;
accepted &= index != [self.draggedGroup.parent.groups indexOfObject:self.draggedGroup];
}
accepted = ![self.draggedGroup isAnchestorOfGroup:target];
if( accepted ) {
[self.draggedGroup moveToGroupUndoable:target atIndex:index];
}
info.animatesToDestination = !accepted;
self.draggedGroup = nil;
return accepted;
}
NSPasteboard *pasteBoard = [info draggingPasteboard];
NSArray *items = [pasteBoard pasteboardItems];
if([items count] > 0) {
NSPasteboardItem *item = items[0];
UUID *uuid = [[UUID alloc] initWithString:[item stringForType:MPPasteBoardType]];
MPDocument *document = [[[outlineView window] windowController] document];
KdbGroup *rootGroup = [document root];
KdbEntry *draggedEntry = [rootGroup entryForUUID:uuid];
if(draggedEntry) {
if(draggedEntry.parent != target && index == NSOutlineViewDropOnItemIndex) {
[draggedEntry moveToGroupUndoable:target atIndex:index];
return YES;
}
}
}
*/
return NO;
}
@end

View File

@@ -0,0 +1,34 @@
//
// MPPasswordEditWindowController.h
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "MPSheetWindowController.h"
@class MPDocument;
@class HNHRoundedSecureTextField;
@interface MPPasswordEditWindowController : MPSheetWindowController <NSTextFieldDelegate>
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordTextField;
@property (weak) IBOutlet HNHRoundedSecureTextField *passwordRepeatTextField;
@property (weak) IBOutlet NSPathControl *keyfilePathControl;
@property (weak) IBOutlet NSButton *togglePasswordButton;
@property (weak) IBOutlet NSTextField *errorTextField;
@property (weak) IBOutlet NSButton *changePasswordButton;
/**
* Dedicated initializer for the Windowcontroller
* @param document The Database document that is currently active
* @return initalized windowcontroller
*/
- (id)initWithDocument:(MPDocument *)document;
- (IBAction)clearKey:(id)sender;
- (IBAction)generateKey:(id)sender;
@end

View File

@@ -0,0 +1,141 @@
//
// MPPasswordEditWindowController.m
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPPasswordEditWindowController.h"
#import "MPDocument.h"
#import "HNHRoundedSecureTextField.h"
#import "NSString+Empty.h"
@interface MPPasswordEditWindowController () {
MPDocument * __unsafe_unretained _document;
}
@property (nonatomic,assign) BOOL showPassword;
@property (nonatomic,assign) BOOL hasValidPasswordOrKey;
@property (nonatomic,weak) NSURL *keyURL;
@end
@implementation MPPasswordEditWindowController
- (id)initWithDocument:(MPDocument *)document {
self = [super initWithWindowNibName:@"PasswordEditWindow"];
if(self){
_showPassword = NO;
_hasValidPasswordOrKey = NO;
_document = document;
}
return self;
}
- (void)windowDidLoad {
[super windowDidLoad];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
}
- (void)updateView {
if(!self.isDirty) {
return;
}
self.showPassword = NO;
[self.passwordTextField setStringValue:_document.password ? _document.password : @""];
[self.passwordRepeatTextField setStringValue:[self.passwordTextField stringValue]];
self.keyURL = _document.key;
NSDictionary *negateOption = @{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName };
[self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil];
[self.togglePasswordButton bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil];
[self.passwordRepeatTextField bind:NSEnabledBinding toObject:self withKeyPath:@"showPassword" options:negateOption];
[self.errorTextField bind:NSHiddenBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.changePasswordButton bind:NSEnabledBinding toObject:self withKeyPath:@"hasValidPasswordOrKey" options:nil];
[self.keyfilePathControl bind:NSValueBinding toObject:self withKeyPath:@"keyURL" options:nil];
[self.passwordRepeatTextField setDelegate:self];
[self.passwordTextField setDelegate:self];
/* Manually initate the first check */
[self _verifyPasswordAndKey];
self.isDirty = NO;
}
- (void)setShowPassword:(BOOL)showPassword {
if(_showPassword != showPassword) {
_showPassword = showPassword;
[self.passwordRepeatTextField setStringValue:@""];
[self _verifyPasswordAndKey];
}
}
- (void)setKeyURL:(NSURL *)keyURL {
_keyURL = keyURL;
[self _verifyPasswordAndKey];
}
#pragma mark Actions
- (IBAction)save:(id)sender {
_document.password = [self.passwordTextField stringValue];
_document.key = [self.keyfilePathControl URL];
[self dismissSheet:NSRunStoppedResponse];
}
- (IBAction)cancel:(id)sender {
[self dismissSheet:NSRunAbortedResponse];
}
- (IBAction)clearKey:(id)sender {
self.keyURL = nil;
}
- (IBAction)generateKey:(id)sender {
}
#pragma mark NSTextFieldDelegate
- (void)controlTextDidChange:(NSNotification *)obj {
[self _verifyPasswordAndKey];
}
- (void)_verifyPasswordAndKey {
NSString *password = [self.passwordTextField stringValue];
NSString *repeat = [self.passwordRepeatTextField stringValue];
BOOL hasKey = (self.keyURL != nil);
BOOL keyOk = YES;
if(hasKey) {
keyOk = [self.keyURL checkResourceIsReachableAndReturnError:nil];
}
BOOL hasPassword = ![NSString isEmptyString:password];
if(!self.showPassword) {
hasPassword |= ![NSString isEmptyString:repeat];
}
BOOL passwordOk = YES;
if(hasPassword ) {
passwordOk = [password isEqualToString:repeat] || self.showPassword;
}
BOOL hasPasswordOrKey = (hasKey || hasPassword);
keyOk = hasKey ? keyOk : YES;
passwordOk = hasPassword ? passwordOk : YES;
self.hasValidPasswordOrKey = passwordOk && keyOk;
if(!hasPasswordOrKey) {
[self.errorTextField setTextColor:[NSColor controlTextColor]];
[self.errorTextField setStringValue:NSLocalizedString(@"WARNING_NO_PASSWORD_OR_KEYFILE", "No Key or Password")];
return; // alldone
}
[self.errorTextField setTextColor:[NSColor redColor]];
if(!passwordOk && !keyOk ) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH_INVALID_KEYFILE", "Passwords do not match, keyfile is invalid")];
}
else if(!passwordOk) {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_PASSWORD_MISSMATCH", "Passwords do not match")];
}
else {
[self.errorTextField setStringValue:NSLocalizedString(@"ERROR_INVALID_KEYFILE", "Keyfile not valid")];
}
}
@end

View File

@@ -0,0 +1,20 @@
//
// MPSavePanelAccessoryViewController.h
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPViewController.h"
@class MPDocument;
@interface MPSavePanelAccessoryViewController : MPViewController
@property (nonatomic, assign) NSSavePanel *savePanel;
@property (nonatomic, assign) MPDocument *document;
@property (nonatomic, weak) IBOutlet NSPopUpButton *fileTypePopupButton;
@property (nonatomic, weak) IBOutlet NSTextField *infoTextField;
@end

View File

@@ -0,0 +1,68 @@
//
// MPSavePanelAccessoryViewController.m
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPSavePanelAccessoryViewController.h"
#import "MPDocument.h"
@interface MPSavePanelAccessoryViewController ()
@end
@implementation MPSavePanelAccessoryViewController
- (id)init {
self = [super initWithNibName:@"SavePanelAccessoryView" bundle:nil];
if(self) {
}
return self;
}
- (void)didLoadView {
NSArray *types = [self.document writableTypesForSaveOperation:NSSaveOperation];
NSMenu *menu = [[NSMenu alloc] init];
for (NSString *uti in types ) {
NSString *description = CFBridgingRelease(UTTypeCopyDescription((__bridge CFStringRef)(uti)));
NSString *extension = [self.document fileNameExtensionForType:uti saveOperation:NSSaveOperation];
NSString *title = [NSString stringWithFormat:@"%@ (%@)", description, extension];
[menu addItemWithTitle:title action:@selector(setFileType:) keyEquivalent:@""];
NSMenuItem *item = [[menu itemArray] lastObject];
[item setTarget:self];
[item setRepresentedObject:uti];
}
[self.fileTypePopupButton setMenu:menu];
[self.infoTextField setHidden:YES];
[self _updateView];
}
- (IBAction)setFileType:(id)sender {
NSString *uti = [[self.fileTypePopupButton selectedItem] representedObject];
BOOL showInfoText = (self.document.version == MPDatabaseVersion4) && [uti isEqualToString:@"com.hicknhack.macpass.kdb"];
[self.infoTextField setHidden:!showInfoText];
[self.savePanel setAllowedFileTypes:@[uti]];
}
- (void)setDocument:(MPDocument *)document {
if(_document != document) {
_document = document;
[self _updateView];
}
}
- (void)_updateView {
switch(self.document.version) {
case MPDatabaseVersion3:
[self.fileTypePopupButton selectItemAtIndex:1];
break;
case MPDatabaseVersion4:
[self.fileTypePopupButton selectItemAtIndex:0];
break;
}
}
@end

View File

@@ -0,0 +1,33 @@
//
// MPSheetWindowController.h
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
// Based on
// DESSheetController by Peter Nix (pnix@digitalenginesoftware.com)
//
#import <Cocoa/Cocoa.h>
/**
* Generic Windowcontroller to be used for sheets
* Subclasses are ablte to initalize their views within updateView
* and thus are able to reset themself befor being displayed as sheets
*/
@interface MPSheetWindowController : NSWindowController
/**
* Flag to indicate that the view might need resetting.
* The default implementation of dismissi sheet and the
* designate initalizer both set the value to YES
*/
@property (nonatomic, assign) BOOL isDirty;
/**
* This method is a entry point to ensure updated ui befor being presented
* The method is called every time the window message is sent to the controller
*/
- (void)updateView;
- (void)dismissSheet:(NSInteger)returnCode;
@end

View File

@@ -0,0 +1,36 @@
//
// MPSheetWindowController.m
// MacPass
//
// Created by Michael Starke on 10.08.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
#import "MPSheetWindowController.h"
@implementation MPSheetWindowController
- (id)initWithWindow:(NSWindow *)window {
self = [super initWithWindow:window];
if(self) {
_isDirty = YES;
}
return self;
}
- (NSWindow *)window {
NSWindow *window = [super window];
[self updateView];
return window;
}
- (void)updateView {
// do nothing
}
- (void)dismissSheet:(NSInteger)returnCode {
self.isDirty = YES;
[NSApp endSheet:[super window] returnCode:returnCode];
[[super window] orderOut:self];
}
@end

View File

@@ -12,9 +12,13 @@
<string>kdbx</string>
</array>
<key>CFBundleTypeName</key>
<string>KeePass2 Database </string>
<string></string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.hicknhack.macpass.kdbx</string>
</array>
<key>NSDocumentClass</key>
<string>MPDocument</string>
</dict>
@@ -24,9 +28,13 @@
<string>kdb</string>
</array>
<key>CFBundleTypeName</key>
<string>KeePass Database</string>
<string></string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.hicknhack.macpass.kdb</string>
</array>
<key>NSDocumentClass</key>
<string>MPDocument</string>
</dict>
@@ -59,5 +67,42 @@
<string>NSApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Keepass 2 Database</string>
<key>UTTypeIdentifier</key>
<string>com.hicknhack.macpass.kdbx</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>kdbx</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Keepass Database</string>
<key>UTTypeIdentifier</key>
<string>com.hicknhack.macpass.kdb</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>kdb</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,630 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">3084</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>NSCustomObject</string>
<string>NSCustomView</string>
<string>NSMenu</string>
<string>NSMenuItem</string>
<string>NSPopUpButton</string>
<string>NSPopUpButtonCell</string>
<string>NSTextField</string>
<string>NSTextFieldCell</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="NSCustomObject" id="1001">
<string key="NSClassName">MPSavePanelAccessoryViewController</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSCustomView" id="1005">
<reference key="NSNextResponder"/>
<int key="NSvFlags">268</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="227871464">
<reference key="NSNextResponder" ref="1005"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{126, 20}, {363, 28}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<string key="NSAntiCompressionPriority">{249, 750}</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="841038612">
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">272629760</int>
<string key="NSContents">Not all Information inside your current database can be stored with this format.</string>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">11</double>
<int key="NSfFlags">3100</int>
</object>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="227871464"/>
<object class="NSColor" key="NSBackgroundColor" id="808731424">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor" id="617654541">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSTextField" id="1012867257">
<reference key="NSNextResponder" ref="1005"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{126, 58}, {53, 17}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="393971086"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="389721311">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">272630784</int>
<string key="NSContents">Format:</string>
<object class="NSFont" key="NSSupport" id="167579766">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="1012867257"/>
<reference key="NSBackgroundColor" ref="808731424"/>
<reference key="NSTextColor" ref="617654541"/>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSPopUpButton" id="393971086">
<reference key="NSNextResponder" ref="1005"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{182, 53}, {144, 26}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="227871464"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="976976603">
<int key="NSCellFlags">-2076180416</int>
<int key="NSCellFlags2">2048</int>
<reference key="NSSupport" ref="167579766"/>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="393971086"/>
<int key="NSButtonFlags">109199360</int>
<int key="NSButtonFlags2">129</int>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
<int key="NSPeriodicInterval">75</int>
<object class="NSMenuItem" key="NSMenuItem" id="897198694">
<reference key="NSMenu" ref="301298341"/>
<string key="NSTitle">KeePass 1 (KDB)</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<int key="NSState">1</int>
<object class="NSCustomResource" key="NSOnImage" id="852036856">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuCheckmark</string>
</object>
<object class="NSCustomResource" key="NSMixedImage" id="991929968">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">NSMenuMixedState</string>
</object>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="976976603"/>
</object>
<bool key="NSMenuItemRespectAlignment">YES</bool>
<object class="NSMenu" key="NSMenu" id="301298341">
<string key="NSTitle">OtherViews</string>
<array class="NSMutableArray" key="NSMenuItems">
<reference ref="897198694"/>
<object class="NSMenuItem" id="305900241">
<reference key="NSMenu" ref="301298341"/>
<string key="NSTitle">KeePass 2 (KDBX)</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="852036856"/>
<reference key="NSMixedImage" ref="991929968"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="976976603"/>
</object>
</array>
<reference key="NSMenuFont" ref="167579766"/>
</object>
<int key="NSSelectedIndex">-1</int>
<int key="NSPreferredEdge">1</int>
<bool key="NSUsesItemFromMenu">YES</bool>
<bool key="NSAltersState">YES</bool>
<int key="NSArrowPosition">2</int>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrameSize">{506, 95}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1012867257"/>
<string key="NSClassName">NSView</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1005"/>
</object>
<int key="connectionID">106</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">fileTypePopupButton</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="393971086"/>
</object>
<int key="connectionID">107</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">infoTextField</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="227871464"/>
</object>
<int key="connectionID">108</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="1005"/>
<array class="NSMutableArray" key="children">
<object class="IBNSLayoutConstraint" id="287625583">
<reference key="firstItem" ref="393971086"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1012867257"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="48960717">
<reference key="firstItem" ref="1005"/>
<int key="firstAttribute">9</int>
<int key="relation">0</int>
<reference key="secondItem" ref="393971086"/>
<int key="secondAttribute">9</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="710476841">
<reference key="firstItem" ref="393971086"/>
<int key="firstAttribute">10</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1012867257"/>
<int key="secondAttribute">10</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="846575981">
<reference key="firstItem" ref="1005"/>
<int key="firstAttribute">6</int>
<int key="relation">1</int>
<reference key="secondItem" ref="393971086"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="415778777">
<reference key="firstItem" ref="1005"/>
<int key="firstAttribute">4</int>
<int key="relation">1</int>
<reference key="secondItem" ref="227871464"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="533808731">
<reference key="firstItem" ref="227871464"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="393971086"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="567866089">
<reference key="firstItem" ref="227871464"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1012867257"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">2</int>
</object>
<object class="IBNSLayoutConstraint" id="209120337">
<reference key="firstItem" ref="1005"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="227871464"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="543937448">
<reference key="firstItem" ref="1012867257"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1005"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="45831968">
<reference key="firstItem" ref="1012867257"/>
<int key="firstAttribute">5</int>
<int key="relation">1</int>
<reference key="secondItem" ref="1005"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1005"/>
<int key="scoringType">9</int>
<float key="scoringTypeFloat">40</float>
<int key="contentType">3</int>
</object>
<reference ref="393971086"/>
<reference ref="1012867257"/>
<reference ref="227871464"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="393971086"/>
<array class="NSMutableArray" key="children">
<reference ref="976976603"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">3</int>
<reference key="object" ref="976976603"/>
<array class="NSMutableArray" key="children">
<reference ref="301298341"/>
</array>
<reference key="parent" ref="393971086"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="301298341"/>
<array class="NSMutableArray" key="children">
<reference ref="897198694"/>
<reference ref="305900241"/>
</array>
<reference key="parent" ref="976976603"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="897198694"/>
<reference key="parent" ref="301298341"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="305900241"/>
<reference key="parent" ref="301298341"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">11</int>
<reference key="object" ref="1012867257"/>
<array class="NSMutableArray" key="children">
<reference ref="389721311"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">12</int>
<reference key="object" ref="389721311"/>
<reference key="parent" ref="1012867257"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">51</int>
<reference key="object" ref="227871464"/>
<array class="NSMutableArray" key="children">
<reference ref="841038612"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">52</int>
<reference key="object" ref="841038612"/>
<reference key="parent" ref="227871464"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">80</int>
<reference key="object" ref="45831968"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">81</int>
<reference key="object" ref="846575981"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">86</int>
<reference key="object" ref="543937448"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">91</int>
<reference key="object" ref="48960717"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">78</int>
<reference key="object" ref="209120337"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">101</int>
<reference key="object" ref="533808731"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">89</int>
<reference key="object" ref="710476841"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">103</int>
<reference key="object" ref="415778777"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">92</int>
<reference key="object" ref="287625583"/>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">95</int>
<reference key="object" ref="567866089"/>
<reference key="parent" ref="1005"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array key="1.IBNSViewMetadataConstraints">
<reference ref="45831968"/>
<reference ref="543937448"/>
<reference ref="209120337"/>
<reference ref="567866089"/>
<reference ref="533808731"/>
<reference ref="415778777"/>
<reference ref="846575981"/>
<reference ref="710476841"/>
<reference ref="48960717"/>
<reference ref="287625583"/>
</array>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="101.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="103.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="11.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="2.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="51.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="51.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="52.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="78.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="80.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="81.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="86.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="89.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="91.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="92.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="95.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">108</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MPSavePanelAccessoryViewController</string>
<string key="superclassName">MPViewController</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">setFileType:</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
<string key="NS.key.0">setFileType:</string>
<object class="IBActionInfo" key="NS.object.0">
<string key="name">setFileType:</string>
<string key="candidateClassName">id</string>
</object>
</object>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="fileTypePopupButton">NSPopUpButton</string>
<string key="infoTextField">NSTextField</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="fileTypePopupButton">
<string key="name">fileTypePopupButton</string>
<string key="candidateClassName">NSPopUpButton</string>
</object>
<object class="IBToOneOutletInfo" key="infoTextField">
<string key="name">infoTextField</string>
<string key="candidateClassName">NSTextField</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPSavePanelAccessoryViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MPViewController</string>
<string key="superclassName">NSViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="NSMenuCheckmark">{11, 11}</string>
<string key="NSMenuMixedState">{10, 3}</string>
</dictionary>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>

View File

@@ -53,6 +53,7 @@
</set>
<string key="NSFrame">{{36, 19}, {32, 32}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="724782086"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
@@ -77,6 +78,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{73, 27}, {162, 17}}</string>
<reference key="NSSuperview" ref="1005"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="470987877">
@@ -114,6 +116,7 @@
</array>
<string key="NSFrameSize">{307, 71}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="914116063"/>
<string key="NSClassName">NSView</string>
</object>
@@ -383,7 +386,54 @@
<nil key="sourceID"/>
<int key="maxID">43</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MPDocument</string>
<string key="superclassName">NSDocument</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="createEntryFromTemplate:">id</string>
<string key="emptyTrash:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="createEntryFromTemplate:">
<string key="name">createEntryFromTemplate:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="emptyTrash:">
<string key="name">emptyTrash:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="warningView">NSView</string>
<string key="warningViewImage">NSImageView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="warningView">
<string key="name">warningView</string>
<string key="candidateClassName">NSView</string>
</object>
<object class="IBToOneOutletInfo" key="warningViewImage">
<string key="name">warningViewImage</string>
<string key="candidateClassName">NSImageView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MPDocument.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>

Binary file not shown.

Binary file not shown.