diff --git a/MasterPassword/ObjC/MPAlgorithmV1.m b/MasterPassword/ObjC/MPAlgorithmV1.m index 6b0f0028..a95db09b 100644 --- a/MasterPassword/ObjC/MPAlgorithmV1.m +++ b/MasterPassword/ObjC/MPAlgorithmV1.m @@ -47,10 +47,12 @@ - (NSString *)generateContentNamed:(NSString *)name ofType:(MPElementType)type withCounter:(NSUInteger)counter usingKey:(MPKey *)key { - static NSDictionary *MPTypes_ciphers = nil; - if (MPTypes_ciphers == nil) + static __strong NSDictionary *MPTypes_ciphers = nil; + static dispatch_once_t once = 0; + dispatch_once(&once, ^{ MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL: - [[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]]; + [[NSBundle mainBundle] URLForResource:@"ciphers" withExtension:@"plist"]]; + }); // Determine the seed whose bytes will be used for calculating a password uint32_t ncounter = htonl(counter), nnameLength = htonl(name.length); diff --git a/MasterPassword/ObjC/Mac/MPMacAppDelegate.h b/MasterPassword/ObjC/Mac/MPMacAppDelegate.h index 579e4425..320865d7 100644 --- a/MasterPassword/ObjC/Mac/MPMacAppDelegate.h +++ b/MasterPassword/ObjC/Mac/MPMacAppDelegate.h @@ -23,6 +23,7 @@ @property(nonatomic, weak) IBOutlet NSMenuItem *openAtLoginItem; @property(nonatomic, weak) IBOutlet NSMenuItem *savePasswordItem; @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; diff --git a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m index 21047cca..2f9d682d 100644 --- a/MasterPassword/ObjC/Mac/MPMacAppDelegate.m +++ b/MasterPassword/ObjC/Mac/MPMacAppDelegate.m @@ -40,7 +40,7 @@ static EventHotKeyID MPLockHotKey = { .signature = 'lock', .id = 1 }; [MPMacConfig get]; #ifdef DEBUG - [PearlLogger get].printLevel = PearlLogLevelDebug;//Trace; + [PearlLogger get].printLevel = PearlLogLevelDebug; //Trace; #endif } ); } @@ -68,7 +68,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven - (void)updateUsers { [[[self.usersItem submenu] itemArray] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if (idx > 1) + if (idx > 2) [[self.usersItem submenu] removeItem:obj]; }]; @@ -77,15 +77,24 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven self.createUserItem.title = @"New User (Not ready)"; self.createUserItem.enabled = NO; self.createUserItem.toolTip = @"Please wait until the app is fully loaded."; + self.deleteUserItem.title = @"Delete User (Not ready)"; + self.deleteUserItem.enabled = NO; + self.deleteUserItem.toolTip = @"Please wait until the app is fully loaded."; [self.usersItem.submenu addItemWithTitle:@"Loading..." action:NULL keyEquivalent:@""].enabled = NO; return; } + MPUserEntity *activeUser = [self activeUserInContext:context]; + 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."; + NSError *error = nil; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ]; @@ -100,7 +109,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven @"Then give iCloud some time to sync the new user to your Mac."; } - MPUserEntity *activeUser = [self activeUserInContext:context]; + self.usersItem.state = NSMixedState; for (MPUserEntity *user in users) { NSMenuItem *userItem = [[NSMenuItem alloc] initWithTitle:user.name action:@selector(selectUser:) keyEquivalent:@""]; [userItem setTarget:self]; @@ -108,7 +117,14 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven [[self.usersItem submenu] addItem:userItem]; if (!activeUser && [user.name isEqualToString:[MPMacConfig get].usedUserName]) - [self selectUser:userItem]; + [super setActiveUser:activeUser = user]; + + if ([activeUser isEqual:user]) { + userItem.state = NSOnState; + self.usersItem.state = NSOffState; + } + else + userItem.state = NSOffState; } [self updateMenuItems]; @@ -200,6 +216,26 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven }]; } +- (IBAction)deleteUser:(NSMenuItem *)sender { + + NSAlert *alert = [NSAlert alertWithMessageText:@"Delete User" + defaultButton:@"Delete" alternateButton:nil otherButton:@"Cancel" + informativeTextWithFormat:@"This will delete %@ and all his sites.", self.activeUserForMainThread.name]; + if ([alert runModal] != NSAlertDefaultReturn) + return; + + [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { + [moc deleteObject:[self activeUserInContext:moc]]; + [self setActiveUser:nil]; + [moc saveToStore]; + + [[NSOperationQueue mainQueue] addOperationWithBlock:^{ + [self updateUsers]; + [self showPasswordWindow:nil]; + }]; + }]; +} + - (IBAction)lock:(id)sender { self.key = nil; @@ -334,17 +370,11 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven [super setActiveUser:activeUser]; - self.usersItem.state = NSMixedState; - [[[self.usersItem submenu] itemArray] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if ([[obj representedObject] isEqual:[activeUser objectID]]) { - [obj setState:NSOnState]; - self.usersItem.state = NSOffState; - } - else - [obj setState:NSOffState]; - }]; - [MPMacConfig get].usedUserName = activeUser.name; + + PearlMainQueue(^{ + [self updateUsers]; + }); } - (void)updateMenuItems { diff --git a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj index 262ad00b..9c379e68 100644 --- a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj @@ -1876,7 +1876,7 @@ ); GCC_PREFIX_HEADER = "MasterPassword-Prefix.pch"; INFOPLIST_FILE = "MasterPassword-Info.plist"; - PROVISIONING_PROFILE = "923BEF9D-3682-4969-A451-8CAA949E579A"; + PROVISIONING_PROFILE = "9FCC90BB-24CA-40E2-8565-860F95CCC039"; SKIP_INSTALL = NO; WRAPPER_NAME = "Master Password.${WRAPPER_EXTENSION}"; }; diff --git a/MasterPassword/ObjC/Mac/en.lproj/MainMenu.xib b/MasterPassword/ObjC/Mac/en.lproj/MainMenu.xib index 0f7e048a..412ca9cd 100644 --- a/MasterPassword/ObjC/Mac/en.lproj/MainMenu.xib +++ b/MasterPassword/ObjC/Mac/en.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -16,6 +16,7 @@ + @@ -41,6 +42,12 @@ + + + + + + @@ -146,7 +153,7 @@ - + @@ -163,7 +170,7 @@ - + @@ -201,4 +208,4 @@ - \ No newline at end of file + diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m index 5b53e35d..0aa43e32 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m @@ -26,7 +26,7 @@ if ([self class] == [MPiOSAppDelegate class]) { [PearlLogger get].historyLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelTrace: PearlLogLevelInfo; #ifdef DEBUG - [PearlLogger get].printLevel = PearlLogLevelDebug; + [PearlLogger get].printLevel = PearlLogLevelDebug; //Trace; #else [PearlLogger get].printLevel = [[MPiOSConfig get].traceMode boolValue]? PearlLogLevelDebug: PearlLogLevelInfo; #endif