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}