NS_IMETHODIMP
nsAbAddressCollector::CollectSingleAddress(const nsACString &aEmail,
                                           const nsACString &aDisplayName,
                                           bool aCreateCard,
                                           uint32_t aSendFormat,
                                           bool aSkipCheckExisting)
{
  if (!mDirectory)
    return NS_OK;

  nsresult rv;
  nsCOMPtr<nsIAbCard> card;
  bool emailAddressIn2ndEmailColumn = false;

  nsCOMPtr<nsIAbDirectory> originDirectory;

  if (!aSkipCheckExisting)
  {
    card = GetCardFromProperty(kPriEmailProperty, aEmail,
                               getter_AddRefs(originDirectory));
    // We've not found a card, but is this address actually in the additional
    // email column?
    if (!card)
    {
      card = GetCardFromProperty(k2ndEmailProperty, aEmail,
                                 getter_AddRefs(originDirectory));
      if (card)
        emailAddressIn2ndEmailColumn = true;
    }
  }

  if (!card && (aCreateCard || aSkipCheckExisting))
  {
    card = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv) && card)
    {
      // Set up the fields for the new card.
      SetNamesForCard(card, aDisplayName);
      AutoCollectScreenName(card, aEmail);

      if (NS_SUCCEEDED(card->SetPrimaryEmail(NS_ConvertUTF8toUTF16(aEmail))))
      {
        card->SetPropertyAsUint32(kPreferMailFormatProperty, aSendFormat);

        nsCOMPtr<nsIAbCard> addedCard;
        rv = mDirectory->AddCard(card, getter_AddRefs(addedCard));
        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add card");
      }
    }
  }
  else if (card && !emailAddressIn2ndEmailColumn && originDirectory)
  {
    // It could be that the origin directory is read-only, so don't try and
    // write to it if it is.
    bool readOnly;
    rv = originDirectory->GetReadOnly(&readOnly);
    NS_ENSURE_SUCCESS(rv, rv);

    if (readOnly)
      return NS_OK;

    // address is already in the AB, so update the names
    bool modifiedCard = false;

    nsString displayName;
    card->GetDisplayName(displayName);
    // If we already have a display name, don't set the names on the card.
    if (displayName.IsEmpty() && !aDisplayName.IsEmpty())
      modifiedCard = SetNamesForCard(card, aDisplayName);

    if (aSendFormat != nsIAbPreferMailFormat::unknown)
    {
      uint32_t currentFormat;
      rv = card->GetPropertyAsUint32(kPreferMailFormatProperty,
                                     &currentFormat);
      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get preferred mail format");

      // we only want to update the AB if the current format is unknown
      if (currentFormat == nsIAbPreferMailFormat::unknown &&
          NS_SUCCEEDED(card->SetPropertyAsUint32(kPreferMailFormatProperty,
                                                 aSendFormat)))
        modifiedCard = true;
    }

    if (modifiedCard)
      originDirectory->ModifyCard(card);
  }

  return NS_OK;
}
NS_IMETHODIMP nsAbAddressCollecter::CollectAddress(const char *aAddress, PRBool aCreateCard, PRUint32 aSendFormat)
{
    // note that we're now setting the whole recipient list,
    // not just the pretty name of the first recipient.
    PRUint32 numAddresses;
    char *names;
    char *addresses;

    nsresult rv;
    nsCOMPtr<nsIMsgHeaderParser> pHeader = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv,rv);

    rv = pHeader->ParseHeaderAddresses(nsnull, aAddress, &names, &addresses, &numAddresses);
    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to parse, so can't collect");
    if (NS_FAILED(rv))
        return NS_OK;

    char *curName = names;
    char *curAddress = addresses;

    for (PRUint32 i = 0; i < numAddresses; i++)
    {
        nsXPIDLCString unquotedName;
        rv = pHeader->UnquotePhraseOrAddr(curName, PR_FALSE, getter_Copies(unquotedName));
        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to unquote name");
        if (NS_FAILED(rv))
            continue;

        nsCOMPtr <nsIAbCard> existingCard;
        nsCOMPtr <nsIAbCard> cardInstance;
        PRBool emailAddressIn2ndEmailColumn = PR_FALSE;

        rv = GetCardFromAttribute(kPriEmailColumn, curAddress, getter_AddRefs(existingCard));
        // We've not found a card, but is this address actually in the additional
        // email column?
        if (!existingCard)
        {
            rv = GetCardFromAttribute(k2ndEmailColumn, curAddress, getter_AddRefs(existingCard));
            if (existingCard)
                emailAddressIn2ndEmailColumn = PR_TRUE;
        }

        if (!existingCard && aCreateCard)
        {
            nsCOMPtr<nsIAbCard> senderCard = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv);
            if (NS_SUCCEEDED(rv) && senderCard)
            {
                PRBool modifiedCard;
                rv = SetNamesForCard(senderCard, unquotedName.get(), &modifiedCard);
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set names");

                rv = AutoCollectScreenName(senderCard, curAddress, &modifiedCard);
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set screenname");

                rv = senderCard->SetPrimaryEmail(NS_ConvertASCIItoUCS2(curAddress).get());
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set email");

                if (aSendFormat != nsIAbPreferMailFormat::unknown)
                {
                    rv = senderCard->SetPreferMailFormat(aSendFormat);
                    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remember preferred mail format");
                }

                rv = AddCardToAddressBook(senderCard);
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add card");
            }
        }
        else if (existingCard && !emailAddressIn2ndEmailColumn) {
            // address is already in the AB, so update the names
            PRBool setNames = PR_FALSE;

            if (!unquotedName.IsEmpty())
            {
                rv = SetNamesForCard(existingCard, unquotedName.get(), &setNames);
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set names");
            }

            PRBool setScreenName = PR_FALSE;
            rv = AutoCollectScreenName(existingCard, curAddress, &setScreenName);
            NS_ASSERTION(NS_SUCCEEDED(rv), "failed to set screen name");

            PRBool setPreferMailFormat = PR_FALSE;
            if (aSendFormat != nsIAbPreferMailFormat::unknown)
            {
                PRUint32 currentFormat;
                rv = existingCard->GetPreferMailFormat(&currentFormat);
                NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get preferred mail format");

                // we only want to update the AB if the current format is unknown
                if (currentFormat == nsIAbPreferMailFormat::unknown)
                {
                    rv = existingCard->SetPreferMailFormat(aSendFormat);
                    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remember preferred mail format");
                    setPreferMailFormat = PR_TRUE;
                }
            }

            if (setScreenName || setNames || setPreferMailFormat)
                existingCard->EditCardToDatabase(m_abURI.get());
        }

        curName += strlen(curName) + 1;
        curAddress += strlen(curAddress) + 1;
    }

    PR_FREEIF(addresses);
    PR_FREEIF(names);
    return NS_OK;
}