// // P4PasswordKeeper.m // MBMenuExtra // // Created by Michael Bishop on 1/7/10. // Copyright 2010 Perforce Software. All rights reserved. // #import "P4Keychain.h" #import "EMKeychainProxy.h" #import "EMKeychainItem.h" #import "NGAUtilities.h" // TODO: Make sure all memory is allocated in a zone that is locked in memory // with the mlock() call NSString * const kPerforceServiceName = @"p4://"; @implementation P4Keychain SINGLETON_IMPLEMENTATION( P4Keychain, sharedKeychain ) -(id)init { if ( (self = [super init]) == nil ) return nil; _passwords = [[NSMutableDictionary alloc] init]; return self; } -(void)dealloc { [_passwords release]; [super dealloc]; } -(id)P4_keyForPort:(NSString*)port user:(NSString*)user { return [NSString stringWithFormat:@"%@%@", port, user]; } -(NSString*)passwordForUser:(NSString*)user port:(NSString*)port { NSString * password = nil; if ( !port || !user ) return nil; // load from cache... @synchronized (_passwords) { password = [_passwords objectForKey:[self P4_keyForPort:port user:user]]; if ( password ) return password; } // load from keychain EMKeychainItem * item = [[EMKeychainProxy sharedProxy] genericKeychainItemForService:[kPerforceServiceName stringByAppendingString:port] withUsername:user]; if ( !item ) return nil; password = [item password]; @synchronized (_passwords) { [_passwords setObject:password forKey:[self P4_keyForPort:port user:user]]; } return password; } -(void)setPassword:(NSString*)password forUser:(NSString*)user port:(NSString*)port { if (!password || !port) return; @synchronized (_passwords) { [_passwords setObject:password forKey:[self P4_keyForPort:port user:user]]; } NSString * serviceName = [kPerforceServiceName stringByAppendingString:port]; EMKeychainProxy * proxy = [EMKeychainProxy sharedProxy]; EMKeychainItem * item = [proxy genericKeychainItemForService:serviceName withUsername:user]; if ( item ) { [item setPassword:password]; return; } [proxy addGenericKeychainItemForService:serviceName withUsername:user password:password]; } @end