Part of Bug 326809 modernize nsIMsgHeaderParser - |string| and |wstring| vs AString and AUTF8String - Move nsIMsgHeaderParser::extractHeaderAddressMailboxes to ACString from string. r=Neil,sr=bienvenu
authorMark Banner <bugzilla@standard8.plus.com>
Fri, 17 Oct 2008 21:55:13 +0100
changeset 631 e43b70b86507055364aafc90f7aceb84229aa2d1
parent 630 6b0bbba2af789d0f3a8cd70e256e45a986a3bca1
child 632 3c8fa20dc00b19c65e7a5d3b1948dc230769ed91
push idunknown
push userunknown
push dateunknown
reviewersNeil, bienvenu
bugs326809
Part of Bug 326809 modernize nsIMsgHeaderParser - |string| and |wstring| vs AString and AUTF8String - Move nsIMsgHeaderParser::extractHeaderAddressMailboxes to ACString from string. r=Neil,sr=bienvenu
mailnews/base/src/nsMsgContentPolicy.cpp
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/compose/src/nsMsgCompose.cpp
mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
mailnews/mime/public/nsIMsgHeaderParser.idl
mailnews/mime/src/nsMsgHeaderParser.cpp
mailnews/mime/test/unit/test_nsIMsgHeaderParser2.js
mailnews/news/src/nsNNTPProtocol.cpp
--- a/mailnews/base/src/nsMsgContentPolicy.cpp
+++ b/mailnews/base/src/nsMsgContentPolicy.cpp
@@ -143,18 +143,17 @@ nsresult nsMsgContentPolicy::AllowRemote
   nsCString author;
   rv = aMsgHdr->GetAuthor(getter_Copies(author));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgHeaderParser> headerParser = do_GetService("@mozilla.org/messenger/headerparser;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString emailAddress; 
-  rv = headerParser->ExtractHeaderAddressMailboxes(author.get(),
-                                                   getter_Copies(emailAddress));
+  rv = headerParser->ExtractHeaderAddressMailboxes(author, emailAddress);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIAbManager> abManager = do_GetService("@mozilla.org/abmanager;1",
                                                    &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsISimpleEnumerator> enumerator;
   rv = abManager->GetDirectories(getter_AddRefs(enumerator));
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -1908,18 +1908,17 @@ nsMsgDBFolder::CallFilterPlugins(nsIMsgW
     rv = mDatabase->GetMsgHdrForKey(msgKey, getter_AddRefs(msgHdr));
     if (!NS_SUCCEEDED(rv))
       continue;
     nsCString author;
     nsCString authorEmailAddress;
     if (whiteListDirArray.Count() != 0 || !trustedMailDomains.IsEmpty())
     {
       msgHdr->GetAuthor(getter_Copies(author));
-      rv = headerParser->ExtractHeaderAddressMailboxes(author.get(),
-                                                       getter_Copies(authorEmailAddress));
+      rv = headerParser->ExtractHeaderAddressMailboxes(author, authorEmailAddress);
     }
 
     if (!trustedMailDomains.IsEmpty())
     {
       nsCAutoString domain;
       PRInt32 atPos = authorEmailAddress.FindChar('@');
       if (atPos >= 0)
         domain = Substring(authorEmailAddress, atPos + 1);
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -1872,26 +1872,26 @@ nsresult nsMsgCompose::CreateMessage(con
             msgHdr->GetRecipients(getter_Copies(recipients));
 
             nsCString ccList, ccListEmailAddresses;
             msgHdr->GetCcList(getter_Copies(ccList));
 
             nsCOMPtr<nsIMsgHeaderParser> parser (do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID));
             if (parser) {
               // convert to UTF8 before passing to MakeFullAddress
-              rv = parser->ExtractHeaderAddressMailboxes(author.get(),
-                                                         getter_Copies(authorEmailAddress));
+              rv = parser->ExtractHeaderAddressMailboxes(author,
+                                                         authorEmailAddress);
               NS_ENSURE_SUCCESS(rv,rv);
 
-              rv = parser->ExtractHeaderAddressMailboxes(recipients.get(),
-                                                         getter_Copies(recipientsEmailAddresses));
+              rv = parser->ExtractHeaderAddressMailboxes(recipients,
+                                                         recipientsEmailAddresses);
               NS_ENSURE_SUCCESS(rv,rv);
 
-              rv = parser->ExtractHeaderAddressMailboxes(ccList.get(),
-                                                         getter_Copies(ccListEmailAddresses));
+              rv = parser->ExtractHeaderAddressMailboxes(ccList,
+                                                         ccListEmailAddresses);
               NS_ENSURE_SUCCESS(rv,rv);
             }
 
             PRBool replyToSelfCheckAll = PR_FALSE;
             nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
             if (NS_SUCCEEDED(rv))
               prefBranch->GetBoolPref("mailnews.reply_to_self_check_all_ident", &replyToSelfCheckAll);
 
--- a/mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
+++ b/mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
@@ -869,17 +869,18 @@ nsresult nsMsgComposeSecure::MimeFinishE
 
 /* Used to figure out what certs should be used when encrypting this message.
  */
 nsresult nsMsgComposeSecure::MimeCryptoHackCerts(const char *aRecipients,
                                                  nsIMsgSendReport *sendReport,
                                                  PRBool aEncrypt,
                                                  PRBool aSign)
 {
-  char *all_mailboxes = 0, *mailboxes = 0, *mailbox_list = 0;
+  char *mailboxes = 0, *mailbox_list = 0;
+  nsCString all_mailboxes;
   const char *mailbox = 0;
   PRUint32 count = 0;
   nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
   nsresult res;
   nsCOMPtr<nsIMsgHeaderParser> pHeader = do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID, &res);
   NS_ENSURE_SUCCESS(res,res);
 
   mCerts = do_CreateInstance(NS_ARRAY_CONTRACTID, &res);
@@ -899,22 +900,19 @@ nsresult nsMsgComposeSecure::MimeCryptoH
   }
 
   if ((mSelfEncryptionCert == nsnull) && aEncrypt) {
     SetError(sendReport, NS_LITERAL_STRING("NoSenderEncryptionCert").get());
     res = NS_ERROR_FAILURE;
     goto FAIL;
   }
 
-  pHeader->ExtractHeaderAddressMailboxes(aRecipients, &all_mailboxes);
-  pHeader->RemoveDuplicateAddresses(all_mailboxes, 0, PR_FALSE, &mailboxes);
-  if (all_mailboxes) {
-    nsMemory::Free(all_mailboxes);
-    all_mailboxes = nsnull;
-  }
+  pHeader->ExtractHeaderAddressMailboxes(nsDependentCString(aRecipients),
+                                         all_mailboxes);
+  pHeader->RemoveDuplicateAddresses(all_mailboxes.get(), 0, PR_FALSE, &mailboxes);
 
   if (mailboxes) {
     pHeader->ParseHeaderAddresses(mailboxes, 0, &mailbox_list, &count);
     nsMemory::Free(mailboxes);
     mailboxes = nsnull;
   }
   if (count < 0) return count;
 
--- a/mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
+++ b/mailnews/extensions/smime/src/nsSMimeJSHelper.cpp
@@ -428,25 +428,20 @@ nsresult nsSMimeJSHelper::getMailboxList
       all_recipients.Append(',');
     }
 
     if (!ng.IsEmpty())
       all_recipients.Append(NS_ConvertUTF16toUTF8(ng));
 
     char *unique_mailboxes = nsnull;
 
-    {
-      char *all_mailboxes = nsnull;
-      parser->ExtractHeaderAddressMailboxes(all_recipients.get(), &all_mailboxes);
-      parser->RemoveDuplicateAddresses(all_mailboxes, 0, PR_FALSE,
-                                       &unique_mailboxes);
-      if (all_mailboxes) {
-        nsMemory::Free(all_mailboxes);
-      }
-    }
+    nsCString all_mailboxes;
+    parser->ExtractHeaderAddressMailboxes(all_recipients, all_mailboxes);
+    parser->RemoveDuplicateAddresses(all_mailboxes.get(), 0, PR_FALSE,
+                                     &unique_mailboxes);
     if (unique_mailboxes)
     {
       parser->ParseHeaderAddresses(unique_mailboxes, 0, mailbox_list,
                                    mailbox_count);
     }
     if (unique_mailboxes) {
       nsMemory::Free(unique_mailboxes);
     }
--- a/mailnews/mime/public/nsIMsgHeaderParser.idl
+++ b/mailnews/mime/public/nsIMsgHeaderParser.idl
@@ -44,17 +44,17 @@ interface nsISimpleEnumerator;
 
 #define NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID \
   "@mozilla.org/messenger/headerparser;1"
 %}
 
 /* 
  * nsIMsgRFCParser Interface declaration 
  */ 
-[scriptable, uuid(a6f865a2-eb19-4072-bd44-6720e69adbc6)]
+[scriptable, uuid(96502670-07dd-4dd3-987a-ee6cafa8afa3)]
 interface nsIMsgHeaderParser : nsISupports {
 
   void parseHeadersWithArray(in wstring aLine, 
                              [array, size_is(count)] out wstring aEmailAddresses,
                              [array, size_is(count)] out wstring aNames,
                              [array, size_is(count)] out wstring aFullNames,
                              [retval] out unsigned long count);
 
@@ -83,18 +83,17 @@ interface nsIMsgHeaderParser : nsISuppor
   /**
    * Given a string which contains a list of Header addresses, returns a
    * comma-separated list of just the `mailbox' portions.
    *
    * @param aLine          The header line to parse.
    * @return               A comma-separated list of just the mailbox parts
    *                       of the email-addresses.
    */
-  string extractHeaderAddressMailboxes(in string aLine);
-
+  ACString extractHeaderAddressMailboxes(in ACString aLine);
 
   /**
    * Given a string which contains a list of Header addresses, returns a
    * comma-separated list of just the `user name' portions.  If any of
    * the addresses doesn't have a name, then the mailbox is used instead.
    *
    * @param aLine          The header line to parse.
    * @return               A comma-separated list of just the name parts
--- a/mailnews/mime/src/nsMsgHeaderParser.cpp
+++ b/mailnews/mime/src/nsMsgHeaderParser.cpp
@@ -65,17 +65,16 @@ nsresult FillResultsArray(const char * a
  * The following are prototypes for the old "C" functions used to support all of the RFC-822 parsing code
  * We could have made these private functions of nsMsgHeaderParser if we wanted...
  */
 static int msg_parse_Header_addresses(const char *line, char **names, char **addresses,
                                       PRBool quote_names_p = PR_TRUE, PRBool quote_addrs_p = PR_TRUE,
                                       PRBool first_only_p = PR_FALSE);
 static int msg_quote_phrase_or_addr(char *address, PRInt32 length, PRBool addr_p);
 static nsresult msg_unquote_phrase_or_addr(const char *line, PRBool strict, char **lineout);
-static char *msg_extract_Header_address_mailboxes(const char *line);
 static char *msg_extract_Header_address_names(const char *line);
 static char *msg_extract_Header_address_name(const char *line);
 #if 0
 static char *msg_format_Header_addresses(const char *addrs, int count,
                                          PRBool wrap_lines_p);
 #endif
 static char *msg_reformat_Header_addresses(const char *line);
 
@@ -196,25 +195,16 @@ nsMsgHeaderParser::ParseHeaderAddresses(
                                         PRUint32 *aNumAddresses)
 {
   NS_ENSURE_ARG_POINTER(aNumAddresses);
   *aNumAddresses = msg_parse_Header_addresses(aLine, aNames, aAddresses);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsMsgHeaderParser::ExtractHeaderAddressMailboxes(const char *aLine,
-                                                 char **aMailboxes)
-{
-  NS_ENSURE_ARG_POINTER(aMailboxes);
-  *aMailboxes = msg_extract_Header_address_mailboxes(aLine);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsMsgHeaderParser::ExtractHeaderAddressNames(const char *aLine, char **aNames)
 {
   NS_ENSURE_ARG_POINTER(aNames);
   *aNames = msg_extract_Header_address_names(aLine);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1100,63 +1090,69 @@ msg_unquote_phrase_or_addr(const char *l
       NEXT_CHAR(lineptr);
     }
   }
   *outptr = '\0';
 
   return NS_OK;
 }
 
-/* msg_extract_Header_address_mailboxes
- *
+/**
  * Given a string which contains a list of Header addresses, returns a
  * comma-separated list of just the `mailbox' portions.
  */
-static char *
-msg_extract_Header_address_mailboxes(const char *line)
+NS_IMETHODIMP
+nsMsgHeaderParser::ExtractHeaderAddressMailboxes(const nsACString &aLine,
+                                                 nsACString &aResult)
 {
+  if (aLine.IsEmpty())
+  {
+    aResult.Truncate();
+    return NS_OK;
+  }
+
   char *addrs = 0;
-  char *result, *s, *out;
+  int status = msg_parse_Header_addresses(PromiseFlatCString(aLine).get(),
+                                          NULL, &addrs);
+  if (status <= 0)
+    return NS_ERROR_FAILURE;
+
+  char *s = addrs;
   PRUint32 i, size = 0;
-  int status = msg_parse_Header_addresses(line, NULL, &addrs);
-  if (status <= 0)
-    return NULL;
 
-  s = addrs;
   for (i = 0; (int) i < status; i++)
   {
     PRUint32 j = strlen(s);
     s += j + 1;
-    size += j + 2;
+    if ((int)(i + 1) < status)
+      size += j + 2;
+    else
+      size += j;
   }
 
-  result = (char*)PR_Malloc(size + 1);
-  if (!result)
-  {
-    PR_Free(addrs);
-    return 0;
-  }
-  out = result;
+  nsCString result;
+  result.SetLength(size);
   s = addrs;
+  char* out = result.BeginWriting();
   for (i = 0; (int)i < status; i++)
   {
     PRUint32 j = strlen(s);
     memcpy(out, s, j);
     out += j;
     if ((int)(i+1) < status)
     {
       *out++ = ',';
       *out++ = ' ';
     }
     s += j + 1;
   }
-  *out = 0;
 
   PR_Free(addrs);
-  return result;
+  aResult = result;
+  return NS_OK;
 }
 
 
 /* msg_extract_Header_address_names
  *
  * Given a string which contains a list of Header addresses, returns a
  * comma-separated list of just the `user name' portions.  If any of
  * the addresses doesn't have a name, then the mailbox is used instead.
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser2.js
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Test suite for nsIMsgHeaderParser functions.
+ */
+
+function run_test() {
+  var i;
+
+  var parser = Components.classes["@mozilla.org/messenger/headerparser;1"]
+                         .getService(Components.interfaces.nsIMsgHeaderParser);
+
+  const checks =
+  [
+    ["abc@invalid.com",
+     "abc@invalid.com" ],
+    ["foo <ghj@invalid.com>",
+     "ghj@invalid.com"],
+    ["abc@invalid.com, foo <ghj@invalid.com>",
+     "abc@invalid.com, ghj@invalid.com"],
+    ["foo bar <foo@bar.invalid>",
+     "foo@bar.invalid"],
+    ["foo bar <foo@bar.invalid>, abc@invalid.com, foo <ghj@invalid.com>",
+     "foo@bar.invalid, abc@invalid.com, ghj@invalid.com"],
+    // More complicated examples drawn from RFC 2822
+    ["Test <\"abc!x.yz\"@invalid.com>, Test <test@[xyz!]>,\"Joe Q. Public\" <john.q.public@example.com>,\"Giant; \\\"Big\\\" Box\" <sysservices@example.net>",
+     "\"abc!x.yz\"@invalid.com, test@[xyz!], john.q.public@example.com, sysservices@example.net"],
+  ];
+
+  // Test - empty strings
+
+  do_check_eq(parser.extractHeaderAddressMailboxes(""), "");
+
+  // Test - extractHeaderAddressMailboxes
+
+  for (i = 0; i < checks.length; ++i)
+    do_check_eq(parser.extractHeaderAddressMailboxes(checks[i][0]), checks[i][1]);
+}
--- a/mailnews/news/src/nsNNTPProtocol.cpp
+++ b/mailnews/news/src/nsNNTPProtocol.cpp
@@ -4141,18 +4141,19 @@ PRBool nsNNTPProtocol::CheckIfAuthor(nsI
 
     if (NS_FAILED(rv)) {
         cancelInfo->from.Truncate();
         return PR_TRUE;
     }
 
     nsCString us;
     nsCString them;
-    nsresult rv1 = parser->ExtractHeaderAddressMailboxes(cancelInfo->from.get(), getter_Copies(us));
-    nsresult rv2 = parser->ExtractHeaderAddressMailboxes(cancelInfo->old_from.get(), getter_Copies(them));
+    nsresult rv1 = parser->ExtractHeaderAddressMailboxes(cancelInfo->from, us);
+    nsresult rv2 = parser->ExtractHeaderAddressMailboxes(cancelInfo->old_from,
+                                                         them);
 
     PR_LOG(NNTP,PR_LOG_ALWAYS,("us = %s, them = %s", us.get(), them.get()));
 
     if (NS_FAILED(rv1) || NS_FAILED(rv2) || !us.Equals(them, nsCaseInsensitiveCStringComparator())) {
         //no match.  don't set cancel email
         cancelInfo->from.Truncate();
         return PR_TRUE;
     }