347 :(NSString *)username
348 andPassword:(NSString *)password
349 forServerName:(NSString *)serverName
350 updateExisting:(BOOL)updateExisting
351 error:(NSError **)error
352{
353 if (!username || !password || !serverName)
354 {
355 if (error != nil)
356 {
357 *error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:-2000 userInfo:nil];
358 }
359 return NO;
360 }
361
362
363 NSError *getError = nil;
365 andServerName:serverName
366 error:&getError];
367
368 if ([getError code] == -1999)
369 {
370
371
372
373
374 getError = nil;
375
376 [self deleteItemForUsername:username andServerName:serverName error:&getError];
377
378 if ([getError code] != noErr)
379 {
380 if (error != nil)
381 {
382 *error = getError;
383 }
384 return NO;
385 }
386 }
387 else if ([getError code] != noErr)
388 {
389 if (error != nil)
390 {
391 *error = getError;
392 }
393 return NO;
394 }
395
396 if (error != nil)
397 {
398 *error = nil;
399 }
400
401 OSStatus status = noErr;
402
403 if (existingPassword)
404 {
405
406
407
408 if (![existingPassword isEqualToString:password] && updateExisting)
409 {
410
411
412 NSArray *keys =
413 [[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService,
414 kSecAttrLabel, kSecAttrAccount, nil] autorelease];
415
416 NSArray *objects =
417 [[[NSArray alloc] initWithObjects:(NSString *)kSecClassGenericPassword, serverName,
418 serverName, username, nil] autorelease];
419
420 NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
421 forKeys:keys] autorelease];
422
423 status = SecItemUpdate(
424 (CFDictionaryRef)query,
425 (CFDictionaryRef)[NSDictionary
426 dictionaryWithObject:[password dataUsingEncoding:NSUTF8StringEncoding]
427 forKey:(NSString *)kSecValueData]);
428 }
429 }
430 else
431 {
432
433
434
435 NSArray *keys =
436 [[[NSArray alloc] initWithObjects:(NSString *)kSecClass, kSecAttrService, kSecAttrLabel,
437 kSecAttrAccount, kSecValueData, nil] autorelease];
438
439 NSArray *objects = [[[NSArray alloc]
440 initWithObjects:(NSString *)kSecClassGenericPassword, serverName, serverName, username,
441 [password dataUsingEncoding:NSUTF8StringEncoding], nil] autorelease];
442
443 NSDictionary *query = [[[NSDictionary alloc] initWithObjects:objects
444 forKeys:keys] autorelease];
445
446 status = SecItemAdd((CFDictionaryRef)query, NULL);
447 }
448
449 if (error != nil && status != noErr)
450 {
451
452 *error = [NSError errorWithDomain:SFHFKeychainUtilsErrorDomain code:status userInfo:nil];
453
454 return NO;
455 }
456
457 return YES;
458}