Reformat.
This commit is contained in:
@@ -12,16 +12,16 @@
|
||||
|
||||
@interface MPAppDelegate : MPAppDelegate_Shared<NSApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) NSStatusItem *statusItem;
|
||||
@property (nonatomic, strong) MPPasswordWindowController *passwordWindow;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *showItem;
|
||||
@property (nonatomic, strong) IBOutlet NSMenu *statusMenu;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *useICloudItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *rememberPasswordItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *savePasswordItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *createUserItem;
|
||||
@property (nonatomic, weak) IBOutlet NSMenuItem *usersItem;
|
||||
@property(nonatomic, strong) NSStatusItem *statusItem;
|
||||
@property(nonatomic, strong) MPPasswordWindowController *passwordWindow;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *lockItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *showItem;
|
||||
@property(nonatomic, strong) IBOutlet NSMenu *statusMenu;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *useICloudItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *rememberPasswordItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *savePasswordItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *createUserItem;
|
||||
@property(nonatomic, weak) IBOutlet NSMenuItem *usersItem;
|
||||
|
||||
- (IBAction)activate:(id)sender;
|
||||
- (IBAction)togglePreference:(NSMenuItem *)sender;
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#import "MPAppDelegate_Store.h"
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
|
||||
@implementation MPAppDelegate
|
||||
|
||||
@synthesize statusItem;
|
||||
@synthesize lockItem;
|
||||
@synthesize showItem;
|
||||
@@ -26,28 +26,28 @@
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
||||
static EventHotKeyID MPShowHotKey = {.signature = 'show', .id = 1};
|
||||
static EventHotKeyID MPLockHotKey = {.signature = 'lock', .id = 1};
|
||||
static EventHotKeyID MPShowHotKey = { .signature = 'show', .id = 1 };
|
||||
static EventHotKeyID MPLockHotKey = { .signature = 'lock', .id = 1 };
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (void)initialize {
|
||||
|
||||
static dispatch_once_t initialize;
|
||||
dispatch_once(&initialize, ^{
|
||||
dispatch_once( &initialize, ^{
|
||||
[MPMacConfig get];
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
[PearlLogger get].printLevel = PearlLogLevelDebug;//Trace;
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
} );
|
||||
}
|
||||
|
||||
static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
|
||||
|
||||
// Extract the hotkey ID.
|
||||
EventHotKeyID hotKeyID;
|
||||
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID,
|
||||
NULL, sizeof(hotKeyID), NULL, &hotKeyID);
|
||||
GetEventParameter( theEvent, kEventParamDirectObject, typeEventHotKeyID,
|
||||
NULL, sizeof(hotKeyID), NULL, &hotKeyID );
|
||||
|
||||
// Check which hotkey this was.
|
||||
if (hotKeyID.signature == MPShowHotKey.signature && hotKeyID.id == MPShowHotKey.id) {
|
||||
@@ -63,7 +63,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
}
|
||||
|
||||
- (void)updateUsers {
|
||||
|
||||
|
||||
[[[self.usersItem submenu] itemArray] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if (idx > 1)
|
||||
[[self.usersItem submenu] removeItem:obj];
|
||||
@@ -82,34 +82,34 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
self.createUserItem.title = @"New User";
|
||||
self.createUserItem.enabled = YES;
|
||||
self.createUserItem.toolTip = nil;
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPUserEntity class])];
|
||||
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO]];
|
||||
NSArray *users = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
|
||||
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
|
||||
NSArray *users = [moc executeFetchRequest:fetchRequest error:&error];
|
||||
if (!users)
|
||||
err(@"Failed to load users: %@", error);
|
||||
|
||||
err(@"Failed to load users: %@", error);
|
||||
|
||||
if (![users count]) {
|
||||
NSMenuItem *noUsersItem = [self.usersItem.submenu addItemWithTitle:@"No users" action:NULL keyEquivalent:@""];
|
||||
noUsersItem.enabled = NO;
|
||||
noUsersItem.toolTip = @"Use the iOS app to create users and make sure iCloud is enabled in its preferences as well. "
|
||||
@"Then give iCloud some time to sync the new user to your Mac.";
|
||||
@"Then give iCloud some time to sync the new user to your Mac.";
|
||||
}
|
||||
|
||||
|
||||
for (MPUserEntity *user in users) {
|
||||
NSMenuItem *userItem = [[NSMenuItem alloc] initWithTitle:user.name action:@selector(selectUser:) keyEquivalent:@""];
|
||||
[userItem setTarget:self];
|
||||
[userItem setRepresentedObject:[user objectID]];
|
||||
[[self.usersItem submenu] addItem:userItem];
|
||||
|
||||
|
||||
if ([user.name isEqualToString:[MPMacConfig get].usedUserName])
|
||||
[self selectUser:userItem];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)selectUser:(NSMenuItem *)item {
|
||||
|
||||
|
||||
self.activeUser = (MPUserEntity *)[[MPAppDelegate managedObjectContextForThreadIfReady] objectRegisteredForID:[item representedObject]];
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
- (IBAction)activate:(id)sender {
|
||||
|
||||
if (!self.activeUser)
|
||||
// No user, can't activate.
|
||||
// No user, can't activate.
|
||||
return;
|
||||
|
||||
if ([[NSApplication sharedApplication] isActive])
|
||||
@@ -152,7 +152,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
}
|
||||
|
||||
- (IBAction)signOut:(id)sender {
|
||||
|
||||
|
||||
[self signOutAnimated:YES];
|
||||
}
|
||||
|
||||
@@ -163,8 +163,8 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (void)didUpdateConfigForKey:(SEL)configKey fromValue:(id)oldValue {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPCheckConfigNotification
|
||||
object:NSStringFromSelector(configKey) userInfo:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:MPCheckConfigNotification object:NSStringFromSelector( configKey ) userInfo:nil];
|
||||
}
|
||||
|
||||
#pragma mark - NSApplicationDelegate
|
||||
@@ -176,17 +176,17 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
__weak id weakSelf = self;
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
[weakSelf updateMenuItems];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
[weakSelf updateMenuItems];
|
||||
} forKeyPath:@"activeUser" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
} forKeyPath:@"activeUser" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
|
||||
// Status item.
|
||||
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||
self.statusItem.image = [NSImage imageNamed:@"menu-icon"];
|
||||
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||
self.statusItem.image = [NSImage imageNamed:@"menu-icon"];
|
||||
self.statusItem.highlightMode = YES;
|
||||
self.statusItem.target = self;
|
||||
self.statusItem.action = @selector(showMenu);
|
||||
self.statusItem.target = self;
|
||||
self.statusItem.action = @selector(showMenu);
|
||||
|
||||
__weak MPAppDelegate *wSelf = self;
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
@@ -201,33 +201,33 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
[MPMacConfig get].usedUserName = activeUser.name;
|
||||
} forKeyPath:@"activeUserObjectID" options:0 context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidChangeNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil
|
||||
usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:UbiquityManagedStoreDidImportChangesNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
[self updateUsers];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPCheckConfigNotification object:nil queue:nil usingBlock:
|
||||
^(NSNotification *note) {
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState;
|
||||
self.savePasswordItem.state = [MPAppDelegate get].activeUser.saveKey? NSOnState: NSOffState;
|
||||
}];
|
||||
^(NSNotification *note) {
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState;
|
||||
self.savePasswordItem.state = [MPAppDelegate get].activeUser.saveKey? NSOnState: NSOffState;
|
||||
}];
|
||||
[self updateUsers];
|
||||
|
||||
// Global hotkey.
|
||||
EventHotKeyRef hotKeyRef;
|
||||
EventTypeSpec hotKeyEvents[1] = {{.eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed}};
|
||||
OSStatus status = InstallApplicationEventHandler(NewEventHandlerUPP(MPHotKeyHander), GetEventTypeCount(hotKeyEvents),
|
||||
hotKeyEvents,
|
||||
(__bridge void *)self, NULL);
|
||||
EventTypeSpec hotKeyEvents[1] = { { .eventClass = kEventClassKeyboard, .eventKind = kEventHotKeyPressed } };
|
||||
OSStatus status = InstallApplicationEventHandler(NewEventHandlerUPP( MPHotKeyHander ), GetEventTypeCount( hotKeyEvents ),
|
||||
hotKeyEvents,
|
||||
(__bridge void *)self, NULL);
|
||||
if (status != noErr)
|
||||
err(@"Error installing application event handler: %d", status);
|
||||
status = RegisterEventHotKey(35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef);
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + cmdKey, MPShowHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'show' hotkey: %d", status);
|
||||
status = RegisterEventHotKey(35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef);
|
||||
status = RegisterEventHotKey( 35 /* p */, controlKey + optionKey + cmdKey, MPLockHotKey, GetApplicationEventTarget(), 0, &hotKeyRef );
|
||||
if (status != noErr)
|
||||
err(@"Error registering 'lock' hotkey: %d", status);
|
||||
}
|
||||
@@ -235,50 +235,55 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
- (void)updateMenuItems {
|
||||
|
||||
if (!(self.showItem.enabled = ![self.passwordWindow.window isVisible])) {
|
||||
self.showItem.title = @"Show (Showing)";
|
||||
self.showItem.title = @"Show (Showing)";
|
||||
self.showItem.toolTip = @"Master Password is already showing.";
|
||||
} else if (!(self.showItem.enabled = (self.activeUser != nil))) {
|
||||
self.showItem.title = @"Show (No user)";
|
||||
}
|
||||
else if (!(self.showItem.enabled = (self.activeUser != nil))) {
|
||||
self.showItem.title = @"Show (No user)";
|
||||
self.showItem.toolTip = @"First select the user to show passwords for.";
|
||||
} else {
|
||||
self.showItem.title = @"Show";
|
||||
}
|
||||
else {
|
||||
self.showItem.title = @"Show";
|
||||
self.showItem.toolTip = nil;
|
||||
}
|
||||
|
||||
if (self.key) {
|
||||
self.lockItem.title = @"Lock";
|
||||
self.lockItem.title = @"Lock";
|
||||
self.lockItem.enabled = YES;
|
||||
self.lockItem.toolTip = nil;
|
||||
} else {
|
||||
self.lockItem.title = @"Lock (Locked)";
|
||||
}
|
||||
else {
|
||||
self.lockItem.title = @"Lock (Locked)";
|
||||
self.lockItem.enabled = NO;
|
||||
self.lockItem.toolTip = @"Master Password is currently locked.";
|
||||
}
|
||||
|
||||
self.rememberPasswordItem.state = [[MPConfig get].rememberLogin boolValue]? NSOnState: NSOffState;
|
||||
|
||||
self.savePasswordItem.state = [MPAppDelegate get].activeUser.saveKey? NSOnState: NSOffState;
|
||||
self.savePasswordItem.state = [MPAppDelegate get].activeUser.saveKey? NSOnState: NSOffState;
|
||||
if (!self.activeUser) {
|
||||
self.savePasswordItem.title = @"Save Password (No user)";
|
||||
self.savePasswordItem.title = @"Save Password (No user)";
|
||||
self.savePasswordItem.enabled = NO;
|
||||
self.savePasswordItem.toolTip = @"First select your user and unlock by showing the Master Password window.";
|
||||
} else if (!self.key) {
|
||||
self.savePasswordItem.title = @"Save Password (Locked)";
|
||||
}
|
||||
else if (!self.key) {
|
||||
self.savePasswordItem.title = @"Save Password (Locked)";
|
||||
self.savePasswordItem.enabled = NO;
|
||||
self.savePasswordItem.toolTip = @"First unlock by showing the Master Password window.";
|
||||
} else {
|
||||
self.savePasswordItem.title = @"Save Password";
|
||||
}
|
||||
else {
|
||||
self.savePasswordItem.title = @"Save Password";
|
||||
self.savePasswordItem.enabled = YES;
|
||||
self.savePasswordItem.toolTip = nil;
|
||||
}
|
||||
|
||||
self.useICloudItem.state = [[MPMacConfig get].iCloud boolValue]? NSOnState: NSOffState;
|
||||
self.useICloudItem.state = [[MPMacConfig get].iCloud boolValue]? NSOnState: NSOffState;
|
||||
if (!(self.useICloudItem.enabled = ![[MPMacConfig get].iCloud boolValue])) {
|
||||
self.useICloudItem.title = @"Use iCloud (Required)";
|
||||
self.useICloudItem.title = @"Use iCloud (Required)";
|
||||
self.useICloudItem.toolTip = @"iCloud is required in this version. Future versions will work without iCloud as well.";
|
||||
}
|
||||
else {
|
||||
self.useICloudItem.title = @"Use iCloud (Required)";
|
||||
self.useICloudItem.title = @"Use iCloud (Required)";
|
||||
self.useICloudItem.toolTip = nil;
|
||||
}
|
||||
}
|
||||
@@ -315,7 +320,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
NSError *error = nil;
|
||||
if (![moc save:&error])
|
||||
err(@"While terminating: %@", error);
|
||||
err(@"While terminating: %@", error);
|
||||
|
||||
return NSTerminateNow;
|
||||
}
|
||||
@@ -323,7 +328,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
#pragma mark - UbiquityStoreManagerDelegate
|
||||
|
||||
- (void)ubiquityStoreManager:(UbiquityStoreManager *)manager didSwitchToCloud:(BOOL)cloudEnabled {
|
||||
|
||||
|
||||
[super ubiquityStoreManager:manager didSwitchToCloud:cloudEnabled];
|
||||
|
||||
[self updateMenuItems];
|
||||
@@ -331,7 +336,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
if (![[MPConfig get].iCloudDecided boolValue]) {
|
||||
if (cloudEnabled)
|
||||
return;
|
||||
|
||||
|
||||
switch ([[NSAlert alertWithMessageText:@"iCloud Is Disabled"
|
||||
defaultButton:@"Enable iCloud" alternateButton:@"Leave iCloud Off" otherButton:@"Explain?"
|
||||
informativeTextWithFormat:@"It is highly recommended you enable iCloud."] runModal]) {
|
||||
@@ -340,26 +345,26 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
manager.cloudEnabled = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case NSAlertOtherReturn: {
|
||||
[[NSAlert alertWithMessageText:@"About iCloud"
|
||||
defaultButton:[PearlStrings get].commonButtonThanks alternateButton:nil otherButton:nil
|
||||
informativeTextWithFormat:
|
||||
@"iCloud is Apple's solution for saving your data in \"the cloud\" "
|
||||
@"and making sure your other iPhones, iPads and Macs are in sync.\n\n"
|
||||
@"For Master Password, that means your sites are available on all your "
|
||||
@"Apple devices, and you always have a backup of them in case "
|
||||
@"you loose one or need to restore.\n\n"
|
||||
@"Because of the way Master Password works, it doesn't need to send your "
|
||||
@"site's passwords to Apple. Only their names are saved to make it easier "
|
||||
@"for you to find the site you need. For some sites you may have set "
|
||||
@"a user-specified password: these are sent to iCloud after being encrypted "
|
||||
@"with your master password.\n\n"
|
||||
@"Apple can never see any of your passwords."] runModal];
|
||||
@"iCloud is Apple's solution for saving your data in \"the cloud\" "
|
||||
@"and making sure your other iPhones, iPads and Macs are in sync.\n\n"
|
||||
@"For Master Password, that means your sites are available on all your "
|
||||
@"Apple devices, and you always have a backup of them in case "
|
||||
@"you loose one or need to restore.\n\n"
|
||||
@"Because of the way Master Password works, it doesn't need to send your "
|
||||
@"site's passwords to Apple. Only their names are saved to make it easier "
|
||||
@"for you to find the site you need. For some sites you may have set "
|
||||
@"a user-specified password: these are sent to iCloud after being encrypted "
|
||||
@"with your master password.\n\n"
|
||||
@"Apple can never see any of your passwords."] runModal];
|
||||
[self ubiquityStoreManager:manager didSwitchToCloud:cloudEnabled];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
|
||||
@interface MPMacConfig : MPConfig
|
||||
|
||||
@property (nonatomic, retain) NSString *usedUserName;
|
||||
@property(nonatomic, retain) NSString *usedUserName;
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
if (!(self = [super init]))
|
||||
return self;
|
||||
|
||||
[self.defaults registerDefaults:@{NSStringFromSelector(@selector(iTunesID)): @"510296984"}];
|
||||
[self.defaults registerDefaults:@{ NSStringFromSelector( @selector(iTunesID) ) : @"510296984" }];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
NSString *_content;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) NSString *content;
|
||||
@property(nonatomic, strong) NSString *content;
|
||||
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *contentField;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *tipField;
|
||||
@property (nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property (nonatomic, weak) IBOutlet NSProgressIndicator *progressView;
|
||||
@property (nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *siteField;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *contentField;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *tipField;
|
||||
@property(nonatomic, weak) IBOutlet NSView *contentContainer;
|
||||
@property(nonatomic, weak) IBOutlet NSProgressIndicator *progressView;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField *userLabel;
|
||||
|
||||
- (void)unlock;
|
||||
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
#define MPAlertUnlockMP @"MPAlertUnlockMP"
|
||||
#define MPAlertIncorrectMP @"MPAlertIncorrectMP"
|
||||
|
||||
@interface MPPasswordWindowController()
|
||||
|
||||
@interface MPPasswordWindowController ()
|
||||
|
||||
@property (nonatomic, strong) NSArray /* MPElementEntity */ *siteResults;
|
||||
@property (nonatomic) BOOL inProgress;
|
||||
@property (nonatomic) BOOL siteFieldPreventCompletion;
|
||||
@property(nonatomic, strong) NSArray /* MPElementEntity */ *siteResults;
|
||||
@property(nonatomic) BOOL inProgress;
|
||||
@property(nonatomic) BOOL siteFieldPreventCompletion;
|
||||
|
||||
@end
|
||||
|
||||
@@ -31,38 +30,38 @@
|
||||
[self.tipField setStringValue:@""];
|
||||
|
||||
[[MPAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
[self.userLabel setStringValue:PearlString(@"%@'s password for:", [MPAppDelegate get].activeUser.name)];
|
||||
[self.userLabel setStringValue:PearlString( @"%@'s password for:", [MPAppDelegate get].activeUser.name )];
|
||||
} forKeyPath:@"activeUser" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[MPAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
if (![MPAppDelegate get].key) {
|
||||
[self unlock];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
[MPAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
MPUserEntity *activeUser = [MPAppDelegate get].activeUser;
|
||||
if (![MPAlgorithmDefault migrateUser:activeUser])
|
||||
[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."];
|
||||
@"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];
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
if (!self.inProgress)
|
||||
[self unlock];
|
||||
[self.siteField selectText:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[[NSApplication sharedApplication] hide:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:MPSignedOutNotification object:nil queue:nil
|
||||
usingBlock:^(NSNotification *note) {
|
||||
[self.window close];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
|
||||
if (!self.inProgress)
|
||||
[self unlock];
|
||||
[self.siteField selectText:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
|
||||
[[NSApplication sharedApplication] hide:self];
|
||||
}];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:MPSignedOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
[self.window close];
|
||||
}];
|
||||
|
||||
[super windowDidLoad];
|
||||
}
|
||||
@@ -70,18 +69,18 @@
|
||||
- (void)unlock {
|
||||
|
||||
if (![MPAppDelegate get].activeUser)
|
||||
// No user to sign in with.
|
||||
// No user to sign in with.
|
||||
return;
|
||||
if ([MPAppDelegate get].key)
|
||||
// Already logged in.
|
||||
// Already logged in.
|
||||
return;
|
||||
if ([[MPAppDelegate get] signInAsUser:[MPAppDelegate get].activeUser usingMasterPassword:nil])
|
||||
// Load the key from the keychain.
|
||||
// Load the key from the keychain.
|
||||
return;
|
||||
|
||||
if (![MPAppDelegate get].key)
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Ask the user to set the key through his master password.
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
if ([MPAppDelegate get].key)
|
||||
return;
|
||||
|
||||
@@ -89,16 +88,17 @@
|
||||
[self.siteField setStringValue:@""];
|
||||
[self.tipField setStringValue:@""];
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
|
||||
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@", [MPAppDelegate get].activeUser.name];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
|
||||
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@",
|
||||
[MPAppDelegate get].activeUser.name];
|
||||
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
|
||||
[alert setAccessoryView:passwordField];
|
||||
[alert layout];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
||||
@@ -114,12 +114,12 @@
|
||||
if ([[NSAlert alertWithMessageText:@"Changing Master Password"
|
||||
defaultButton:nil alternateButton:[PearlStrings get].commonButtonCancel otherButton:nil
|
||||
informativeTextWithFormat:
|
||||
@"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."] runModal]
|
||||
== 1) {
|
||||
@"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."] runModal]
|
||||
== 1) {
|
||||
[MPAppDelegate get].activeUser.keyID = nil;
|
||||
[[MPAppDelegate get] forgetSavedKeyFor:[MPAppDelegate get].activeUser];
|
||||
[[MPAppDelegate get] signOutAnimated:YES];
|
||||
@@ -136,25 +136,25 @@
|
||||
self.contentContainer.alphaValue = 0;
|
||||
[self.progressView startAnimation:nil];
|
||||
self.inProgress = YES;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
|
||||
BOOL success = [[MPAppDelegate get] signInAsUser:[MPAppDelegate get].activeUser
|
||||
usingMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]];
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0 ), ^{
|
||||
BOOL success = [[MPAppDelegate get] signInAsUser:[MPAppDelegate get].activeUser
|
||||
usingMasterPassword:[(NSSecureTextField *)alert.accessoryView stringValue]];
|
||||
self.inProgress = NO;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self.progressView stopAnimation:nil];
|
||||
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
[[NSAlert alertWithError:[NSError errorWithDomain:MPErrorDomain code:0 userInfo:@{
|
||||
NSLocalizedDescriptionKey : PearlString(@"Incorrect master password for user %@",
|
||||
[MPAppDelegate get].activeUser.name)
|
||||
NSLocalizedDescriptionKey : PearlString( @"Incorrect master password for user %@",
|
||||
[MPAppDelegate get].activeUser.name )
|
||||
}]] beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -172,10 +172,10 @@
|
||||
if (![query length] || ![MPAppDelegate get].key)
|
||||
return nil;
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses_" ascending:NO]];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, [MPAppDelegate get].activeUser];
|
||||
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(name BEGINSWITH[cd] %@) AND user == %@",
|
||||
query, [MPAppDelegate get].activeUser];
|
||||
|
||||
NSError *error = nil;
|
||||
self.siteResults = [[MPAppDelegate managedObjectContextForThreadIfReady] executeFetchRequest:fetchRequest error:&error];
|
||||
@@ -184,12 +184,12 @@
|
||||
|
||||
if ([self.siteResults count] == 1) {
|
||||
[textView setString:[(MPElementEntity *)[self.siteResults objectAtIndex:0] name]];
|
||||
[textView setSelectedRange:NSMakeRange([query length], [[textView string] length] - [query length])];
|
||||
[textView setSelectedRange:NSMakeRange( [query length], [[textView string] length] - [query length] )];
|
||||
if ([self trySite])
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray *mutableResults = [NSMutableArray arrayWithCapacity:[self.siteResults count] + 1];
|
||||
NSMutableArray *mutableResults = [NSMutableArray arrayWithCapacity:[self.siteResults count] + 1];
|
||||
if (self.siteResults)
|
||||
for (MPElementEntity *element in self.siteResults)
|
||||
[mutableResults addObject:element.name];
|
||||
@@ -204,7 +204,7 @@
|
||||
[self.window close];
|
||||
return YES;
|
||||
}
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector(commandSelector) hasPrefix:@"delete"]))
|
||||
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"]))
|
||||
return NO;
|
||||
if (commandSelector == @selector(insertNewline:) && [self.content length]) {
|
||||
if ([self trySite])
|
||||
@@ -223,17 +223,17 @@
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
self.tipField.alphaValue = 1;
|
||||
[self.tipField setStringValue:@"Copied! Hit ⎋ (ESC) to close window."];
|
||||
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC));
|
||||
dispatch_after(popTime, dispatch_get_main_queue(), ^{
|
||||
dispatch_time_t popTime = dispatch_time( DISPATCH_TIME_NOW, (int64_t)(5.0f * NSEC_PER_SEC) );
|
||||
dispatch_after( popTime, dispatch_get_main_queue(), ^{
|
||||
[NSAnimationContext beginGrouping];
|
||||
[[NSAnimationContext currentContext] setDuration:0.2f];
|
||||
[self.tipField.animator setAlphaValue:0];
|
||||
[NSAnimationContext endGrouping];
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
[[self findElement] use];
|
||||
}
|
||||
@@ -283,10 +283,10 @@
|
||||
paragraph.alignment = NSCenterTextAlignment;
|
||||
|
||||
[self.contentField setAttributedStringValue:
|
||||
[[NSAttributedString alloc] initWithString:_content
|
||||
attributes:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
paragraph, NSParagraphStyleAttributeName,
|
||||
nil]]];
|
||||
[[NSAttributedString alloc] initWithString:_content
|
||||
attributes:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
paragraph, NSParagraphStyleAttributeName,
|
||||
nil]]];
|
||||
}
|
||||
|
||||
- (BOOL)trySite {
|
||||
@@ -298,17 +298,17 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
|
||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
||||
NSString *description = [result.content description];
|
||||
if (!description)
|
||||
description = @"";
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[self setContent:description];
|
||||
[self.tipField setStringValue:@"Hit ⌤ (ENTER) to copy the password."];
|
||||
self.tipField.alphaValue = 1;
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
// For when the app should be able to create new sites.
|
||||
/*
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Icon</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.lyndir.lhunath.${PRODUCT_NAME:rfc1034identifier}.Mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>[auto]</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>[auto]</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2011-2013 Lyndir. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Icon</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.lyndir.lhunath.${PRODUCT_NAME:rfc1034identifier}.Mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>[auto]</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>[auto]</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2011-2013 Lyndir. All rights reserved.</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#import "Pearl-Prefix.pch"
|
||||
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
return NSApplicationMain(argc, (const char **)argv);
|
||||
return NSApplicationMain( argc, (const char **)argv );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user