Cloud and initial window improvements.
[ADDED] Advanced option to mark self as corrupt. [ADDED] Tell user initial cloud sync can take a moment. [IMPROVED] Initial window now visible on full-screen spaces. [FIXED] User name label.
This commit is contained in:
parent
3fa9843855
commit
658d710847
Binary file not shown.
@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.crashlytics.sdk.mac</string>
|
||||
<string>com.crashlytics.ios</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@ -15,16 +15,16 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.1.2</string>
|
||||
<string>2.1.6</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>macosx</string>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>9</string>
|
||||
<string>21</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<string>iphoneos</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>10.6</string>
|
||||
<string>4.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
||||
Subproject commit 4a3c68dda957adba490aae9b56df018e935d6c84
|
||||
Subproject commit 081c2dec20b3638694a5ad20cd2fddccdb298447
|
2
External/UbiquityStoreManager
vendored
2
External/UbiquityStoreManager
vendored
@ -1 +1 @@
|
||||
Subproject commit a5ee62e1cca559e27aba92ac65ffc4da44827dfe
|
||||
Subproject commit ef9aa1c29ed6e1729be4d6a3dd65e2c8a289bf4c
|
@ -127,7 +127,7 @@
|
||||
return @"Device Private Password";
|
||||
}
|
||||
|
||||
Throw(@"Type not supported: %lu", type);
|
||||
Throw(@"Type not supported: %lu", (long)type);
|
||||
}
|
||||
|
||||
- (NSString *)shortNameOfType:(MPElementType)type {
|
||||
@ -161,7 +161,7 @@
|
||||
return @"Device";
|
||||
}
|
||||
|
||||
Throw(@"Type not supported: %lu", type);
|
||||
Throw(@"Type not supported: %lu", (long)type);
|
||||
}
|
||||
|
||||
- (NSString *)classNameOfType:(MPElementType)type {
|
||||
@ -200,7 +200,7 @@
|
||||
return [MPElementStoredEntity class];
|
||||
}
|
||||
|
||||
Throw(@"Type not supported: %lu", type);
|
||||
Throw(@"Type not supported: %lu", (long)type);
|
||||
}
|
||||
|
||||
- (MPElementType)nextType:(MPElementType)type {
|
||||
@ -227,7 +227,7 @@
|
||||
return MPElementTypeStoredPersonal;
|
||||
}
|
||||
|
||||
Throw(@"Type not supported: %lu", type);
|
||||
Throw(@"Type not supported: %lu", (long)type);
|
||||
}
|
||||
|
||||
- (MPElementType)previousType:(MPElementType)type {
|
||||
@ -300,13 +300,13 @@
|
||||
case MPElementTypeGeneratedBasic:
|
||||
case MPElementTypeGeneratedShort:
|
||||
case MPElementTypeGeneratedPIN: {
|
||||
NSAssert(NO, @"Cannot save content to element with generated type %lu.", element.type);
|
||||
NSAssert(NO, @"Cannot save content to element with generated type %lu.", (long)element.type);
|
||||
break;
|
||||
}
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:[elementKey subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
|
||||
@ -315,7 +315,7 @@
|
||||
}
|
||||
case MPElementTypeStoredDevicePrivate: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
|
||||
NSData *encryptedContent = [[clearContent dataUsingEncoding:NSUTF8StringEncoding]
|
||||
encryptWithSymmetricKey:[elementKey subKeyOfLength:PearlCryptKeySize].keyData padding:YES];
|
||||
@ -360,7 +360,7 @@
|
||||
case MPElementTypeGeneratedShort:
|
||||
case MPElementTypeGeneratedPIN: {
|
||||
NSAssert([element isKindOfClass:[MPElementGeneratedEntity class]],
|
||||
@"Element with generated type %lu is not an MPElementGeneratedEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with generated type %lu is not an MPElementGeneratedEntity, but a %@.", (long)element.type, [element class]);
|
||||
|
||||
NSString *name = element.name;
|
||||
MPElementType type = element.type;
|
||||
@ -382,7 +382,7 @@
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
|
||||
NSData *encryptedContent = ((MPElementStoredEntity *)element).contentObject;
|
||||
|
||||
@ -394,7 +394,7 @@
|
||||
}
|
||||
case MPElementTypeStoredDevicePrivate: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
|
||||
NSDictionary *elementQuery = [self queryForDevicePrivateElementNamed:element.name];
|
||||
NSData *encryptedContent = [PearlKeyChain dataOfItemForQuery:elementQuery];
|
||||
@ -423,7 +423,7 @@
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
if ([importKey.keyID isEqualToData:elementKey.keyID])
|
||||
((MPElementStoredEntity *)element).contentObject = [protectedContent decodeBase64];
|
||||
|
||||
@ -481,7 +481,7 @@
|
||||
|
||||
case MPElementTypeStoredPersonal: {
|
||||
NSAssert([element isKindOfClass:[MPElementStoredEntity class]],
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", element.type, [element class]);
|
||||
@"Element with stored type %lu is not an MPElementStoredEntity, but a %@.", (long)element.type, [element class]);
|
||||
result = [((MPElementStoredEntity *)element).contentObject encodeBase64];
|
||||
break;
|
||||
}
|
||||
|
@ -75,6 +75,8 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
||||
|
||||
if (password)
|
||||
NSAssert(![NSThread isMainThread], @"Computing key must not happen from the main thread.");
|
||||
if (!user)
|
||||
return NO;
|
||||
|
||||
MPKey *tryKey = nil;
|
||||
|
||||
|
@ -701,7 +701,7 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
||||
|
||||
[export appendFormat:@"%@ %8ld %8s %20s\t%@\n",
|
||||
[[NSDateFormatter rfc3339DateFormatter] stringFromDate:lastUsed], (long)uses,
|
||||
[PearlString( @"%lu:%lu", type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
[PearlString( @"%lu:%lu", (long)type, (unsigned long)version ) UTF8String], [name UTF8String], content
|
||||
? content: @""];
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
if (!aType || aType == (MPElementType)NSNotFound)
|
||||
aType = MPElementTypeGeneratedLong;
|
||||
if (![self isKindOfClass:[self.algorithm classOfType:aType]])
|
||||
Throw(@"This object's class does not support the type: %lu", aType);
|
||||
Throw(@"This object's class does not support the type: %lu", (long)aType);
|
||||
|
||||
self.type_ = @(aType);
|
||||
}
|
||||
@ -128,7 +128,7 @@
|
||||
- (NSString *)debugDescription {
|
||||
|
||||
return PearlString( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
||||
NSStringFromClass( [self class] ), self.name, self.user.name, self.type, (long)self.uses, self.lastUsed, (long)self.version,
|
||||
NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed, (long)self.version,
|
||||
self.loginName, self.requiresExplicitMigration );
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
// Copyright, lhunath (Maarten Billemont) 2014. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPElementCollectionView.h"
|
||||
#import "MPElementModel.h"
|
||||
#import "MPMacAppDelegate.h"
|
||||
@ -36,17 +37,24 @@
|
||||
if (!(self = [super initWithCoder:coder]))
|
||||
return nil;
|
||||
|
||||
__weak MPElementCollectionView *wSelf = self;
|
||||
[self addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
wSelf.counterHidden = !(MPElementTypeClassGenerated & wSelf.representedObject.type);
|
||||
wSelf.updateContentHidden = !(MPElementTypeClassStored & wSelf.representedObject.type);
|
||||
} );
|
||||
} forKeyPath:@"representedObject" options:0 context: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;
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B3116" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1080" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -34,6 +34,7 @@
|
||||
- (IBAction)newUser:(NSMenuItem *)sender;
|
||||
- (IBAction)lock:(id)sender;
|
||||
- (IBAction)rebuildCloud:(id)sender;
|
||||
- (IBAction)corruptCloud:(id)sender;
|
||||
- (IBAction)terminate:(id)sender;
|
||||
- (IBAction)iphoneAppStore:(id)sender;
|
||||
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
#define LOGIN_HELPER_BUNDLE_ID @"com.lyndir.lhunath.MasterPassword.Mac.LoginHelper"
|
||||
|
||||
@interface UbiquityStoreManager (Private)
|
||||
|
||||
- (void)markCloudStoreCorrupted;
|
||||
|
||||
@end
|
||||
|
||||
@interface MPMacAppDelegate()
|
||||
|
||||
@property(nonatomic, strong) NSWindowController *initialWindow;
|
||||
@ -129,16 +135,23 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (IBAction)togglePreference:(id)sender {
|
||||
|
||||
if (sender == self.enableCloudButton)
|
||||
[self storeManager].cloudEnabled = (self.enableCloudButton.state == NSOnState);
|
||||
if (sender == self.enableCloudButton) {
|
||||
if (([self storeManager].cloudEnabled = self.enableCloudButton.state == NSOnState)) {
|
||||
NSAlert *alert = [NSAlert new];
|
||||
alert.messageText = @"iCloud Enabled";
|
||||
alert.informativeText = @"If you already have a user on another iCloud-enabled device, "
|
||||
@"it may take a moment for that user to sync down to this device.";
|
||||
[alert runModal];
|
||||
}
|
||||
}
|
||||
if (sender == self.useCloudItem)
|
||||
[self storeManager].cloudEnabled = !(self.useCloudItem.state == NSOnState);
|
||||
[self storeManager].cloudEnabled = self.useCloudItem.state != NSOnState;
|
||||
if (sender == self.rememberPasswordItem)
|
||||
[MPConfig get].rememberLogin = [NSNumber numberWithBool:![[MPConfig get].rememberLogin boolValue]];
|
||||
if (sender == self.openAtLoginButton)
|
||||
[self setLoginItemEnabled:(self.openAtLoginButton.state == NSOnState)];
|
||||
[self setLoginItemEnabled:self.openAtLoginButton.state == NSOnState];
|
||||
if (sender == self.openAtLoginItem)
|
||||
[self setLoginItemEnabled:!(self.openAtLoginItem.state == NSOnState)];
|
||||
[self setLoginItemEnabled:self.openAtLoginItem.state != NSOnState];
|
||||
if (sender == self.savePasswordItem) {
|
||||
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:context];
|
||||
@ -194,14 +207,24 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
- (IBAction)rebuildCloud:(id)sender {
|
||||
|
||||
if ([[NSAlert alertWithMessageText:@"iCloud Truth Sync" defaultButton:@"Continue"
|
||||
if ([[NSAlert alertWithMessageText:@"iCloud Truth Push" defaultButton:@"Continue"
|
||||
alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"This action will force all your iCloud enabled devices to revert to this device's version of the truth."
|
||||
informativeTextWithFormat:@"This action will force all your iCloud enabled devices to switch to this device's version of the truth."
|
||||
@"\n\nThis is only necessary if you notice that your devices aren't syncing properly anymore. "
|
||||
"Any data on other devices not available from here will be lost."] runModal] == NSAlertDefaultReturn)
|
||||
[self.storeManager rebuildCloudContentFromCloudStoreOrLocalStore:NO];
|
||||
}
|
||||
|
||||
- (IBAction)corruptCloud:(id)sender {
|
||||
|
||||
if ([[NSAlert alertWithMessageText:@"iCloud Truth Pull" defaultButton:@"Continue"
|
||||
alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"This action will force another iCloud enabled device to push their version of the truth on all."
|
||||
@"\n\nThis is only necessary if you notice that your devices aren't syncing properly anymore. "
|
||||
"Any data on this device not available from the other will be lost."] runModal] == NSAlertDefaultReturn)
|
||||
[self.storeManager markCloudStoreCorrupted];
|
||||
}
|
||||
|
||||
- (IBAction)terminate:(id)sender {
|
||||
|
||||
[self.passwordWindow close];
|
||||
@ -301,8 +324,11 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
||||
|
||||
// Initial display.
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
if ([[MPMacConfig get].firstRun boolValue])
|
||||
[self.initialWindow = [[NSWindowController alloc] initWithWindowNibName:@"MPInitialWindow" owner:self] showWindow:self];
|
||||
if ([[MPMacConfig get].firstRun boolValue]) {
|
||||
self.initialWindow = [[NSWindowController alloc] initWithWindowNibName:@"MPInitialWindow" owner:self];
|
||||
[self.initialWindow.window setLevel:NSFloatingWindowLevel];
|
||||
[self.initialWindow showWindow:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setActiveUser:(MPUserEntity *)activeUser {
|
||||
|
@ -44,7 +44,6 @@
|
||||
self.backgroundQueue = [NSOperationQueue new];
|
||||
self.backgroundQueue.maxConcurrentOperationCount = 1;
|
||||
|
||||
[self.userLabel setStringValue:PearlString( @"%@'s password for:", [[MPMacAppDelegate get] activeUserForMainThread].name )];
|
||||
[[MPMacAppDelegate get] addObserverBlock:^(NSString *keyPath, id object, NSDictionary *change, void *context) {
|
||||
// [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||
// if (![MPAlgorithmDefault migrateUser:[[MPMacAppDelegate get] activeUserInContext:moc]])
|
||||
@ -54,9 +53,9 @@
|
||||
// @"their passwords to change. You'll need to update your profile for that site with the new password."];
|
||||
// [moc saveToStore];
|
||||
// }];
|
||||
dispatch_async( dispatch_get_main_queue(), ^{
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
[self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
|
||||
} );
|
||||
}];
|
||||
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSWindowDidBecomeKeyNotification object:self.window
|
||||
queue:[NSOperationQueue mainQueue] usingBlock:
|
||||
@ -77,11 +76,18 @@
|
||||
[[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) {
|
||||
@ -107,37 +113,7 @@
|
||||
}
|
||||
if (contextInfo == MPAlertUnlockMP) {
|
||||
switch (returnCode) {
|
||||
case NSAlertAlternateReturn: {
|
||||
// "Change" button.
|
||||
NSInteger returnCode_ = [[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];
|
||||
|
||||
if (returnCode_ == NSAlertDefaultReturn) {
|
||||
[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 NSAlertOtherReturn: {
|
||||
// "Cancel" button.
|
||||
[self close];
|
||||
break;
|
||||
}
|
||||
|
||||
case NSAlertDefaultReturn: {
|
||||
case NSAlertFirstButtonReturn: {
|
||||
// "Unlock" button.
|
||||
self.contentContainer.alphaValue = 0;
|
||||
self.inProgress = YES;
|
||||
@ -150,7 +126,7 @@
|
||||
usingMasterPassword:password];
|
||||
self.inProgress = NO;
|
||||
|
||||
dispatch_async( dispatch_get_current_queue(), ^{
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
if (success)
|
||||
self.contentContainer.alphaValue = 1;
|
||||
else {
|
||||
@ -159,11 +135,41 @@
|
||||
}]] 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;
|
||||
}
|
||||
@ -304,16 +310,19 @@
|
||||
|
||||
[self.siteField 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%@",
|
||||
userName];
|
||||
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];
|
||||
[passwordField becomeFirstResponder];
|
||||
[alert beginSheetModalForWindow:self.window modalDelegate:self
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
|
||||
[passwordField becomeFirstResponder];
|
||||
}];
|
||||
}];
|
||||
|
||||
@ -413,9 +422,11 @@
|
||||
- (void)createNewSite:(NSString *)siteName {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:@"Create site?"
|
||||
defaultButton:@"Create" alternateButton:nil otherButton:@"Cancel"
|
||||
informativeTextWithFormat:@"Do you want to create a new site named:\n\n%@", siteName];
|
||||
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];
|
||||
}];
|
||||
|
@ -10,8 +10,8 @@
|
||||
<string>Master Password</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>MasterPassword</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>MasterPassword</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.lyndir.lhunath.MasterPassword.Mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
|
@ -1982,7 +1982,7 @@
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch";
|
||||
INFOPLIST_FILE = "MasterPassword-Info.plist";
|
||||
PROVISIONING_PROFILE = "";
|
||||
PROVISIONING_PROFILE = "2A46D0C9-E5F0-4C52-BCC6-96434A0D1C1B";
|
||||
SKIP_INSTALL = NO;
|
||||
WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}";
|
||||
};
|
||||
|
@ -140,13 +140,30 @@
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Advanced" id="777">
|
||||
<items>
|
||||
<menuItem title="iCloud Truth Sync" id="778">
|
||||
<menuItem title="iCloud Truth Push" id="778">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="rebuildCloud:" target="494" id="780"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Force this device's version of the truth upon all others." enabled="NO" id="779">
|
||||
<menuItem title="Force our version of the truth upon all other devices." enabled="NO" id="779">
|
||||
<attributedString key="attributedTitle">
|
||||
<fragment content="Force this device's version of the truth upon all others.">
|
||||
<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="iCloud Truth Pull" id="cLQ-kc-cYN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="corruptCloud:" target="494" id="asr-sb-Zkz"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Mark ourselves as corrupt and pull the truth from another." enabled="NO" id="6NL-ki-Jff">
|
||||
<attributedString key="attributedTitle">
|
||||
<fragment content="Force this device's version of the truth upon all others.">
|
||||
<attributes>
|
||||
@ -164,7 +181,7 @@
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="718"/>
|
||||
<menuItem title="Show" keyEquivalent="p" id="719">
|
||||
<menuItem title="Open" keyEquivalent="p" id="719">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="showPasswordWindow:" target="494" id="782"/>
|
||||
|
@ -15,11 +15,11 @@
|
||||
93D395F08A087F8A24689347 /* NSArray+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39067C0AFDC581794E2B8 /* NSArray+Indexing.m */; };
|
||||
93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3956915634581E737B38C /* PearlNavigationController.m */; };
|
||||
93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D3942A356B639724157982 /* PearlOverlay.h */; };
|
||||
93D397952F5635C793C24DF1 /* NSError+MPFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+MPFullDescription.m */; };
|
||||
93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */; };
|
||||
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */; };
|
||||
93D399433EA75E50656040CB /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D394077F8FAB8167647187 /* Twitter.framework */; };
|
||||
93D399BBC0A7EC746CB1B19B /* MPLogsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D391943675426839501BB8 /* MPLogsViewController.h */; };
|
||||
93D39B842AB9A5D072810D76 /* NSError+MPFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+MPFullDescription.h */; };
|
||||
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */; };
|
||||
93D39C34FE35830EF5BE1D2A /* NSArray+Indexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D396D04E57792A54D437AC /* NSArray+Indexing.h */; };
|
||||
93D39C8AD8EAB747856B3A8C /* LLModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D3923B42DA2DA18F287092 /* LLModel.m */; };
|
||||
93D39E281E3658B30550CB55 /* NSDictionary+Indexing.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */; };
|
||||
@ -499,7 +499,7 @@
|
||||
93D3979190DACEBD1F6AE9F4 /* MPLogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogsViewController.m; sourceTree = "<group>"; };
|
||||
93D3983278751A530262F64E /* LLConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLConfig.h; sourceTree = "<group>"; };
|
||||
93D398567FD02DB2647B8CF3 /* PearlNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlNavigationController.h; sourceTree = "<group>"; };
|
||||
93D398C95847261903D781D3 /* NSError+MPFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+MPFullDescription.h"; sourceTree = "<group>"; };
|
||||
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+PearlFullDescription.h"; sourceTree = "<group>"; };
|
||||
93D39A28369954D147E239BA /* MPSetupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSetupViewController.m; sourceTree = "<group>"; };
|
||||
93D39A3CC4D8330831FC8CB4 /* LLToggleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLToggleViewController.h; sourceTree = "<group>"; };
|
||||
93D39AA1EE2E1E7B81372240 /* NSDictionary+Indexing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Indexing.m"; sourceTree = "<group>"; };
|
||||
@ -507,7 +507,7 @@
|
||||
93D39BF6BCBDFFE844E7D34C /* LLButtonView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLButtonView.m; sourceTree = "<group>"; };
|
||||
93D39C8E26B06F01566785B7 /* LLToggleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LLToggleViewController.m; sourceTree = "<group>"; };
|
||||
93D39F7C9F47BF6387FBC5C3 /* PearlEMail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlEMail.h; sourceTree = "<group>"; };
|
||||
93D39F9106F2CCFB94283188 /* NSError+MPFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+MPFullDescription.m"; sourceTree = "<group>"; };
|
||||
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+PearlFullDescription.m"; sourceTree = "<group>"; };
|
||||
DA04E33D14B1E70400ECA4F3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
|
||||
DA30E9CB15722ECA00A68B4C /* NSBundle+PearlMutableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+PearlMutableInfo.h"; sourceTree = "<group>"; };
|
||||
DA30E9CC15722ECA00A68B4C /* NSBundle+PearlMutableInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+PearlMutableInfo.m"; sourceTree = "<group>"; };
|
||||
@ -2937,8 +2937,8 @@
|
||||
DAFE45F515039823003ABA7C /* PearlStringUtils.m */,
|
||||
DAFE45F815039823003ABA7C /* README */,
|
||||
DAFE45F915039823003ABA7C /* Resources */,
|
||||
93D39F9106F2CCFB94283188 /* NSError+MPFullDescription.m */,
|
||||
93D398C95847261903D781D3 /* NSError+MPFullDescription.h */,
|
||||
93D39F9106F2CCFB94283188 /* NSError+PearlFullDescription.m */,
|
||||
93D398C95847261903D781D3 /* NSError+PearlFullDescription.h */,
|
||||
);
|
||||
path = Pearl;
|
||||
sourceTree = "<group>";
|
||||
@ -3202,7 +3202,7 @@
|
||||
93D396BA1C74C4A06FD86437 /* PearlOverlay.h in Headers */,
|
||||
DAEB937518AA537D000490CC /* ssl.h in Headers */,
|
||||
93D3992FA1546E01F498F665 /* PearlNavigationController.h in Headers */,
|
||||
93D39B842AB9A5D072810D76 /* NSError+MPFullDescription.h in Headers */,
|
||||
93D39B842AB9A5D072810D76 /* NSError+PearlFullDescription.h in Headers */,
|
||||
DAEB936218AA537D000490CC /* obj_mac.h in Headers */,
|
||||
DAEB934218AA537D000490CC /* bn.h in Headers */,
|
||||
);
|
||||
@ -3854,7 +3854,7 @@
|
||||
DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */,
|
||||
93D3922A53E41A54832E90D9 /* PearlOverlay.m in Sources */,
|
||||
93D396AA30690B256F30378A /* PearlNavigationController.m in Sources */,
|
||||
93D397952F5635C793C24DF1 /* NSError+MPFullDescription.m in Sources */,
|
||||
93D397952F5635C793C24DF1 /* NSError+PearlFullDescription.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user