GnomeKeyringResult
GnomeKeyring::findLogins(const nsAString & aHostname,
                         const nsAString & aActionURL,
                         const nsAString & aHttpRealm,
                         GList** found)
{
  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);

  addAttribute(attributes, kHostnameAttr, aHostname);
  if (!aActionURL.IsVoid() && !aActionURL.IsEmpty()) {
    addAttribute(attributes, kFormSubmitURLAttr, aActionURL);
  }
  if (!aHttpRealm.IsVoid() && !aHttpRealm.IsEmpty()) {
    addAttribute(attributes, kHttpRealmAttr, aHttpRealm);
  }

  GnomeKeyringResult result = findLoginItems(attributes, found);

  if (aActionURL.IsVoid()) {
    // TODO: filter out items with a kFormSubmitURLAttr
    // practically, this is not necessary since actionURL/httpRealm are
    // mutually exclusive, but this is not enforced by the interface
  }
  if (aHttpRealm.IsVoid()) {
    // TODO: filter out items with a kHttpRealmAttr
    // practically, this is not necessary since actionURL/httpRealm are
    // mutually exclusive, but this is not enforced by the interface
  }

  return result;
}
NS_IMETHODIMP GnomeKeyring::RemoveAllLogins()
{
  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);

  AutoFoundList foundList;
  GnomeKeyringResult result = findLoginItems(attributes, &foundList);
  MGK_GK_CHECKF_NS(result);

  return deleteFoundItems(foundList);
}
NS_IMETHODIMP GnomeKeyring::GetAllLogins(PRUint32 *aCount,
                                         nsILoginInfo ***aLogins)
{
  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);

  AutoFoundList foundList;
  GnomeKeyringResult result = findLoginItems(attributes, &foundList);
  MGK_GK_CHECKF_NS(result);

  return foundListToArray(foundToLoginInfo, foundList, aCount, aLogins);
}
NS_IMETHODIMP GnomeKeyring::RemoveLogin(nsILoginInfo *aLogin)
{
  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);
  appendAttributesFromLogin(aLogin, attributes);

  AutoFoundList foundList;
  GnomeKeyringResult result = findLoginItems(attributes, &foundList);
  MGK_GK_CHECK_NS(result);

  return deleteFoundItems(foundList, PR_TRUE);
}
NS_IMETHODIMP GnomeKeyring::SearchLogins(PRUint32 *count,
                                         nsIPropertyBag *matchData,
                                         nsILoginInfo ***logins)
{
  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);
  appendAttributesFromBag(matchData, attributes);

  AutoFoundList foundList;
  GnomeKeyringResult result = findLoginItems(attributes, &foundList);
  MGK_GK_CHECKF_NS(result);

  return foundListToArray(foundToLoginInfo, foundList, count, logins);
}
NS_IMETHODIMP GnomeKeyring::ModifyLogin(nsILoginInfo *oldLogin,
                                        nsISupports *modLogin)
{
  nsresult interfaceok;

  /* If the second argument is an nsILoginInfo,
   * just remove the old login and add the new one */
  nsCOMPtr<nsILoginInfo> newLogin( do_QueryInterface(modLogin, &interfaceok) );
  if (interfaceok == NS_OK) {
    nsresult rvremovelogin = RemoveLogin(oldLogin);
    nsresult rvaddlogin = AddLogin(newLogin);
    if(NS_FAILED(rvremovelogin)) {
        return rvremovelogin;
    } else {
        return rvaddlogin;
    }
  }

  /* Otherwise, it has to be an nsIPropertyBag.
   * Let's get the attributes from the old login, then append the ones
   * fetched from the property bag. Gracefully, if an attribute appears
   * twice in an attribut list, the last value is stored. */
  nsCOMPtr<nsIPropertyBag> matchData( do_QueryInterface(modLogin, &interfaceok) );
  if (interfaceok != NS_OK) {
    return interfaceok;
  }

  GnomeKeyringResult result;

  AutoAttributeList attributes;
  newLoginInfoAttributes(&attributes);
  appendAttributesFromLogin(oldLogin, attributes);

  // We need the id of the keyring item to set its attributes.
  AutoFoundList foundList;
  result = findLoginItems(attributes, &foundList);
  MGK_GK_CHECK_NS(result);
  PRUint32 i = 0, id;
  for (GList* l = foundList; l != NULL; l = l->next, i++)
  {
    GnomeKeyringFound* found = static_cast<GnomeKeyringFound*>(l->data);
    id = found->item_id;
    if (i >= 1) {
      NS_ERROR("found more than one item to edit");
      return NS_ERROR_FAILURE;
    }
  }

  // set new attributes
  appendAttributesFromBag(matchData.get(), attributes);
  result = gnome_keyring_item_set_attributes_sync(keyringName.get(),
                                                  id,
                                                  attributes);
  MGK_GK_CHECK_NS(result);

  // set new iteminfo, e.g. password
  AutoItemInfo itemInfo;
  result = gnome_keyring_item_get_info_sync(keyringName.get(),
                                            id,
                                            &itemInfo);
  MGK_GK_CHECK_NS(result);
  appendItemInfoFromBag(matchData.get(), itemInfo);
  result = gnome_keyring_item_set_info_sync(keyringName.get(),
                                            id,
                                            itemInfo);
  MGK_GK_CHECK_NS(result);

  return NS_OK;
}