Remove dialog & add import/export
[REMOVED] Mac password Dialog. [ADDED] Mac sites import / export. [FIXED] Copying of hidden passwords.
This commit is contained in:
parent
34d8dc375f
commit
971538d6b5
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit a3f33c5f0cbafd6910ae55fb313764c18b48ad69
|
||||
Subproject commit 59dc05c9cca43504bad026dc4633dbba34b4cc43
|
@ -11,13 +11,13 @@
|
||||
#import "UbiquityStoreManager.h"
|
||||
#import "MPFixable.h"
|
||||
|
||||
typedef enum {
|
||||
typedef NS_ENUM( NSUInteger, MPImportResult ) {
|
||||
MPImportResultSuccess,
|
||||
MPImportResultCancelled,
|
||||
MPImportResultInvalidPassword,
|
||||
MPImportResultMalformedInput,
|
||||
MPImportResultInternalError,
|
||||
} MPImportResult;
|
||||
};
|
||||
|
||||
@interface MPAppDelegate_Shared(Store)<UbiquityStoreManagerDelegate>
|
||||
|
||||
|
@ -784,7 +784,7 @@ PearlAssociatedObjectProperty( NSManagedObjectContext*, MainManagedObjectContext
|
||||
|
||||
[export appendFormat:@"%@ %8ld %8s %20s\t%@\n",
|
||||
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed], (long)uses,
|
||||
[PearlString( @"%lu:%lu", (long)type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
[strf( @"%lu:%lu", (long)type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
? content: @""];
|
||||
}
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPElementCollectionView.h
|
||||
// MPElementCollectionView
|
||||
//
|
||||
// Created by lhunath on 2/11/2014.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@class MPElementModel;
|
||||
|
||||
@interface MPElementCollectionView : NSCollectionViewItem
|
||||
|
||||
@property (nonatomic) MPElementModel *representedObject;
|
||||
@property (nonatomic) BOOL counterHidden;
|
||||
@property (nonatomic) BOOL updateContentHidden;
|
||||
|
||||
- (IBAction)toggleType:(id)sender;
|
||||
- (IBAction)updateLoginName:(id)sender;
|
||||
- (IBAction)updateContent:(id)sender;
|
||||
- (IBAction)delete:(id)sender;
|
||||
|
||||
@end
|
@ -1,225 +0,0 @@
|
||||
/**
|
||||
* Copyright Maarten Billemont (http://www.lhunath.com, lhunath@lyndir.com)
|
||||
*
|
||||
* See the enclosed file LICENSE for license information (LGPLv3). If you did
|
||||
* not receive this file, see http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*
|
||||
* @author Maarten Billemont <lhunath@lyndir.com>
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
*/
|
||||
|
||||
//
|
||||
// MPElementCollectionView.h
|
||||
// MPElementCollectionView
|
||||
//
|
||||
// Created by lhunath on 2/11/2014.
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementCollectionView.h"
|
||||
#import "MPElementModel.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPPasswordDialogController.h"
|
||||
|
||||
#define MPAlertChangeType @"MPAlertChangeType"
|
||||
#define MPAlertChangeLogin @"MPAlertChangeLogin"
|
||||
#define MPAlertChangeContent @"MPAlertChangeContent"
|
||||
#define MPAlertDeleteSite @"MPAlertDeleteSite"
|
||||
|
||||
@implementation MPElementCollectionView {
|
||||
}
|
||||
|
||||
@dynamic representedObject;
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)coder {
|
||||
|
||||
if (!(self = [super initWithCoder:coder]))
|
||||
return nil;
|
||||
|
||||
[self addObserver:self forKeyPath:@"representedObject" options:0 context:nil];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
self.counterHidden = !(MPElementTypeClassGenerated & self.representedObject.type);
|
||||
self.updateContentHidden = !(MPElementTypeClassStored & self.representedObject.type);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
||||
[self removeObserver:self forKeyPath:@"representedObject"];
|
||||
}
|
||||
|
||||
- (IBAction)toggleType:(id)sender {
|
||||
|
||||
id<MPAlgorithm> algorithm = self.representedObject.algorithm;
|
||||
NSString *previousType = [algorithm nameOfType:[algorithm previousType:self.representedObject.type]];
|
||||
NSString *nextType = [algorithm nameOfType:[algorithm nextType:self.representedObject.type]];
|
||||
|
||||
[[NSAlert alertWithMessageText:@"Change Password Type"
|
||||
defaultButton:nextType alternateButton:@"Cancel" otherButton:previousType
|
||||
informativeTextWithFormat:@"Changing the password type for this site will cause the password to change.\n"
|
||||
@"You will need to update your account with the new password.\n\n"
|
||||
@"Changing back to the old type will restore your current password."]
|
||||
beginSheetModalForWindow:self.view.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeType];
|
||||
}
|
||||
|
||||
- (IBAction)updateLoginName:(id)sender {
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Update Login Name"
|
||||
defaultButton:@"Update" alternateButton:@"Cancel" otherButton:nil
|
||||
informativeTextWithFormat:@"Enter the login name for %@:", self.representedObject.siteName];
|
||||
NSTextField *passwordField = [[NSTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeLogin];
|
||||
}
|
||||
|
||||
- (IBAction)updateContent:(id)sender {
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Update Password"
|
||||
defaultButton:@"Update" alternateButton:@"Cancel" otherButton:nil
|
||||
informativeTextWithFormat:@"Enter the new password for %@:", self.representedObject.siteName];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertChangeContent];
|
||||
}
|
||||
|
||||
- (IBAction)delete:(id)sender {
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Delete Site"
|
||||
defaultButton:@"Delete" alternateButton:@"Cancel" otherButton:nil
|
||||
informativeTextWithFormat:@"Are you sure you want to delete the site: %@?", self.representedObject.siteName];
|
||||
[alert beginSheetModalForWindow:self.view.window modalDelegate:self
|
||||
didEndSelector:@selector( alertDidEnd:returnCode:contextInfo: ) contextInfo:MPAlertDeleteSite];
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
if (contextInfo == MPAlertChangeType) {
|
||||
switch (returnCode) {
|
||||
case NSAlertDefaultReturn: {
|
||||
// "Next type" button.
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self.representedObject entityInContext:context];
|
||||
element = [[MPMacAppDelegate get] changeElement:element saveInContext:context
|
||||
toType:[element.algorithm nextType:element.type]];
|
||||
|
||||
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Cancel" button.
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertOtherReturn: {
|
||||
// "Previous type" button.
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self.representedObject entityInContext:context];
|
||||
element = [[MPMacAppDelegate get] changeElement:element saveInContext:context
|
||||
toType:[element.algorithm previousType:element.type]];
|
||||
|
||||
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertChangeLogin) {
|
||||
switch (returnCode) {
|
||||
case NSAlertDefaultReturn: {
|
||||
// "Update" button.
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self.representedObject entityInContext:context];
|
||||
element.loginName = [(NSTextField *)alert.accessoryView stringValue];
|
||||
[context saveToStore];
|
||||
|
||||
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Cancel" button.
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertChangeContent) {
|
||||
switch (returnCode) {
|
||||
case NSAlertDefaultReturn: {
|
||||
// "Update" button.
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self.representedObject entityInContext:context];
|
||||
[element.algorithm saveContent:[(NSSecureTextField *)alert.accessoryView stringValue]
|
||||
toElement:element usingKey:[MPMacAppDelegate get].key];
|
||||
[context saveToStore];
|
||||
|
||||
self.representedObject = [[MPElementModel alloc] initWithEntity:element];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Cancel" button.
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertDeleteSite) {
|
||||
switch (returnCode) {
|
||||
case NSAlertDefaultReturn: {
|
||||
// "Delete" button.
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPElementEntity *element = [self.representedObject entityInContext:context];
|
||||
[context deleteObject:element];
|
||||
[context saveToStore];
|
||||
|
||||
[((MPPasswordDialogController *)self.collectionView.window.windowController) updateElements];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Cancel" button.
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -25,6 +25,7 @@
|
||||
@property (nonatomic) MPElementType type;
|
||||
@property (nonatomic) NSString *typeName;
|
||||
@property (nonatomic) NSString *content;
|
||||
@property (nonatomic) NSString *contentDisplay;
|
||||
@property (nonatomic) NSString *loginName;
|
||||
@property (nonatomic) NSNumber *uses;
|
||||
@property (nonatomic) NSUInteger counter;
|
||||
|
@ -111,13 +111,21 @@
|
||||
|
||||
- (void)updateContent:(MPElementEntity *)entity {
|
||||
|
||||
[entity resolveContentUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
||||
result = [result stringByReplacingMatchesOfExpression:
|
||||
[NSRegularExpression regularExpressionWithPattern:@"." options:0 error:nil]
|
||||
withTemplate:@"●"];
|
||||
static NSRegularExpression *re_anyChar;
|
||||
static dispatch_once_t once = 0;
|
||||
dispatch_once( &once, ^{
|
||||
re_anyChar = [NSRegularExpression regularExpressionWithPattern:@"." options:0 error:nil];
|
||||
} );
|
||||
|
||||
PearlMainQueue( ^{ self.content = result; } );
|
||||
[entity resolveContentUsingKey:[MPAppDelegate_Shared get].key result:^(NSString *result) {
|
||||
NSString *displayResult = result;
|
||||
if ([[MPConfig get].hidePasswords boolValue] && !([NSEvent modifierFlags] & NSAlternateKeyMask))
|
||||
displayResult = [displayResult stringByReplacingMatchesOfExpression:re_anyChar withTemplate:@"●"];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
self.content = result;
|
||||
self.contentDisplay = displayResult;
|
||||
} );
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *createUserItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *deleteUserItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *usersItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleRegular;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *dialogStyleHUD;
|
||||
@property(nonatomic, weak) IBOutlet NSButton *openAtLoginButton;
|
||||
@property(nonatomic, weak) IBOutlet NSButton *enableCloudButton;
|
||||
|
||||
|
@ -37,7 +37,7 @@ static EventHotKeyID MPLockHotKey = { .signature = 'lock', .id = 1 };
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
static dispatch_once_t initialize;
|
||||
static dispatch_once_t initialize = 0;
|
||||
dispatch_once( &initialize, ^{
|
||||
[MPMacConfig get];
|
||||
|
||||
@ -71,7 +71,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
|
||||
PearlProfiler *profiler = [PearlProfiler profilerForTask:@"applicationDidFinishLaunching"];
|
||||
// Setup delegates and listeners.
|
||||
[MPConfig get].delegate = self;
|
||||
__weak id weakSelf = self;
|
||||
@ -90,7 +89,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[weakSelf updateMenuItems];
|
||||
} );
|
||||
} forKeyPath:@"storeManager.cloudAvailable" options:0 context:nil];
|
||||
[profiler finishJob:@"observers"];
|
||||
|
||||
// Status item.
|
||||
self.statusView = [[RHStatusItemView alloc] initWithStatusBarItem:
|
||||
@ -99,41 +97,24 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.statusView.menu = self.statusMenu;
|
||||
self.statusView.target = self;
|
||||
self.statusView.action = @selector( showMenu );
|
||||
[profiler finishJob:@"statusView"];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidImportChangesNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
NSString *key = note.object;
|
||||
if (!key || [key isEqualToString:NSStringFromSelector( @selector( hidePasswords ) )])
|
||||
self.hidePasswordsItem.state = [[MPConfig get].hidePasswords boolValue]? NSOnState: NSOffState;
|
||||
if (!key || [key isEqualToString:NSStringFromSelector( @selector( rememberLogin ) )])
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState;
|
||||
if (!key || [key isEqualToString:NSStringFromSelector( @selector( dialogStyleHUD ) )]) {
|
||||
self.dialogStyleRegular.state = ![[MPMacConfig get].dialogStyleHUD boolValue]? NSOnState: NSOffState;
|
||||
self.dialogStyleHUD.state = [[MPMacConfig get].dialogStyleHUD boolValue]? NSOnState: NSOffState;
|
||||
if (![self.passwordWindow.window isVisible])
|
||||
self.passwordWindow = nil;
|
||||
else {
|
||||
[self.passwordWindow close];
|
||||
self.passwordWindow = nil;
|
||||
[self showPasswordWindow:nil];
|
||||
}
|
||||
}
|
||||
}];
|
||||
[profiler finishJob:@"notificationCenter"];
|
||||
[self updateUsers];
|
||||
[profiler finishJob:@"updateUsers"];
|
||||
|
||||
// Global hotkey.
|
||||
EventHotKeyRef hotKeyRef;
|
||||
@ -148,7 +129,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err( @"Error registering 'lock' hotkey: %i", (int)status );
|
||||
[profiler finishJob:@"hotKey"];
|
||||
|
||||
// Initial display.
|
||||
if ([[MPMacConfig get].firstRun boolValue]) {
|
||||
@ -156,7 +136,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[self.initialWindow.window setLevel:NSFloatingWindowLevel];
|
||||
[self.initialWindow showWindow:self];
|
||||
}
|
||||
[profiler finishJob:@"initial display"];
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification {
|
||||
@ -230,12 +209,113 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
[self signOutAnimated:NO];
|
||||
|
||||
NSError *error = nil;
|
||||
NSManagedObjectContext *context = [MPMacAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
self.activeUser = (MPUserEntity *)[context existingObjectWithID:[item representedObject] error:&error];
|
||||
NSManagedObjectContext *mainContext = [MPMacAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
self.activeUser = [MPUserEntity existingObjectWithID:[item representedObject] inContext:mainContext];
|
||||
}
|
||||
|
||||
if (error)
|
||||
err( @"While looking up selected user: %@", error );
|
||||
- (IBAction)exportSitesSecure:(id)sender {
|
||||
|
||||
[self exportSitesAndRevealPasswords:NO];
|
||||
}
|
||||
|
||||
- (IBAction)exportSitesReveal:(id)sender {
|
||||
|
||||
[self exportSitesAndRevealPasswords:YES];
|
||||
}
|
||||
|
||||
- (IBAction)importSites:(id)sender {
|
||||
|
||||
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
||||
openPanel.allowsMultipleSelection = NO;
|
||||
openPanel.canChooseDirectories = NO;
|
||||
openPanel.title = @"Master Password";
|
||||
openPanel.message = @"Locate the Master Password export file to import.";
|
||||
openPanel.prompt = @"Import";
|
||||
openPanel.directoryURL = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
|
||||
openPanel.allowedFileTypes = @[ @"mpsites" ];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
if ([openPanel runModal] == NSFileHandlingPanelCancelButton)
|
||||
return;
|
||||
|
||||
NSURL *url = openPanel.URL;
|
||||
|
||||
PearlNotMainQueue( ^{
|
||||
NSError *error;
|
||||
NSURLResponse *response;
|
||||
NSData *importedSitesData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url]
|
||||
returningResponse:&response error:&error];
|
||||
if (error)
|
||||
err( @"While reading imported sites from %@: %@", url, error );
|
||||
if (!importedSitesData)
|
||||
return;
|
||||
|
||||
NSString *importedSitesString = [[NSString alloc] initWithData:importedSitesData encoding:NSUTF8StringEncoding];
|
||||
MPImportResult result = [self importSites:importedSitesString askImportPassword:^NSString *(NSString *userName) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
PearlMainQueueWait( ^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Unlock"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
alert.messageText = @"Import File's Master Password";
|
||||
alert.informativeText = strf( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName );
|
||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert layout];
|
||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
|
||||
} );
|
||||
|
||||
return masterPassword;
|
||||
} askUserPassword:^NSString *(NSString *userName, NSUInteger importCount, NSUInteger deleteCount) {
|
||||
__block NSString *masterPassword = nil;
|
||||
|
||||
PearlMainQueueWait( ^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Import"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
alert.messageText = strf( @"Master Password for\n%@", userName );
|
||||
alert.informativeText = strf( @"Imports %lu sites, overwriting %lu.",
|
||||
(unsigned long)importCount, (unsigned long)deleteCount );
|
||||
alert.accessoryView = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert layout];
|
||||
if ([alert runModal] == NSAlertFirstButtonReturn)
|
||||
masterPassword = ((NSTextField *)alert.accessoryView).stringValue;
|
||||
} );
|
||||
|
||||
return masterPassword;
|
||||
}];
|
||||
|
||||
PearlMainQueue( ^{
|
||||
switch (result) {
|
||||
case MPImportResultSuccess: {
|
||||
[self updateUsers];
|
||||
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"Successfully imported sites.";
|
||||
[alert runModal];
|
||||
break;
|
||||
}
|
||||
case MPImportResultCancelled:
|
||||
break;
|
||||
case MPImportResultInternalError:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Import failed because of an internal error."
|
||||
}]];
|
||||
break;
|
||||
case MPImportResultMalformedInput:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"The import doesn't look like a Master Password export."
|
||||
}]];
|
||||
break;
|
||||
case MPImportResultInvalidPassword:
|
||||
[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : @"Incorrect master password for the import sites."
|
||||
}]];
|
||||
break;
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
- (IBAction)togglePreference:(id)sender {
|
||||
@ -269,10 +349,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[context saveToStore];
|
||||
}];
|
||||
}
|
||||
if (sender == self.dialogStyleRegular)
|
||||
[MPMacConfig get].dialogStyleHUD = @NO;
|
||||
if (sender == self.dialogStyleHUD)
|
||||
[MPMacConfig get].dialogStyleHUD = @YES;
|
||||
|
||||
[MPMacConfig flush];
|
||||
}
|
||||
@ -381,23 +457,81 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
// If no user, can't activate.
|
||||
if (![self activeUserForMainThread]) {
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"No User Selected";
|
||||
alert.informativeText = @"Begin by selecting or creating your user from the status menu (●●●|) next to the clock.";
|
||||
[alert runModal];
|
||||
[self showPopup:nil];
|
||||
[[NSAlert alertWithMessageText:@"No User Selected" defaultButton:[PearlStrings get].commonButtonOkay alternateButton:nil
|
||||
otherButton:nil informativeTextWithFormat:
|
||||
@"Begin by selecting or creating your user from the status menu (●●●|) next to the clock."]
|
||||
runModal];
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't show window if we weren't already running (ie. if we haven't been activated before).
|
||||
PearlProfiler *profiler = [PearlProfiler profilerForTask:@"passwordWindow"];
|
||||
if (!self.passwordWindow)
|
||||
self.passwordWindow = [[MPPasswordWindowController alloc] initWithWindowNibName:@"MPPasswordWindowController"];
|
||||
[profiler finishJob:@"init"];
|
||||
|
||||
[self.passwordWindow showWindow:self];
|
||||
[profiler finishJob:@"show"];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)exportSitesAndRevealPasswords:(BOOL)revealPasswords {
|
||||
|
||||
MPUserEntity *mainActiveUser = [self activeUserForMainThread];
|
||||
if (!mainActiveUser) {
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"No User Selected";
|
||||
alert.informativeText = @"To export your sites, first select the user whose sites to export.";
|
||||
[alert runModal];
|
||||
[self showPopup:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.key) {
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"User Locked";
|
||||
alert.informativeText = @"To export your sites, first unlock your user by opening Master Password.";
|
||||
[alert runModal];
|
||||
[self showPopup:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||
|
||||
NSSavePanel *savePanel = [NSSavePanel savePanel];
|
||||
savePanel.title = @"Master Password";
|
||||
savePanel.message = @"Pick a location for the export Master Password's sites.";
|
||||
if (revealPasswords)
|
||||
savePanel.message = strf( @"%@\nWARNING: Your passwords will be visible. Make sure to always keep the file in a secure location.",
|
||||
savePanel.message );
|
||||
savePanel.prompt = @"Export";
|
||||
savePanel.directoryURL = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
|
||||
savePanel.nameFieldStringValue = strf( @"%@ (%@).mpsites", mainActiveUser.name,
|
||||
[exportDateFormatter stringFromDate:[NSDate date]] );
|
||||
savePanel.allowedFileTypes = @[ @"mpsites" ];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
if ([savePanel runModal] == NSFileHandlingPanelCancelButton)
|
||||
return;
|
||||
|
||||
NSError *coordinateError = nil;
|
||||
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
|
||||
[[[NSFileCoordinator alloc] initWithFilePresenter:nil] coordinateWritingItemAtURL:savePanel.URL options:0 error:&coordinateError
|
||||
byAccessor:^(NSURL *newURL) {
|
||||
NSError *writeError = nil;
|
||||
if (![exportedSites writeToURL:newURL atomically:NO encoding:NSUTF8StringEncoding error:&writeError])
|
||||
PearlMainQueue( ^{
|
||||
[[NSAlert alertWithError:writeError] runModal];
|
||||
} );
|
||||
}];
|
||||
if (coordinateError)
|
||||
PearlMainQueue( ^{
|
||||
[[NSAlert alertWithError:coordinateError] runModal];
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)updateUsers {
|
||||
|
||||
[[[self.usersItem submenu] itemArray] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
@ -405,8 +539,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[[self.usersItem submenu] removeItem:obj];
|
||||
}];
|
||||
|
||||
NSManagedObjectContext *context = [MPMacAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
if (!context) {
|
||||
NSManagedObjectContext *mainContext = [MPMacAppDelegate managedObjectContextForMainThreadIfReady];
|
||||
if (!mainContext) {
|
||||
self.createUserItem.title = @"New User (Not ready)";
|
||||
self.createUserItem.enabled = NO;
|
||||
self.createUserItem.toolTip = @"Please wait until the app is fully loaded.";
|
||||
@ -418,20 +552,20 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
return;
|
||||
}
|
||||
|
||||
MPUserEntity *activeUser = [self activeUserInContext:context];
|
||||
MPUserEntity *mainActiveUser = [self activeUserInContext:mainContext];
|
||||
|
||||
self.createUserItem.title = @"New User";
|
||||
self.createUserItem.enabled = YES;
|
||||
self.createUserItem.toolTip = nil;
|
||||
|
||||
self.deleteUserItem.title = activeUser? @"Delete User": @"Delete User (None Selected)";
|
||||
self.deleteUserItem.enabled = activeUser != nil;
|
||||
self.deleteUserItem.toolTip = activeUser? nil: @"First select the user to delete.";
|
||||
self.deleteUserItem.title = mainActiveUser? @"Delete User": @"Delete User (None Selected)";
|
||||
self.deleteUserItem.enabled = mainActiveUser != nil;
|
||||
self.deleteUserItem.toolTip = mainActiveUser? nil: @"First select the user to delete.";
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
|
||||
NSArray *users = [context executeFetchRequest:fetchRequest error:&error];
|
||||
NSArray *users = [mainContext executeFetchRequest:fetchRequest error:&error];
|
||||
if (!users)
|
||||
err( @"Failed to load users: %@", error );
|
||||
|
||||
@ -449,10 +583,10 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[userItem setRepresentedObject:[user objectID]];
|
||||
[[self.usersItem submenu] addItem:userItem];
|
||||
|
||||
if (!activeUser && [user.name isEqualToString:[MPMacConfig get].usedUserName])
|
||||
[super setActiveUser:activeUser = user];
|
||||
if (!mainActiveUser && [user.name isEqualToString:[MPMacConfig get].usedUserName])
|
||||
[super setActiveUser:mainActiveUser = user];
|
||||
|
||||
if ([activeUser isEqual:user]) {
|
||||
if ([mainActiveUser isEqual:user]) {
|
||||
userItem.state = NSOnState;
|
||||
self.usersItem.state = NSOffState;
|
||||
}
|
||||
|
@ -11,6 +11,5 @@
|
||||
@interface MPMacConfig : MPConfig
|
||||
|
||||
@property(nonatomic, retain) NSString *usedUserName;
|
||||
@property(nonatomic, retain) NSNumber *dialogStyleHUD;
|
||||
|
||||
@end
|
||||
|
@ -9,7 +9,6 @@
|
||||
@implementation MPMacConfig
|
||||
|
||||
@dynamic usedUserName;
|
||||
@dynamic dialogStyleHUD;
|
||||
|
||||
- (id)init {
|
||||
|
||||
@ -18,7 +17,6 @@
|
||||
|
||||
[self.defaults registerDefaults:@{
|
||||
NSStringFromSelector( @selector(iTunesID) ) : @"510296984",
|
||||
NSStringFromSelector( @selector(dialogStyleHUD) ) : @NO,
|
||||
}];
|
||||
|
||||
return self;
|
||||
|
@ -1,23 +0,0 @@
|
||||
//
|
||||
// MPPasswordDialogController.h
|
||||
// MasterPassword-Mac
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@class MPElementModel;
|
||||
|
||||
@interface MPPasswordDialogController : NSWindowController<NSTextFieldDelegate, NSCollectionViewDelegate>
|
||||
|
||||
@property(nonatomic, strong) NSMutableArray *elements;
|
||||
@property(nonatomic, strong) NSIndexSet *elementSelectionIndexes;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property(nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
@property(nonatomic, weak) IBOutlet NSCollectionView *siteCollectionView;
|
||||
|
||||
- (void)updateElements;
|
||||
|
||||
@end
|
@ -1,478 +0,0 @@
|
||||
//
|
||||
// MPPasswordDialogController.m
|
||||
// MasterPassword-Mac
|
||||
//
|
||||
// Created by Maarten Billemont on 04/03/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPasswordDialogController.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
#import "MPAppDelegate_Key.h"
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import "MPElementModel.h"
|
||||
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
#define MPAlertCreateSite @"MPAlertCreateSite"
|
||||
|
||||
@interface MPPasswordDialogController()
|
||||
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
|
||||
@property(nonatomic, strong) NSOperationQueue *backgroundQueue;
|
||||
@property(nonatomic, strong) NSAlert *loadingDataAlert;
|
||||
@property(nonatomic) BOOL closing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPasswordDialogController
|
||||
|
||||
#pragma mark - Life
|
||||
|
||||
- (void)windowDidLoad {
|
||||
|
||||
if ([[MPMacConfig get].dialogStyleHUD boolValue]) {
|
||||
self.window.styleMask = NSHUDWindowMask | NSTitledWindowMask | NSUtilityWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor whiteColor];
|
||||
}
|
||||
else {
|
||||
self.window.styleMask = NSTexturedBackgroundWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSClosableWindowMask;
|
||||
self.userLabel.textColor = [NSColor controlTextColor];
|
||||
}
|
||||
|
||||
self.backgroundQueue = [NSOperationQueue new];
|
||||
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
[[MPMacAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
// [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
// if (![MPAlgorithmDefault migrateUser:[[MPMacAppDelegate get] activeUserInContext:moc]])
|
||||
// [NSAlert alertWithMessageText:@"Migration Needed" defaultButton:@"OK" alternateButton:nil otherButton:nil
|
||||
// informativeTextWithFormat:@"Certain sites require explicit migration to get updated to the latest version of the "
|
||||
// @"Master Password algorithm. For these sites, a migration button will appear. Migrating these sites will cause "
|
||||
// @"their passwords to change. You'll need to update your profile for that site with the new password."];
|
||||
// [moc saveToStore];
|
||||
// }];
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
[self updateElements];
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
[self.siteField selectText:nil];
|
||||
[self updateElements];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
NSWindow *sheet = [self.window attachedSheet];
|
||||
if (sheet)
|
||||
[NSApp endSheet:sheet];
|
||||
|
||||
[NSApp hide:nil];
|
||||
self.closing = NO;
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = @"";
|
||||
self.siteField.stringValue = @"";
|
||||
self.elements = nil;
|
||||
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedInNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.userLabel.stringValue = PearlString( @"%@'s password for:",
|
||||
[[MPMacAppDelegate get] activeUserForMainThread].name );
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:USMStoreDidChangeNotification object:nil
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
|
||||
}];
|
||||
|
||||
[super windowDidLoad];
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
||||
self.closing = YES;
|
||||
[super close];
|
||||
}
|
||||
|
||||
#pragma mark - NSAlert
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
|
||||
if (contextInfo == MPAlertIncorrectMP) {
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertUnlockMP) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Unlock" button.
|
||||
self.contentContainer.alphaValue = 0;
|
||||
self.inProgress = YES;
|
||||
|
||||
NSString *password = [(NSSecureTextField *)alert.accessoryView stringValue];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
BOOL success = [[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc
|
||||
usingMasterPassword:password];
|
||||
self.inProgress = NO;
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@", userName )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertSecondButtonReturn: {
|
||||
// "Change" button.
|
||||
NSAlert *alert_ = [NSAlert new];
|
||||
[alert_ addButtonWithTitle:@"Update"];
|
||||
[alert_ addButtonWithTitle:@"Cancel"];
|
||||
[alert_ setMessageText:@"Changing Master Password"];
|
||||
[alert_ setInformativeText:@"This will allow you to log in with a different master password.\n\n"
|
||||
@"Note that you will only see the sites and passwords for the master password you log in with.\n"
|
||||
@"If you log in with a different master password, your current sites will be unavailable.\n\n"
|
||||
@"You can always change back to your current master password later.\n"
|
||||
@"Your current sites and passwords will then become available again."];
|
||||
|
||||
if ([alert_ runModal] == NSAlertFirstButtonReturn) {
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:context];
|
||||
activeUser.keyID = nil;
|
||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||
[[MPMacAppDelegate get] signOutAnimated:YES];
|
||||
[context saveToStore];
|
||||
}];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertThirdButtonReturn: {
|
||||
// "Cancel" button.
|
||||
[self close];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (contextInfo == MPAlertCreateSite) {
|
||||
switch (returnCode) {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Create" button.
|
||||
[[MPMacAppDelegate get] addElementNamed:[self.siteField stringValue] completion:^(MPElementEntity *element) {
|
||||
if (element)
|
||||
PearlMainQueue( ^{ [self updateElements]; } );
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case NSAlertThirdButtonReturn:
|
||||
// "Cancel" button.
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSCollectionViewDelegate
|
||||
|
||||
#pragma mark - NSTextFieldDelegate
|
||||
|
||||
- (void)doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
}
|
||||
|
||||
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||
|
||||
if (commandSelector == @selector(cancel:))
|
||||
[self close];
|
||||
if (commandSelector == @selector(moveUp:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MAX(self.elementSelectionIndexes.firstIndex, (NSUInteger)1) - 1];
|
||||
if (commandSelector == @selector(moveDown:))
|
||||
self.elementSelectionIndexes =
|
||||
[NSIndexSet indexSetWithIndex:MIN(self.elementSelectionIndexes.firstIndex + 1, self.elements.count - 1)];
|
||||
if (commandSelector == @selector(moveLeft:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
if (commandSelector == @selector(moveRight:))
|
||||
[[self selectedView].animator setBoundsOrigin:NSMakePoint( self.siteCollectionView.frame.size.width / 2, 0 )];
|
||||
if (commandSelector == @selector(insertNewline:))
|
||||
[self useSite];
|
||||
else
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)controlTextDidChange:(NSNotification *)note {
|
||||
|
||||
if (note.object != self.siteField)
|
||||
return;
|
||||
|
||||
// Update the site content as the site name changes.
|
||||
if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
[[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@"\r"]) { // Return while completing.
|
||||
[self useSite];
|
||||
return;
|
||||
}
|
||||
|
||||
// if ([[NSApp currentEvent] type] == NSKeyDown &&
|
||||
// [[[NSApp currentEvent] charactersIgnoringModifiers] characterAtIndex:0] == 0x1b) { // Escape while completing.
|
||||
// [self trySiteWithAction:NO];
|
||||
// return;
|
||||
// }
|
||||
|
||||
[self updateElements];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (BOOL)ensureLoadedAndUnlockedOrCloseIfLoggedOut:(BOOL)closeIfLoggedOut {
|
||||
|
||||
if (![self ensureStoreLoaded])
|
||||
return NO;
|
||||
|
||||
if (self.closing || self.inProgress || !self.window.isKeyWindow)
|
||||
return NO;
|
||||
|
||||
return [self ensureUnlocked:closeIfLoggedOut];
|
||||
}
|
||||
|
||||
- (BOOL)ensureStoreLoaded {
|
||||
|
||||
if ([MPMacAppDelegate managedObjectContextForMainThreadIfReady]) {
|
||||
// Store loaded.
|
||||
if (self.loadingDataAlert.window)
|
||||
[NSApp endSheet:self.loadingDataAlert.window];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
[self.loadingDataAlert = [NSAlert alertWithMessageText:@"Opening Your Data" defaultButton:@"..." alternateButton:nil otherButton:nil
|
||||
informativeTextWithFormat:@""]
|
||||
beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)ensureUnlocked:(BOOL)closeIfLoggedOut {
|
||||
|
||||
__block BOOL unlocked = NO;
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||
NSString *userName = activeUser.name;
|
||||
if (!activeUser) {
|
||||
// No user to sign in with.
|
||||
if (closeIfLoggedOut)
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([MPMacAppDelegate get].key) {
|
||||
// Already logged in.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
if (activeUser.saveKey && closeIfLoggedOut) {
|
||||
// App was locked, don't instantly unlock again.
|
||||
[self close];
|
||||
return;
|
||||
}
|
||||
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil]) {
|
||||
// Loaded the key from the keychain.
|
||||
unlocked = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask the user to set the key through his master password.
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if ([MPMacAppDelegate get].key)
|
||||
return;
|
||||
|
||||
[self.siteField setStringValue:@""];
|
||||
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Unlock"];
|
||||
[alert addButtonWithTitle:@"Change"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Master Password is locked."];
|
||||
[alert setInformativeText:PearlString( @"The master password is required to unlock the application for:\n\n%@", userName )];
|
||||
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
[passwordField becomeFirstResponder];
|
||||
}];
|
||||
}];
|
||||
|
||||
return unlocked;
|
||||
}
|
||||
|
||||
- (void)updateElements {
|
||||
|
||||
if (![MPMacAppDelegate get].key) {
|
||||
self.elements = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *query = [self.siteField.currentEditor string];
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, query, [[MPMacAppDelegate get] activeUserInContext:context]];
|
||||
|
||||
NSError *error = nil;
|
||||
NSArray *siteResults = [context executeFetchRequest:fetchRequest error:&error];
|
||||
if (!siteResults) {
|
||||
err(@"While fetching elements for completion: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *newElements = [NSMutableArray arrayWithCapacity:[siteResults count]];
|
||||
for (MPElementEntity *element in siteResults)
|
||||
[newElements addObject:[[MPElementModel alloc] initWithEntity:element]];
|
||||
self.elements = newElements;
|
||||
if (!self.selectedElement)
|
||||
self.elementSelectionIndexes = [newElements count]? [NSIndexSet indexSetWithIndex:0]: nil;
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSUInteger)selectedIndex {
|
||||
|
||||
if (!self.elementSelectionIndexes)
|
||||
return NSNotFound;
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex >= self.elements.count)
|
||||
return NSNotFound;
|
||||
|
||||
return selectedIndex;
|
||||
}
|
||||
|
||||
- (NSBox *)selectedView {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (NSBox *)[self.siteCollectionView itemAtIndex:selectedIndex].view;
|
||||
}
|
||||
|
||||
- (MPElementModel *)selectedElement {
|
||||
|
||||
NSUInteger selectedIndex = [self selectedIndex];
|
||||
if (selectedIndex == NSNotFound)
|
||||
return nil;
|
||||
|
||||
return (MPElementModel *)self.elements[selectedIndex];
|
||||
}
|
||||
|
||||
- (void)setSelectedElement:(MPElementModel *)element {
|
||||
|
||||
self.elementSelectionIndexes = [NSIndexSet indexSetWithIndex:[self.elements indexOfObject:element]];
|
||||
}
|
||||
|
||||
- (void)useSite {
|
||||
|
||||
MPElementModel *selectedElement = [self selectedElement];
|
||||
if (selectedElement) {
|
||||
// Performing action while content is available. Copy it.
|
||||
[self copyContent:selectedElement.content];
|
||||
|
||||
[self close];
|
||||
|
||||
NSUserNotification *notification = [NSUserNotification new];
|
||||
notification.title = @"Password Copied";
|
||||
if (selectedElement.loginName.length)
|
||||
notification.subtitle = PearlString( @"%@ at %@", selectedElement.loginName, selectedElement.siteName );
|
||||
else
|
||||
notification.subtitle = selectedElement.siteName;
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||
}
|
||||
else {
|
||||
NSString *siteName = [self.siteField stringValue];
|
||||
if ([siteName length])
|
||||
// Performing action without content but a site name is written.
|
||||
[self createNewSite:siteName];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)copyContent:(NSString *)content {
|
||||
|
||||
[[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
if (![[NSPasteboard generalPasteboard] setString:content forType:NSPasteboardTypeString]) {
|
||||
wrn(@"Couldn't copy password to pasteboard.");
|
||||
return;
|
||||
}
|
||||
|
||||
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
[[self.selectedElement entityInContext:moc] use];
|
||||
[moc saveToStore];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)createNewSite:(NSString *)siteName {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
NSAlert *alert = [NSAlert new];
|
||||
[alert addButtonWithTitle:@"Create"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setMessageText:@"Create site?"];
|
||||
[alert setInformativeText:PearlString( @"Do you want to create a new site named:\n\n%@", siteName )];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertCreateSite];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)setElementSelectionIndexes:(NSIndexSet *)elementSelectionIndexes {
|
||||
|
||||
// First reset bounds.
|
||||
PearlMainQueue(^{
|
||||
NSUInteger selectedIndex = self.elementSelectionIndexes.firstIndex;
|
||||
if (selectedIndex != NSNotFound && selectedIndex < self.elements.count)
|
||||
[[self selectedView].animator setBoundsOrigin:NSZeroPoint];
|
||||
} );
|
||||
|
||||
_elementSelectionIndexes = elementSelectionIndexes;
|
||||
}
|
||||
|
||||
- (void)insertObject:(MPElementModel *)model inElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements insertObject:model atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeObjectFromElementsAtIndex:(NSUInteger)index {
|
||||
|
||||
[self.elements removeObjectAtIndex:index];
|
||||
}
|
||||
|
||||
@end
|
@ -1,380 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1080" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordDialogController">
|
||||
<connections>
|
||||
<outlet property="contentContainer" destination="143" id="214"/>
|
||||
<outlet property="siteCollectionView" destination="pr9-BO-vQV" id="Bnh-WQ-RaO"/>
|
||||
<outlet property="siteField" destination="182" id="224"/>
|
||||
<outlet property="userLabel" destination="216" id="223"/>
|
||||
<outlet property="window" destination="22" id="40"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application"/>
|
||||
<window title="Master Password" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="22" customClass="NSPanel">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" texturedBackground="YES"/>
|
||||
<rect key="contentRect" x="600" y="530" width="480" height="320"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<value key="minSize" type="size" width="480" height="320"/>
|
||||
<value key="maxSize" type="size" width="480" height="320"/>
|
||||
<view key="contentView" wantsLayer="YES" id="23">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="143">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="182">
|
||||
<rect key="frame" x="140" y="256" width="200" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="200" id="258"/>
|
||||
</constraints>
|
||||
<shadow key="shadow" blurRadius="2">
|
||||
<color key="color" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" placeholderString="Site name" usesSingleLineMode="YES" bezelStyle="round" id="185">
|
||||
<font key="font" metaFont="cellTitle"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="188"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="216">
|
||||
<rect key="frame" x="146" y="286" width="188" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="center" title="Maarten Billemont's password for:" usesSingleLineMode="YES" id="217">
|
||||
<font key="font" metaFont="palette"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tjI-mV-s8H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="248"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" id="mfh-QT-ClZ">
|
||||
<rect key="frame" x="1" y="1" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<collectionView selectable="YES" maxNumberOfColumns="1" id="pr9-BO-vQV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="478" height="246"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="secondaryBackgroundColor" name="controlAlternatingRowColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="jTN-Q9-Ajn" name="content" keyPath="arrangedObjects" id="dtF-fs-Fpe"/>
|
||||
<binding destination="-2" name="selectionIndexes" keyPath="elementSelectionIndexes" previousBinding="dtF-fs-Fpe" id="UFy-9F-18H"/>
|
||||
<outlet property="delegate" destination="-2" id="4cD-GP-imR"/>
|
||||
<outlet property="itemPrototype" destination="QBZ-sO-HQn" id="QAi-HN-YUc"/>
|
||||
</connections>
|
||||
</collectionView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="6vP-Im-BRg">
|
||||
<rect key="frame" x="-100" y="-100" width="233" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="vs6-1G-hvM">
|
||||
<rect key="frame" x="-100" y="-100" width="15" height="143"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tLu-3k-QiL">
|
||||
<rect key="frame" x="449" y="288" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="51o-8V-9eq">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="216" firstAttribute="top" secondItem="143" secondAttribute="top" constant="20" symbolic="YES" id="218"/>
|
||||
<constraint firstItem="182" firstAttribute="top" secondItem="216" secondAttribute="bottom" constant="8" symbolic="YES" id="221"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tjI-mV-s8H" secondAttribute="bottom" id="6y8-tJ-1sX"/>
|
||||
<constraint firstItem="tLu-3k-QiL" firstAttribute="top" secondItem="143" secondAttribute="top" constant="8" id="9h7-dN-MqZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tLu-3k-QiL" secondAttribute="trailing" constant="8" id="UQN-Ab-fIg"/>
|
||||
<constraint firstAttribute="centerX" secondItem="182" secondAttribute="centerX" id="W6t-BO-Njn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tjI-mV-s8H" secondAttribute="trailing" id="aKe-a9-Br8"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="leading" secondItem="143" secondAttribute="leading" id="d8F-JD-EhR"/>
|
||||
<constraint firstItem="tjI-mV-s8H" firstAttribute="top" secondItem="182" secondAttribute="bottom" constant="8" symbolic="YES" id="izG-uH-9BF"/>
|
||||
<constraint firstAttribute="centerX" secondItem="216" secondAttribute="centerX" id="mkv-5E-dy5"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="143" firstAttribute="leading" secondItem="23" secondAttribute="leading" id="145"/>
|
||||
<constraint firstItem="143" firstAttribute="bottom" secondItem="23" secondAttribute="bottom" id="147"/>
|
||||
<constraint firstItem="143" firstAttribute="trailing" secondItem="23" secondAttribute="trailing" id="148"/>
|
||||
<constraint firstItem="143" firstAttribute="top" secondItem="23" secondAttribute="top" id="150"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-2" id="39"/>
|
||||
</connections>
|
||||
</window>
|
||||
<collectionViewItem id="QBZ-sO-HQn" customClass="MPElementCollectionView">
|
||||
<connections>
|
||||
<outlet property="view" destination="bhu-Ky-PQq" id="jZh-jC-6bL"/>
|
||||
</connections>
|
||||
</collectionViewItem>
|
||||
<arrayController objectClassName="MPElementModel" id="jTN-Q9-Ajn">
|
||||
<connections>
|
||||
<binding destination="-2" name="contentArray" keyPath="self.elements" id="8Uz-14-YG0"/>
|
||||
</connections>
|
||||
</arrayController>
|
||||
<box autoresizesSubviews="NO" wantsLayer="YES" boxType="custom" borderType="none" titlePosition="noTitle" id="bhu-Ky-PQq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<view key="contentView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="960" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xwJ-Pu-glP">
|
||||
<rect key="frame" x="6" y="35" width="60" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="apple.com" usesSingleLineMode="YES" id="ymH-M0-M5d">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.siteName" id="4as-ow-WbD"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Cn5-nt-e6X">
|
||||
<rect key="frame" x="362" y="35" width="111" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="lhunath@lyndir.com" usesSingleLineMode="YES" id="Px4-pS-kwG">
|
||||
<font key="font" size="12" name="Exo2.0-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.loginName" id="C2s-1d-p2H">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="a1n-Sf-Mw6">
|
||||
<rect key="frame" x="6" y="8" width="206" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="RutuTutnTeni4," id="7jb-Fa-xX3">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.content" id="41c-PF-OeH">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mp4-r1-7Xg">
|
||||
<rect key="frame" x="440" y="8" width="33" height="38"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.59999999999999998" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="12" id="Vb9-nO-cWY">
|
||||
<font key="font" size="24" name="SourceCodePro-Light"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.uses" id="gSt-Nd-lVa">
|
||||
<dictionary key="options">
|
||||
<bool key="NSContinuouslyUpdatesValue" value="YES"/>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<box autoresizesSubviews="NO" horizontalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="tsT-Xh-Nxb">
|
||||
<rect key="frame" x="477" y="0.0" width="5" height="61"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<font key="titleFont" metaFont="system"/>
|
||||
</box>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vEl-aL-Qd4">
|
||||
<rect key="frame" x="791" y="27" width="167" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="lhunath@lyndir.com" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sl3-bH-Hh2">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateLoginName:" target="QBZ-sO-HQn" id="pJI-k8-LRl"/>
|
||||
<binding destination="QBZ-sO-HQn" name="title" keyPath="representedObject.loginName" id="uaP-Y1-bz6">
|
||||
<dictionary key="options">
|
||||
<string key="NSNullPlaceholder">Click to set login name</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</button>
|
||||
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="d2a-pG-7CW">
|
||||
<rect key="frame" x="528" y="31" width="127" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Long Password" bezelStyle="rounded" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" selectedItem="7Bj-S7-WSd" id="RZo-c7-kqA">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" title="OtherViews" id="mQN-XZ-YKz">
|
||||
<items>
|
||||
<menuItem title="Long Password" state="on" id="7Bj-S7-WSd"/>
|
||||
<menuItem title="Item 2" id="WUd-69-IBV"/>
|
||||
<menuItem title="Item 3" id="pgH-yZ-G0J"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="contentValues" keyPath="representedObject.typeNames" id="eyo-f9-MwY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="selectedIndex" keyPath="representedObject.typeIndex" previousBinding="eyo-f9-MwY" id="dpI-HX-GpX"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="npg-mh-AfY">
|
||||
<rect key="frame" x="486" y="36" width="38" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Type:" id="U2E-DE-2j4">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hqw-ZP-4c1">
|
||||
<rect key="frame" x="486" y="11" width="59" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Number:" id="CDU-Ah-QDj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="xlz-gk-Gwc"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JPX-xQ-VKZ">
|
||||
<rect key="frame" x="565" y="6" width="19" height="27"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<stepperCell key="cell" alignment="left" minValue="1" maxValue="100" doubleValue="1" autorepeat="NO" id="ELG-fy-nVF"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="3FO-ks-R7U"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="awJ-Vg-RUn"/>
|
||||
</connections>
|
||||
</stepper>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kZI-sG-dEn">
|
||||
<rect key="frame" x="549" y="11" width="13" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="1" id="EUB-gJ-7Db">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="counterHidden" id="ZFX-79-eAY"/>
|
||||
<binding destination="QBZ-sO-HQn" name="value" keyPath="representedObject.counter" id="20y-tn-B5k"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qOt-Rp-G9T">
|
||||
<rect key="frame" x="877" y="2" width="81" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Delete" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QCU-VC-W0u">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="delete:" target="QBZ-sO-HQn" id="mLJ-JY-5fz"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5YU-4W-4gz">
|
||||
<rect key="frame" x="727" y="2" width="150" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Change Password" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NQY-Oo-Eid">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="updateContent:" target="QBZ-sO-HQn" id="J8f-vx-10A"/>
|
||||
<binding destination="QBZ-sO-HQn" name="hidden" keyPath="updateContentHidden" id="UwG-p5-kH4"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="bzg-90-kmh">
|
||||
<rect key="frame" x="748" y="36" width="43" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Login:" id="uxE-6c-RjC">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="qOt-Rp-G9T" secondAttribute="centerY" id="6xp-tI-BkX"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="7kp-OB-3BI"/>
|
||||
<constraint firstItem="kZI-sG-dEn" firstAttribute="leading" secondItem="hqw-ZP-4c1" secondAttribute="trailing" constant="8" symbolic="YES" id="8qK-Et-c1F"/>
|
||||
<constraint firstItem="d2a-pG-7CW" firstAttribute="leading" secondItem="npg-mh-AfY" secondAttribute="trailing" constant="8" symbolic="YES" id="F6X-FD-kEX"/>
|
||||
<constraint firstItem="Cn5-nt-e6X" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="FWS-tY-KkM"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="top" secondItem="npg-mh-AfY" secondAttribute="bottom" constant="8" symbolic="YES" id="GuG-5I-quA"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="leading" secondItem="tsT-Xh-Nxb" secondAttribute="trailing" constant="8" id="Hzf-XZ-auZ"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="Cn5-nt-e6X" secondAttribute="trailing" constant="8" id="LjD-10-tVU"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" id="ODH-Nx-QdY"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="centerY" secondItem="5YU-4W-4gz" secondAttribute="centerY" id="PdB-X5-eqF"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="QAM-jm-t0y"/>
|
||||
<constraint firstAttribute="centerY" secondItem="tsT-Xh-Nxb" secondAttribute="centerY" id="Rpi-lc-dZ1"/>
|
||||
<constraint firstItem="tsT-Xh-Nxb" firstAttribute="leading" secondItem="mp4-r1-7Xg" secondAttribute="trailing" constant="8" id="Xfc-Jq-2Rb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="vEl-aL-Qd4" secondAttribute="trailing" constant="8" id="ZZu-AS-C07"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tsT-Xh-Nxb" secondAttribute="bottom" id="ds1-7i-B7I"/>
|
||||
<constraint firstItem="a1n-Sf-Mw6" firstAttribute="leading" secondItem="bhu-Ky-PQq" secondAttribute="leading" constant="8" id="e3g-2s-yee"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="ftr-2Z-9J0"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="centerY" secondItem="d2a-pG-7CW" secondAttribute="centerY" id="g9a-r0-EOo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mp4-r1-7Xg" secondAttribute="bottom" constant="8" id="jCW-5H-6pT"/>
|
||||
<constraint firstAttribute="centerX" secondItem="tsT-Xh-Nxb" secondAttribute="centerX" id="kx6-g0-jUW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="a1n-Sf-Mw6" secondAttribute="bottom" constant="8" id="mWW-rt-kl2"/>
|
||||
<constraint firstItem="npg-mh-AfY" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="n7Z-EF-Dcm"/>
|
||||
<constraint firstItem="qOt-Rp-G9T" firstAttribute="leading" secondItem="5YU-4W-4gz" secondAttribute="trailing" constant="12" symbolic="YES" id="uWm-hE-itO"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qOt-Rp-G9T" secondAttribute="trailing" constant="8" id="x6J-1l-rU4"/>
|
||||
<constraint firstItem="hqw-ZP-4c1" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="xZ7-Mc-9dq"/>
|
||||
<constraint firstItem="vEl-aL-Qd4" firstAttribute="leading" secondItem="bzg-90-kmh" secondAttribute="trailing" constant="8" symbolic="YES" id="z7h-om-WAV"/>
|
||||
<constraint firstItem="xwJ-Pu-glP" firstAttribute="top" secondItem="bhu-Ky-PQq" secondAttribute="top" constant="8" id="z8k-ot-NjU"/>
|
||||
<constraint firstItem="bzg-90-kmh" firstAttribute="centerY" secondItem="vEl-aL-Qd4" secondAttribute="centerY" id="zbz-Qg-uHO"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="centerY" secondItem="kZI-sG-dEn" secondAttribute="centerY" id="zcO-M3-gyr"/>
|
||||
<constraint firstItem="JPX-xQ-VKZ" firstAttribute="leading" secondItem="kZI-sG-dEn" secondAttribute="trailing" constant="8" symbolic="YES" id="zvB-Vk-IL2"/>
|
||||
</constraints>
|
||||
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
|
||||
<color key="fillColor" name="selectedControlColor" catalog="System" colorSpace="catalog"/>
|
||||
<connections>
|
||||
<binding destination="QBZ-sO-HQn" name="transparent" keyPath="selected" id="Tpz-Rp-lA7">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</box>
|
||||
</objects>
|
||||
</document>
|
@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6154.17" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1080" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6154.17"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPPasswordWindowController">
|
||||
@ -25,7 +24,7 @@
|
||||
<windowCollectionBehavior key="collectionBehavior" transient="YES" ignoresCycle="YES" fullScreenAuxiliary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="0.0" y="0.0" width="640" height="530"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="640" height="530"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@ -66,14 +65,13 @@
|
||||
<outlet property="delegate" destination="-2" id="egd-Ny-IEz"/>
|
||||
</connections>
|
||||
</secureTextField>
|
||||
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="31" horizontalPageScroll="10" verticalLineScroll="31" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="Bme-XK-MMc" userLabel="Sites Table">
|
||||
<scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="35" horizontalPageScroll="10" verticalLineScroll="35" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="Bme-XK-MMc" userLabel="Sites Table">
|
||||
<rect key="frame" x="64" y="80" width="512" height="132"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="e11-59-xSS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="512" height="132"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="29" rowSizeStyle="automatic" viewBased="YES" floatsGroupRows="NO" id="xvJ-5c-vDp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="515" height="132"/>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" selectionHighlightStyle="sourceList" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="33" rowSizeStyle="automatic" viewBased="YES" floatsGroupRows="NO" id="xvJ-5c-vDp">
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="calibratedRGB"/>
|
||||
@ -93,11 +91,11 @@
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="xQb-o5-M5U">
|
||||
<rect key="frame" x="1" y="1" width="512" height="29"/>
|
||||
<rect key="frame" x="1" y="1" width="512" height="33"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="ydd-Rv-tra">
|
||||
<rect key="frame" x="-2" y="0.0" width="516" height="29"/>
|
||||
<rect key="frame" x="-2" y="2" width="516" height="29"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.80000000000000004" colorSpace="calibratedWhite"/>
|
||||
@ -118,11 +116,20 @@
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="ydd-Rv-tra" secondAttribute="bottom" id="5YP-zp-i6Y"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ydd-Rv-tra" secondAttribute="bottom" constant="2" id="5YP-zp-i6Y"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ydd-Rv-tra" secondAttribute="trailing" id="GcM-cT-kQi"/>
|
||||
<constraint firstItem="ydd-Rv-tra" firstAttribute="leading" secondItem="xQb-o5-M5U" secondAttribute="leading" id="Wot-L7-qhr"/>
|
||||
<constraint firstItem="ydd-Rv-tra" firstAttribute="top" secondItem="xQb-o5-M5U" secondAttribute="top" id="eZT-Sd-wW5"/>
|
||||
<constraint firstItem="ydd-Rv-tra" firstAttribute="top" secondItem="xQb-o5-M5U" secondAttribute="top" constant="2" id="eZT-Sd-wW5"/>
|
||||
</constraints>
|
||||
<backgroundFilters>
|
||||
<ciFilter name="CIGloom">
|
||||
<configuration>
|
||||
<null key="inputImage"/>
|
||||
<real key="inputIntensity" value="1"/>
|
||||
<real key="inputRadius" value="10"/>
|
||||
</configuration>
|
||||
</ciFilter>
|
||||
</backgroundFilters>
|
||||
<connections>
|
||||
<outlet property="textField" destination="ydd-Rv-tra" id="lMV-D4-Ilq"/>
|
||||
</connections>
|
||||
@ -324,11 +331,9 @@
|
||||
</button>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="NGk-Io-Buc">
|
||||
<rect key="frame" x="20" y="323" width="600" height="163"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XUV-zU-Y9c">
|
||||
<rect key="frame" x="96" y="45" width="408" height="73"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@ -353,7 +358,7 @@
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.content" id="iXY-0g-zZW"/>
|
||||
<binding destination="mcS-ik-b0n" name="value" keyPath="selection.contentDisplay" id="djg-i5-pwt"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
@ -364,7 +369,6 @@
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rhm-sC-xFS">
|
||||
<rect key="frame" x="80" y="220" width="481" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="0.70000000000000007" colorSpace="calibratedWhite"/>
|
||||
@ -384,7 +388,6 @@
|
||||
</textField>
|
||||
<button translatesAutoresizingMaskIntoConstraints="NO" id="Aue-Zx-6Mf">
|
||||
<rect key="frame" x="588" y="478" width="32" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="icon_gear" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="i8r-9N-vcQ">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
@ -397,7 +400,6 @@
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qal-PP-YtO">
|
||||
<rect key="frame" x="399" y="1" width="23" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@ -408,6 +410,11 @@
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="pgW-yB-Zx3">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="mcS-ik-b0n" name="hidden2" keyPath="canRemove" previousBinding="pgW-yB-Zx3" id="XHu-Py-efU">
|
||||
<dictionary key="options">
|
||||
<integer key="NSMultipleValuesPlaceholder" value="-1"/>
|
||||
@ -417,26 +424,25 @@
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="pgW-yB-Zx3">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9b3-wy-KBb">
|
||||
<rect key="frame" x="309" y="2" width="22" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="⌘T" id="HFM-Bk-akx">
|
||||
<font key="font" size="11" name="LucidaGrande"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="highlightColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="CG8-3H-uiD">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="mcS-ik-b0n" name="hidden2" keyPath="canRemove" previousBinding="CG8-3H-uiD" id="n0n-ZB-u5H">
|
||||
<dictionary key="options">
|
||||
<integer key="NSMultipleValuesPlaceholder" value="-1"/>
|
||||
@ -446,16 +452,10 @@
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="CG8-3H-uiD">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ido-NQ-3MY">
|
||||
<rect key="frame" x="197" y="1" width="22" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@ -466,6 +466,11 @@
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="b3W-u1-1A2">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="mcS-ik-b0n" name="hidden2" keyPath="canRemove" previousBinding="b3W-u1-1A2" id="gTg-Go-ELg">
|
||||
<dictionary key="options">
|
||||
<integer key="NSMultipleValuesPlaceholder" value="-1"/>
|
||||
@ -475,26 +480,25 @@
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="b3W-u1-1A2">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uol-dE-I8H">
|
||||
<rect key="frame" x="309" y="70" width="22" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="⌘P" id="MyN-x6-dMk">
|
||||
<font key="font" size="11" name="LucidaGrande"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="highlightColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="MLo-fO-mx5">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="mcS-ik-b0n" name="hidden2" keyPath="canRemove" previousBinding="MLo-fO-mx5" id="vpQ-kw-9ZS">
|
||||
<dictionary key="options">
|
||||
<integer key="NSMultipleValuesPlaceholder" value="-1"/>
|
||||
@ -513,22 +517,16 @@
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
<binding destination="-2" name="hidden" keyPath="alternatePressed" id="MLo-fO-mx5">
|
||||
<dictionary key="options">
|
||||
<string key="NSValueTransformerName">NSNegateBoolean</string>
|
||||
</dictionary>
|
||||
</binding>
|
||||
</connections>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gAU-xs-aae">
|
||||
<rect key="frame" x="595" y="460" width="19" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<shadow key="shadow" blurRadius="1">
|
||||
<size key="offset" width="0.0" height="1"/>
|
||||
<color key="color" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</shadow>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="⌘," id="Xm1-qb-6EP">
|
||||
<font key="font" size="11" name="LucidaGrande"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="highlightColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
@ -606,7 +604,6 @@
|
||||
<subviews>
|
||||
<matrix verticalHuggingPriority="750" allowsEmptySelection="NO" autorecalculatesCellSize="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3fr-Fd-pxx">
|
||||
<rect key="frame" x="18" y="14" width="348" height="158"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="cellSize" width="179" height="18"/>
|
||||
<size key="intercellSpacing" width="4" height="2"/>
|
||||
|
@ -8,6 +8,29 @@
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Master Password</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>mpsites</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Master Password sites</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Owner</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>com.lyndir.lhunath.MasterPassword.sites</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@ -24,6 +47,19 @@
|
||||
<string>[auto]</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.lyndir.lhunath.MasterPassword</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.lyndir.lhunath.MasterPassword</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>[auto]</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
@ -38,5 +74,27 @@
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Master Password sites</string>
|
||||
<key>UTTypeIconFile</key>
|
||||
<string></string>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.lyndir.lhunath.MasterPassword.sites</string>
|
||||
<key>UTTypeSize320IconFile</key>
|
||||
<string></string>
|
||||
<key>UTTypeSize64IconFile</key>
|
||||
<string></string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>mpsites</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -13,7 +13,6 @@
|
||||
93D3970BCF85F7902E611168 /* PearlProfiler.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39DB3A8ADED08C39A6228 /* PearlProfiler.m */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39C5789EFA607CF788082 /* MPElementModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39E73BF5CBF8E5B005CD3 /* MPElementModel.m */; };
|
||||
93D39C7C2BE7C0E0763B0177 /* MPElementCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D394495528B10D1B61A2C3 /* MPElementCollectionView.m */; };
|
||||
93D39D304F73B3BBA031522A /* PearlProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D394EEFF5BF555A55AF361 /* PearlProfiler.h */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */; };
|
||||
@ -64,10 +63,7 @@
|
||||
DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB11724A667003798D8 /* MPUserEntity.m */; };
|
||||
DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */; };
|
||||
DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB61724A667003798D8 /* MPMacConfig.m */; };
|
||||
DA5E5D051724A667003798D8 /* MPPasswordDialogController.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */; };
|
||||
DA5E5D061724A667003798D8 /* MPPasswordDialogController.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */; };
|
||||
DA5E5D081724A667003798D8 /* MasterPassword.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */; };
|
||||
DA5E5D091724A667003798D8 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CC01724A667003798D8 /* Credits.rtf */; };
|
||||
DA5E5D0A1724A667003798D8 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CC21724A667003798D8 /* InfoPlist.strings */; };
|
||||
DA5E5D0B1724A667003798D8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA5E5CC41724A667003798D8 /* MainMenu.xib */; };
|
||||
DA5E5D0C1724A667003798D8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5CC61724A667003798D8 /* main.m */; };
|
||||
@ -312,9 +308,7 @@
|
||||
93D39240B5143E01F0B75E96 /* MPElementModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementModel.h; sourceTree = "<group>"; };
|
||||
93D392C3918763B3B72CF366 /* MPPasswordWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindowController.h; sourceTree = "<group>"; };
|
||||
93D393B97158D7BE9332EA53 /* NSDictionary+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D394495528B10D1B61A2C3 /* MPElementCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementCollectionView.m; sourceTree = "<group>"; };
|
||||
93D394EEFF5BF555A55AF361 /* PearlProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PearlProfiler.h; path = ../../../External/Pearl/Pearl/PearlProfiler.h; sourceTree = "<group>"; };
|
||||
93D3960D320FF8A072B092E3 /* MPElementCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementCollectionView.h; sourceTree = "<group>"; };
|
||||
93D396D04E57792A54D437AC /* NSArray+Indexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+Indexing.h"; sourceTree = "<group>"; };
|
||||
93D3977484534E99F9BA579D /* MPPasswordWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordWindow.h; sourceTree = "<group>"; };
|
||||
93D39A57A7823DE98A0FF83C /* MPPasswordWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordWindowController.m; sourceTree = "<group>"; };
|
||||
@ -393,13 +387,9 @@
|
||||
DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacAppDelegate.m; sourceTree = "<group>"; };
|
||||
DA5E5CB51724A667003798D8 /* MPMacConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMacConfig.h; sourceTree = "<group>"; };
|
||||
DA5E5CB61724A667003798D8 /* MPMacConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMacConfig.m; sourceTree = "<group>"; };
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordDialogController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasswordDialogController.h; sourceTree = "<group>"; };
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasswordDialogController.m; sourceTree = "<group>"; };
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPPasswordDialogController.xib; sourceTree = "<group>"; };
|
||||
DA5E5CBA1724A667003798D8 /* MasterPassword-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MasterPassword-Info.plist"; sourceTree = "<group>"; };
|
||||
DA5E5CBE1724A667003798D8 /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||
DA5E5CC11724A667003798D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
|
||||
DA5E5CC31724A667003798D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
DA5E5CC51724A667003798D8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
DA5E5CC61724A667003798D8 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
@ -1206,19 +1196,13 @@
|
||||
DA5E5CB41724A667003798D8 /* MPMacAppDelegate.m */,
|
||||
DA5E5CB51724A667003798D8 /* MPMacConfig.h */,
|
||||
DA5E5CB61724A667003798D8 /* MPMacConfig.m */,
|
||||
DA5E5CB71724A667003798D8 /* MPPasswordDialogController.h */,
|
||||
DA5E5CB81724A667003798D8 /* MPPasswordDialogController.m */,
|
||||
DA5E5CB91724A667003798D8 /* MPPasswordDialogController.xib */,
|
||||
DA5E5CBA1724A667003798D8 /* MasterPassword-Info.plist */,
|
||||
DA5E5CBE1724A667003798D8 /* MasterPassword-Prefix.pch */,
|
||||
DA5E5CBF1724A667003798D8 /* MasterPassword.entitlements */,
|
||||
DA5E5CC01724A667003798D8 /* Credits.rtf */,
|
||||
DA5E5CC21724A667003798D8 /* InfoPlist.strings */,
|
||||
DA5E5CC41724A667003798D8 /* MainMenu.xib */,
|
||||
DA5E5CC61724A667003798D8 /* main.m */,
|
||||
DA0933C91747A56A00DE1CEF /* MPInitialWindow.xib */,
|
||||
93D394495528B10D1B61A2C3 /* MPElementCollectionView.m */,
|
||||
93D3960D320FF8A072B092E3 /* MPElementCollectionView.h */,
|
||||
93D39E73BF5CBF8E5B005CD3 /* MPElementModel.m */,
|
||||
93D39240B5143E01F0B75E96 /* MPElementModel.h */,
|
||||
DA2508F019511D3600AC23F1 /* MPPasswordWindowController.xib */,
|
||||
@ -2396,9 +2380,7 @@
|
||||
DACA296F1705DF81002C6C22 /* Crashlytics.plist in Resources */,
|
||||
DACA29731705E1A8002C6C22 /* ciphers.plist in Resources */,
|
||||
DACA29741705E1A8002C6C22 /* dictionary.lst in Resources */,
|
||||
DA5E5D061724A667003798D8 /* MPPasswordDialogController.xib in Resources */,
|
||||
DA5E5D081724A667003798D8 /* MasterPassword.entitlements in Resources */,
|
||||
DA5E5D091724A667003798D8 /* Credits.rtf in Resources */,
|
||||
DA5E5D0A1724A667003798D8 /* InfoPlist.strings in Resources */,
|
||||
DA5E5D0B1724A667003798D8 /* MainMenu.xib in Resources */,
|
||||
DA5E5D551724F9C8003798D8 /* MasterPassword.iconset in Resources */,
|
||||
@ -2479,10 +2461,8 @@
|
||||
DA5E5D021724A667003798D8 /* MPUserEntity.m in Sources */,
|
||||
DA5E5D031724A667003798D8 /* MPMacAppDelegate.m in Sources */,
|
||||
DA5E5D041724A667003798D8 /* MPMacConfig.m in Sources */,
|
||||
DA5E5D051724A667003798D8 /* MPPasswordDialogController.m in Sources */,
|
||||
DA5E5D0C1724A667003798D8 /* main.m in Sources */,
|
||||
DA5E5D0D1724A667003798D8 /* MasterPassword.xcdatamodeld in Sources */,
|
||||
93D39C7C2BE7C0E0763B0177 /* MPElementCollectionView.m in Sources */,
|
||||
93D39C5789EFA607CF788082 /* MPElementModel.m in Sources */,
|
||||
93D39F833DEC1C89B2F795AC /* MPPasswordWindowController.m in Sources */,
|
||||
93D390C676DF52DA7E459F19 /* MPPasswordWindow.m in Sources */,
|
||||
@ -2560,14 +2540,6 @@
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
DA5E5CC01724A667003798D8 /* Credits.rtf */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
DA5E5CC11724A667003798D8 /* en */,
|
||||
);
|
||||
name = Credits.rtf;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DA5E5CC21724A667003798D8 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
@ -2798,7 +2770,6 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -2818,7 +2789,6 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = MasterPassword.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -15,5 +15,7 @@
|
||||
<array>
|
||||
<string>HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.Mac</string>
|
||||
</array>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,29 +0,0 @@
|
||||
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw9840\paperh8400
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
|
||||
|
||||
\f0\b\fs24 \cf0 Engineering:
|
||||
\b0 \
|
||||
Some people\
|
||||
\
|
||||
|
||||
\b Human Interface Design:
|
||||
\b0 \
|
||||
Some other people\
|
||||
\
|
||||
|
||||
\b Testing:
|
||||
\b0 \
|
||||
Hopefully not nobody\
|
||||
\
|
||||
|
||||
\b Documentation:
|
||||
\b0 \
|
||||
Whoever\
|
||||
\
|
||||
|
||||
\b With special thanks to:
|
||||
\b0 \
|
||||
Mom\
|
||||
}
|
@ -17,8 +17,6 @@
|
||||
<connections>
|
||||
<outlet property="createUserItem" destination="757" id="763"/>
|
||||
<outlet property="deleteUserItem" destination="ZgZ-p2-463" id="smU-PF-mKA"/>
|
||||
<outlet property="dialogStyleHUD" destination="768" id="771"/>
|
||||
<outlet property="dialogStyleRegular" destination="767" id="772"/>
|
||||
<outlet property="hidePasswordsItem" destination="9G7-17-PzY" id="qPX-VT-jVx"/>
|
||||
<outlet property="lockItem" destination="720" id="726"/>
|
||||
<outlet property="openAtLoginItem" destination="785" id="788"/>
|
||||
@ -97,7 +95,7 @@
|
||||
<action selector="togglePreference:" target="494" id="xgz-pN-csV"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Don't show site passwords (hold alt ⌥ to reveal them)." enabled="NO" id="HnK-hQ-cM9">
|
||||
<menuItem title="Remember the password while the application is running." enabled="NO" id="HnK-hQ-cM9">
|
||||
<attributedString key="attributedTitle">
|
||||
<fragment content="Remember the password while the application is running.">
|
||||
<attributes>
|
||||
@ -142,25 +140,53 @@
|
||||
</attributedString>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Password Dialog Style" id="765">
|
||||
<menuItem title="Export Sites" id="r1P-hr-mh5">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Password Dialog Style" id="766">
|
||||
<menu key="submenu" title="Export Sites" id="fnk-gK-yCi">
|
||||
<items>
|
||||
<menuItem title="Regular" id="767">
|
||||
<menuItem title="Secure Export" id="06i-og-eLt">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="togglePreference:" target="494" id="773"/>
|
||||
<action selector="exportSitesSecure:" target="494" id="LVH-es-imA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="HUD" tag="1" id="768">
|
||||
<menuItem title="Your passwords are not visible." enabled="NO" id="ybY-P3-eao">
|
||||
<attributedString key="attributedTitle">
|
||||
<fragment content="Your passwords are not visible.">
|
||||
<attributes>
|
||||
<font key="NSFont" size="12" name="Helvetica"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="Reveal Passwords" id="fMG-TT-bTn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="togglePreference:" target="494" id="774"/>
|
||||
<action selector="exportSitesReveal:" target="494" id="1IW-VT-Oeu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Keep this file secure or delete it when you're done with it!" enabled="NO" id="cQu-oR-SUa">
|
||||
<attributedString key="attributedTitle">
|
||||
<fragment content="Keep this file secure or delete it when you're done with it!">
|
||||
<attributes>
|
||||
<font key="NSFont" size="12" name="Helvetica"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Import Sites..." id="EFK-zt-EvJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="importSites:" target="494" id="CNv-4j-036"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Advanced" id="776">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Advanced" id="777">
|
||||
|
@ -182,7 +182,7 @@
|
||||
dispatch_group_enter( importPasswordGroup );
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[PearlAlert showAlertWithTitle:@"Import File's Master Password"
|
||||
message:PearlString( @"%@'s export was done using a different master password.\n"
|
||||
message:strf( @"%@'s export was done using a different master password.\n"
|
||||
@"Enter that master password to unlock the exported data.", userName )
|
||||
viewStyle:UIAlertViewStyleSecureTextInput
|
||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert_, NSInteger buttonIndex_) {
|
||||
@ -405,6 +405,7 @@
|
||||
[PearlInfoPlist get].CFBundleShortVersionString,
|
||||
[PearlInfoPlist get].CFBundleVersion );
|
||||
|
||||
NSString *exportedSites = [self exportSitesRevealPasswords:revealPasswords];
|
||||
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
|
||||
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user