Bug 474759 Trunk builds broken due to ParseString and nsStringEnumerator change r=Standard8 rs=dmose in anticipation of forthcoming sr
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Fri, 23 Jan 2009 23:53:01 +0000
changeset 1742 176d86062c81fe326726efa986eb29b9830c1845
parent 1741 854ed8a08a062b479f233fa73fb2e257dd44d9f4
child 1743 b9cd225d077e0a05a667baec4c55c77877c3ffc9
push id1398
push userneil@parkwaycc.co.uk
push dateFri, 23 Jan 2009 23:53:11 +0000
treeherdercomm-central@176d86062c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, dmose
bugs474759
Bug 474759 Trunk builds broken due to ParseString and nsStringEnumerator change r=Standard8 rs=dmose in anticipation of forthcoming sr
mailnews/addrbook/src/nsAbLDAPDirectory.cpp
mailnews/addrbook/src/nsAbLDAPDirectory.h
mailnews/base/public/nsIMsgTagService.idl
mailnews/base/search/public/nsIMsgSearchTerm.idl
mailnews/base/search/src/nsMsgLocalSearch.cpp
mailnews/base/search/src/nsMsgSearchTerm.cpp
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/src/nsMsgAccountManager.h
mailnews/base/src/nsMsgDBView.cpp
mailnews/base/src/nsMsgDBView.h
mailnews/base/src/nsMsgTagService.cpp
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgUtils.cpp
mailnews/base/util/nsMsgUtils.h
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/src/nsMsgSendLater.cpp
mailnews/compose/src/nsSmtpService.cpp
mailnews/imap/src/nsImapProtocol.cpp
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsParseMailbox.cpp
mailnews/local/src/nsPop3Protocol.cpp
mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
mailnews/mime/src/mimeobj.cpp
mailnews/news/build/Makefile.in
mailnews/news/public/nsINntpService.idl
mailnews/news/src/nsNNTPNewsgroupList.cpp
mailnews/news/src/nsNntpService.cpp
--- a/mailnews/addrbook/src/nsAbLDAPDirectory.cpp
+++ b/mailnews/addrbook/src/nsAbLDAPDirectory.cpp
@@ -64,16 +64,17 @@
 #include "nsILDAPModification.h"
 #include "nsILDAPService.h"
 #include "nsIAbLDAPCard.h"
 #include "nsAbUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIPrefService.h"
 #include "nsIMsgAccountManager.h"
 #include "nsMsgBaseCID.h"
+#include "nsMsgUtils.h"
 
 #define kDefaultMaxHits 100
 
 nsAbLDAPDirectory::nsAbLDAPDirectory() :
   nsAbDirectoryRDFResource(),
   mPerformingQuery(PR_FALSE),
   mContext(0),
   mLock(0)
@@ -747,25 +748,25 @@ NS_IMETHODIMP nsAbLDAPDirectory::AddCard
   NS_ENSURE_SUCCESS(rv, rv);
   
   // Retrieve preferences
   nsCAutoString prefString;
   rv = GetRdnAttributes(prefString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   CharPtrArrayGuard rdnAttrs;
-  rv = SplitStringList(prefString.get(), rdnAttrs.GetSizeAddr(),
+  rv = SplitStringList(prefString, rdnAttrs.GetSizeAddr(),
     rdnAttrs.GetArrayAddr());
   NS_ENSURE_SUCCESS(rv, rv);
   
   rv = GetObjectClasses(prefString);
   NS_ENSURE_SUCCESS(rv, rv);
   
   CharPtrArrayGuard objClass;
-  rv = SplitStringList(prefString.get(), objClass.GetSizeAddr(),
+  rv = SplitStringList(prefString, objClass.GetSizeAddr(),
     objClass.GetArrayAddr());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Process updates
   nsCOMPtr<nsIArray> modArray;
   rv = card->GetLDAPMessageInfo(attrMap, objClass.GetSize(), objClass.GetArray(),
     nsILDAPModification::MOD_ADD, getter_AddRefs(modArray));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -849,17 +850,17 @@ NS_IMETHODIMP nsAbLDAPDirectory::ModifyC
   NS_ENSURE_SUCCESS(rv, rv);
   
   // Retrieve preferences
   nsCAutoString prefString;
   rv = GetObjectClasses(prefString);
   NS_ENSURE_SUCCESS(rv, rv);
   
   CharPtrArrayGuard objClass;
-  rv = SplitStringList(prefString.get(), objClass.GetSizeAddr(),
+  rv = SplitStringList(prefString, objClass.GetSizeAddr(),
     objClass.GetArrayAddr());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Process updates
   nsCOMPtr<nsIArray> modArray;
   rv = card->GetLDAPMessageInfo(attrMap, objClass.GetSize(), objClass.GetArray(),
     nsILDAPModification::MOD_REPLACE, getter_AddRefs(modArray));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -929,26 +930,25 @@ NS_IMETHODIMP nsAbLDAPDirectory::GetObje
 }
 
 NS_IMETHODIMP nsAbLDAPDirectory::SetObjectClasses(const nsACString &aObjectClasses)
 {
   return SetStringValue("objectClasses", aObjectClasses);
 }
 
 nsresult nsAbLDAPDirectory::SplitStringList(
-  const char *aString,
+  const nsACString& aString,
   PRUint32 *aCount,
   char ***aValues)
 {
-  NS_ENSURE_ARG_POINTER(aString);
   NS_ENSURE_ARG_POINTER(aCount);
   NS_ENSURE_ARG_POINTER(aValues);
 
   nsCStringArray strarr;
-  strarr.ParseString(aString, ",");
+  ParseString(aString, ',', strarr);
 
   char **cArray = nsnull;
   if (!(cArray = static_cast<char **>(nsMemory::Alloc(
       strarr.Count() * sizeof(char *)))))
     return NS_ERROR_OUT_OF_MEMORY;
 
   for (PRInt32 i = 0; i < strarr.Count(); ++i)
   {
--- a/mailnews/addrbook/src/nsAbLDAPDirectory.h
+++ b/mailnews/addrbook/src/nsAbLDAPDirectory.h
@@ -84,17 +84,17 @@ public:
   // nsIAbDirectorySearch methods
   NS_DECL_NSIABDIRECTORYSEARCH
   NS_DECL_NSIABLDAPDIRECTORY
   NS_DECL_NSIABDIRSEARCHLISTENER
 
 protected:
   nsresult Initiate();
 
-  nsresult SplitStringList(const char *aString,
+  nsresult SplitStringList(const nsACString& aString,
                            PRUint32 *aCount,
                            char ***aValues);
 
   PRPackedBool mPerformingQuery;
   PRInt32 mContext;
   PRInt32 mMaxHits;
 
   nsInterfaceHashtable<nsISupportsHashKey, nsIAbCard> mCache;
--- a/mailnews/base/public/nsIMsgTagService.idl
+++ b/mailnews/base/public/nsIMsgTagService.idl
@@ -64,26 +64,26 @@
 [scriptable, uuid(84d593a3-5d8a-45e6-96e2-9189acd422e1)]
 interface nsIMsgTag : nsISupports {
   readonly attribute ACString key;     // distinct tag identifier
   readonly attribute AString  tag;     // human readable tag name
   readonly attribute ACString color;   // tag color
   readonly attribute ACString ordinal; // custom sort string (usually empty)
 };
 
-[scriptable, uuid(88BBCA01-9BA2-4185-9634-F82DA583D4AA)]
+[scriptable, uuid(97360ce3-0fba-4f1c-8214-af7bdc6f8587)]
 interface nsIMsgTagService : nsISupports {
   // create new tag by deriving the key from the tag
   void addTag(in AString tag, in ACString color, in ACString ordinal);
   // create/update tag with known key
   void addTagForKey(in ACString key, in AString tag, in ACString color, in ACString ordinal);
   // get the key representation of a given tag
   ACString getKeyForTag(in AString tag);
   // get the first key by ordinal order
-  ACString getTopKey(in string keyList);
+  ACString getTopKey(in ACString keyList);
   // support functions for single tag aspects
   AString getTagForKey(in ACString key); // look up the tag for a key.
   void setTagForKey(in ACString key, in AString tag); // this can be used to "rename" a tag
   ACString getColorForKey(in ACString key);
   void setColorForKey(in ACString key, in ACString color);
   ACString getOrdinalForKey(in ACString key);
   void setOrdinalForKey(in ACString key, in ACString ordinal);
   // delete a tag from the list of known tags (but not from any messages)
--- a/mailnews/base/search/public/nsIMsgSearchTerm.idl
+++ b/mailnews/base/search/public/nsIMsgSearchTerm.idl
@@ -39,17 +39,17 @@
 #include "nsISupports.idl"
 #include "nsMsgSearchCore.idl"
 #include "nsIMsgSearchValue.idl"
 
 interface nsIMsgDBHdr;
 interface nsIMsgDatabase;
 interface nsIMsgSearchScopeTerm;
 
-[scriptable, uuid(59db8e90-cd6e-11dc-95ff-0800200c9a66)]
+[scriptable, uuid(2dd082e7-faa4-4e46-81ba-9c636bc9315a)]
 interface nsIMsgSearchTerm : nsISupports {
     attribute nsMsgSearchAttribValue attrib;
     attribute nsMsgSearchOpValue op;
     attribute nsIMsgSearchValue value;
 
     attribute boolean booleanAnd;
     attribute ACString arbitraryHeader;
 
@@ -100,12 +100,12 @@ interface nsIMsgSearchTerm : nsISupports
                                  //[array, size_is(headerLength)] in string headers,
                                  in string headers,
                                  in unsigned long headerLength,
                                  in boolean forFilters);
 
     readonly attribute boolean matchAllBeforeDeciding;
 
     readonly attribute ACString termAsString;
-    boolean matchKeyword(in string keyword); // used for tag searches
+    boolean matchKeyword(in ACString keyword); // used for tag searches
     attribute boolean matchAll;
 };
 
--- a/mailnews/base/search/src/nsMsgLocalSearch.cpp
+++ b/mailnews/base/search/src/nsMsgLocalSearch.cpp
@@ -560,17 +560,17 @@ nsresult nsMsgSearchOfflineMail::Process
           msgToMatch->GetLabel(&label);
           if (label >= 1)
           {
             if (!keywords.IsEmpty())
               keywords.Append(' ');
             keywords.Append("$label");
             keywords.Append(label + '0');
           }
-          err = aTerm->MatchKeyword(keywords.get(), &result);
+          err = aTerm->MatchKeyword(keywords, &result);
           break;
       }
       case nsMsgSearchAttrib::JunkStatus:
       {
          nsCString junkScoreStr;
          msgToMatch->GetStringProperty("junkscore", getter_Copies(junkScoreStr));
          err = aTerm->MatchJunkStatus(junkScoreStr.get(), &result);
          break;
--- a/mailnews/base/search/src/nsMsgSearchTerm.cpp
+++ b/mailnews/base/search/src/nsMsgSearchTerm.cpp
@@ -1431,41 +1431,42 @@ nsresult nsMsgSearchTerm::MatchStatus(PR
  *
  *         # Valid Tokens IsEmpty Contains DoesntContain Is     Isnt
  *                0           +       -         +         -       +
  * Term found?                      N   Y     N   Y     N   Y   N   Y
  *                1           -     -   +     +   -     -   +   +   -
  *               >1           -     -   +     +   -     -   -   +   +
  */
 // look up nsMsgSearchTerm::m_value in space-delimited keywordList
-nsresult nsMsgSearchTerm::MatchKeyword(const char *keywordList, PRBool *pResult)
+nsresult nsMsgSearchTerm::MatchKeyword(const nsACString& keywordList, PRBool *pResult)
 {
   NS_ENSURE_ARG_POINTER(pResult);
   PRBool matches = PR_FALSE;
 
   // special-case empty for performance reasons
-  if (!keywordList || !*keywordList)
+  if (keywordList.IsEmpty())
   {
     *pResult =  m_operator != nsMsgSearchOp::Contains &&
                 m_operator != nsMsgSearchOp::Is;
     return NS_OK;
   }
 
   // check if we can skip expensive valid keywordList test
   if (m_operator == nsMsgSearchOp::DoesntContain ||
       m_operator == nsMsgSearchOp::Contains)
   {
+    nsCString keywordString(keywordList);
     const PRUint32 kKeywordLen = PL_strlen(m_value.string);
-    const char* matchStart = PL_strstr(keywordList, m_value.string);
+    const char* matchStart = PL_strstr(keywordString.get(), m_value.string);
     while (matchStart)
     {
       // For a real match, matchStart must be the start of the keywordList or
       // preceded by a space and matchEnd must point to a \0 or space.
       const char* matchEnd = matchStart + kKeywordLen;
-      if ((matchStart == keywordList || matchStart[-1] == ' ') &&
+      if ((matchStart == keywordString.get() || matchStart[-1] == ' ') &&
           (!*matchEnd || *matchEnd == ' '))
       {
         // found the keyword
         *pResult = m_operator == nsMsgSearchOp::Contains;
         return NS_OK;
       }
       // no match yet, so search on
       matchStart = PL_strstr(matchEnd, m_value.string);
@@ -1473,17 +1474,17 @@ nsresult nsMsgSearchTerm::MatchKeyword(c
     // keyword not found
     *pResult = m_operator == nsMsgSearchOp::DoesntContain;
     return NS_OK;
   }
 
   // Only accept valid keys in tokens.
   nsresult rv = NS_OK;
   nsCStringArray keywordArray;
-  keywordArray.ParseString(keywordList, " ");
+  ParseString(keywordList, ' ', keywordArray);
   nsCOMPtr<nsIMsgTagService> tagService(do_GetService(NS_MSGTAGSERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Loop through tokens in keywords
   PRUint32 count = keywordArray.Count();
   for (PRUint32 i = 0; i < count; i++)
   {
     // is this token a valid tag? Otherwise ignore it
--- a/mailnews/base/src/nsMsgAccountManager.cpp
+++ b/mailnews/base/src/nsMsgAccountManager.cpp
@@ -1258,17 +1258,17 @@ nsMsgAccountManager::LoadAccounts()
       // Get a list of pre-configured accounts
       nsCString appendAccountList;
       rv = m_prefs->GetCharPref(PREF_MAIL_ACCOUNTMANAGER_APPEND_ACCOUNTS, getter_Copies(appendAccountList));
 
       // If there are pre-configured accounts, we need to add them to the existing list.
       if (!appendAccountList.IsEmpty()) {
         if (!accountList.IsEmpty()) {
           nsCStringArray existingAccountsArray;
-          existingAccountsArray.ParseString(accountList.get(), ACCOUNT_DELIMITER);
+          ParseString(accountList.get(), ACCOUNT_DELIMITER, existingAccountsArray);
 
           // Tokenize the data and add each account if it is not already there
           // in the user's current mailnews account list
           char *newAccountStr = appendAccountList.BeginWriting();
           char *token = NS_strtok(ACCOUNT_DELIMITER, &newAccountStr);
 
           nsCAutoString newAccount;
           while (token) {
@@ -2803,17 +2803,17 @@ NS_IMETHODIMP nsMsgAccountManager::LoadV
         else if (dbFolderInfo && Substring(buffer, 0, 6).Equals("scope="))
         {
           buffer.Cut(0, 6);
           // if this is a cross folder virtual folder, we have a list of folders uris,
           // and we have to add a pending listener for each of them.
           if (buffer.Length())
           {
             dbFolderInfo->SetCharProperty("searchFolderUri", buffer);
-            AddVFListenersForVF(virtualFolder, buffer.get(), rdf, msgDBService);
+            AddVFListenersForVF(virtualFolder, buffer, rdf, msgDBService);
           }
           else // this folder is useless
           {
           }
         }
         else if (dbFolderInfo && Substring(buffer, 0, 6).Equals("terms="))
         {
           buffer.Cut(0, 6);
@@ -2912,22 +2912,22 @@ nsresult nsMsgAccountManager::WriteLineT
   PRUint32 writeCount;
   outputStream->Write(prefix, strlen(prefix), &writeCount);
   outputStream->Write(line, strlen(line), &writeCount);
   outputStream->Write("\n", 1, &writeCount);
   return NS_OK;
 }
 
 nsresult nsMsgAccountManager::AddVFListenersForVF(nsIMsgFolder *virtualFolder,
-                                                  const char *srchFolderUris,
+                                                  const nsCString& srchFolderUris,
                                                   nsIRDFService *rdf,
                                                   nsIMsgDBService *msgDBService)
 {
   nsCStringArray folderUris;
-  folderUris.ParseString(srchFolderUris, "|");
+  ParseString(srchFolderUris, '|', folderUris);
   nsCOMPtr <nsIRDFResource> resource;
 
   for (PRInt32 i = 0; i < folderUris.Count(); i++)
   {
     rdf->GetResource(*(folderUris[i]), getter_AddRefs(resource));
     nsCOMPtr <nsIMsgFolder> realFolder = do_QueryInterface(resource);
     VirtualFolderChangeListener *dbListener = new VirtualFolderChangeListener();
     NS_ENSURE_TRUE(dbListener, NS_ERROR_OUT_OF_MEMORY);
@@ -2958,17 +2958,17 @@ NS_IMETHODIMP nsMsgAccountManager::OnIte
     {
       nsCOMPtr <nsIMsgDatabase> virtDatabase;
       nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
       rv = folder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
       NS_ENSURE_SUCCESS(rv, rv);
       nsCString srchFolderUri;
       dbFolderInfo->GetCharProperty("searchFolderUri", srchFolderUri);
       nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
-      AddVFListenersForVF(folder, srchFolderUri.get(), rdf, msgDBService);
+      AddVFListenersForVF(folder, srchFolderUri, rdf, msgDBService);
     }
     rv = SaveVirtualFolders();
   }
   return rv;
 }
 
 NS_IMETHODIMP nsMsgAccountManager::OnItemRemoved(nsIMsgFolder *parentItem, nsISupports *item)
 {
--- a/mailnews/base/src/nsMsgAccountManager.h
+++ b/mailnews/base/src/nsMsgAccountManager.h
@@ -180,17 +180,17 @@ private:
                               PRInt32 port,
                               PRBool aRealFlag,
                               nsIMsgIncomingServer** aResult);
 
   // handle virtual folders
   nsresult GetVirtualFoldersFile(nsCOMPtr<nsILocalFile>& file);
   nsresult WriteLineToOutputStream(const char *prefix, const char * line, nsIOutputStream *outputStream);
   nsresult AddVFListenersForVF(nsIMsgFolder *virtualFolder, 
-                               const char *srchFolderUris,
+                               const nsCString& srchFolderUris,
                                nsIRDFService *rdf,
                                nsIMsgDBService *msgDBService);
 
   static void getUniqueAccountKey(const char * prefix,
                                   nsISupportsArray *accounts,
                                   nsCString& aResult);
 
   
--- a/mailnews/base/src/nsMsgDBView.cpp
+++ b/mailnews/base/src/nsMsgDBView.cpp
@@ -333,17 +333,17 @@ nsresult nsMsgDBView::GetPrefLocalizedSt
 
   rv = prefBranch->GetComplexValue(aPrefName, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls));
   NS_ENSURE_SUCCESS(rv, rv);
   pls->ToString(getter_Copies(ucsval));
   aResult = ucsval.get();
   return rv;
 }
 
-nsresult nsMsgDBView::AppendKeywordProperties(const char *keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty)
+nsresult nsMsgDBView::AppendKeywordProperties(const nsACString& keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty)
 {
   // get the top most keyword's color and append that as a property.
   nsresult rv;
   if (!mTagService)
   {
     mTagService = do_GetService(NS_MSGTAGSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
   }
@@ -699,17 +699,17 @@ nsresult nsMsgDBView::FetchTags(nsIMsgDB
   {
     nsCAutoString labelStr("$label");
     labelStr.Append((char) (label + '0'));
     if (keywords.Find(labelStr, PR_TRUE) == -1)
       FetchLabel(aHdr, tags);
   }
 
   nsCStringArray keywordsArray;
-  keywordsArray.ParseString(keywords.get(), " ");
+  ParseString(keywords, ' ', keywordsArray);
   nsAutoString tag;
 
   for (PRInt32 i = 0; i < keywordsArray.Count(); i++)
   {
     rv = mTagService->GetTagForKey(*(keywordsArray[i]), tag);
     if (NS_SUCCEEDED(rv) && !tag.IsEmpty())
     {
       if (!tags.IsEmpty())
@@ -1171,17 +1171,17 @@ NS_IMETHODIMP nsMsgDBView::GetRowPropert
   if (NS_FAILED(rv) || !msgHdr) {
     ClearHdrCache();
     return NS_MSG_INVALID_DBVIEW_INDEX;
   }
 
   nsCString keywordProperty;
   FetchKeywords(msgHdr, keywordProperty);
   if (!keywordProperty.IsEmpty())
-    AppendKeywordProperties(keywordProperty.get(), properties, PR_FALSE);
+    AppendKeywordProperties(keywordProperty, properties, PR_FALSE);
 
   // give the custom column handlers a chance to style the row.
   for (int i = 0; i < m_customColumnHandlers.Count(); i++)
     m_customColumnHandlers[i]->GetRowProperties(index, properties);
 
   return NS_OK;
 }
 
@@ -1256,17 +1256,17 @@ NS_IMETHODIMP nsMsgDBView::GetCellProper
     properties->AppendElement(junkScoreStr.ToInteger((PRInt32*)&rv) == nsIJunkMailPlugin::IS_SPAM_SCORE ?
                               kJunkMsgAtom : kNotJunkMsgAtom);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Converting junkScore to integer failed.");
   }
 
   nsCString keywords;
   FetchKeywords(msgHdr, keywords);
   if (!keywords.IsEmpty())
-    AppendKeywordProperties(keywords.get(), properties, PR_TRUE);
+    AppendKeywordProperties(keywords, properties, PR_TRUE);
 
   // this is a double fetch of the keywords property since we also fetch
   // it for the tags - do we want to do this?
   // I'm not sure anyone uses the kw- property, though it could be nice
   // for people wanting to extend the thread pane.
   nsCString keywordProperty;
   msgHdr->GetStringProperty("keywords", getter_Copies(keywordProperty));
   if (!keywordProperty.IsEmpty())
--- a/mailnews/base/src/nsMsgDBView.h
+++ b/mailnews/base/src/nsMsgDBView.h
@@ -377,17 +377,17 @@ protected:
   PRBool IsValidIndex(nsMsgViewIndex index);
   nsresult ToggleIgnored(nsMsgViewIndex * indices, PRInt32 numIndices, nsMsgViewIndex *resultIndex, PRBool *resultToggleState);
   nsresult ToggleMessageKilled(nsMsgViewIndex * indices, PRInt32 numIndices, nsMsgViewIndex *resultIndex, PRBool *resultToggleState);
   PRBool OfflineMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndices);
   PRBool NonDummyMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndices);
   PRUnichar * GetString(const PRUnichar *aStringName);
   nsresult GetPrefLocalizedString(const char *aPrefName, nsString& aResult);
   nsresult GetLabelPrefStringAndAtom(const char *aPrefName, nsString& aColor, nsIAtom** aColorAtom);
-  nsresult AppendKeywordProperties(const char *keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty);
+  nsresult AppendKeywordProperties(const nsACString& keywords, nsISupportsArray *properties, PRBool addSelectedTextProperty);
   nsresult InitLabelStrings(void);
   nsresult CopyDBView(nsMsgDBView *aNewMsgDBView, nsIMessenger *aMessengerInstance, nsIMsgWindow *aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater);
   void InitializeAtomsAndLiterals();
   virtual PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThread, nsMsgViewIndex viewIndex);
   nsresult GetImapDeleteModel(nsIMsgFolder *folder);
   nsresult UpdateDisplayMessage(nsMsgViewIndex viewPosition);
 
   PRBool AdjustReadFlag(nsIMsgDBHdr *msgHdr, PRUint32 *msgFlags);
--- a/mailnews/base/src/nsMsgTagService.cpp
+++ b/mailnews/base/src/nsMsgTagService.cpp
@@ -41,16 +41,17 @@
 #include "nsMsgTagService.h"
 #include "nsMsgBaseCID.h"
 #include "nsIPrefService.h"
 #include "nsISupportsPrimitives.h"
 #include "nsMsgI18N.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsMsgDBView.h" // for labels migration
 #include "nsQuickSort.h"
+#include "nsMsgUtils.h"
 
 #define STRLEN(s) (sizeof(s) - 1)
 
 #define TAG_PREF_VERSION        "version"
 #define TAG_PREF_SUFFIX_TAG     ".tag"
 #define TAG_PREF_SUFFIX_COLOR   ".color"
 #define TAG_PREF_SUFFIX_ORDINAL ".ordinal"
 #define TAG_CMP_LESSER          -1
@@ -210,23 +211,23 @@ NS_IMETHODIMP nsMsgTagService::GetKeyFor
       }
     }
   }
   NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, prefList);
   ToLowerCase(aKey);
   return NS_OK;
 }
 
-/* ACString getTopKey (in string keylist); */
-NS_IMETHODIMP nsMsgTagService::GetTopKey(const char * keyList, nsACString & _retval)
+/* ACString getTopKey (in ACString keylist); */
+NS_IMETHODIMP nsMsgTagService::GetTopKey(const nsACString & keyList, nsACString & _retval)
 {
   _retval.Truncate();
   // find the most important key
   nsCStringArray keyArray;
-  keyArray.ParseString(keyList, " ");
+  ParseString(keyList, ' ', keyArray);
   PRUint32 keyCount = keyArray.Count();
   nsCString *topKey = nsnull, *key, topOrdinal, ordinal;
   for (PRUint32 i = 0; i < keyCount; ++i)
   {
     key = keyArray[i];
     if (key->IsEmpty())
       continue;
 
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -2080,17 +2080,17 @@ nsMsgDBFolder::CallFilterPlugins(nsIMsgW
     spamSettings->GetWhiteListAbURI(getter_Copies(whiteListAbURI));
     NS_ENSURE_SUCCESS(rv, rv);
     if (!whiteListAbURI.IsEmpty())
     {
       nsCOMPtr <nsIRDFService> rdfService = do_GetService("@mozilla.org/rdf/rdf-service;1",&rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCStringArray whiteListArray;
-      whiteListArray.ParseString(whiteListAbURI.get(), " ");
+      ParseString(whiteListAbURI, ' ', whiteListArray);
 
       for (PRInt32 index = 0; index < whiteListArray.Count(); index++)
       {
         nsCOMPtr<nsIRDFResource> resource;
         rv = rdfService->GetResource(*whiteListArray[index], getter_AddRefs(resource));
 
         nsCOMPtr<nsIAbDirectory> whiteListDirectory =
           do_QueryInterface(resource, &rv);
@@ -5272,17 +5272,17 @@ NS_IMETHODIMP nsMsgDBFolder::AddKeywords
 
     for(PRUint32 i = 0; i < count; i++)
     {
       nsCOMPtr<nsIMsgDBHdr> message = do_QueryElementAt(aMessages, i, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       message->GetStringProperty("keywords", getter_Copies(keywords));
       nsCStringArray keywordArray;
-      keywordArray.ParseString(nsCString(aKeywords).get(), " ");
+      ParseString(aKeywords, ' ', keywordArray);
       PRUint32 addCount = 0;
       for (PRInt32 j = 0; j < keywordArray.Count(); j++)
       {
         PRInt32 start, length;
         if (!MsgFindKeyword(*(keywordArray[j]), keywords, &start, &length))
         {
           if (!keywords.IsEmpty())
             keywords.Append(' ');
@@ -5317,17 +5317,17 @@ NS_IMETHODIMP nsMsgDBFolder::RemoveKeywo
 
     for(PRUint32 i = 0; i < count; i++)
     {
       nsCOMPtr<nsIMsgDBHdr> message = do_QueryElementAt(aMessages, i, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = message->GetStringProperty("keywords", getter_Copies(keywords));
       nsCAutoString originalKeywords(keywords);
       nsCStringArray keywordArray;
-      keywordArray.ParseString(nsCString(aKeywords).get(), " ");
+      ParseString(aKeywords, ' ', keywordArray);
       PRUint32 removeCount = 0;
       for (PRInt32 j = 0; j < keywordArray.Count(); j++)
       {
         PRBool keywordIsLabel = (StringBeginsWith(*(keywordArray[j]), NS_LITERAL_CSTRING("$label"))
           && keywordArray[j]->CharAt(6) >= '1' && keywordArray[j]->CharAt(6) <= '5');
         if (keywordIsLabel)
         {
           nsMsgLabelValue labelValue;
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -1854,8 +1854,69 @@ NS_MSG_BASE nsresult MsgGetHeadersFromKe
       NS_ENSURE_SUCCESS(rv, rv);
 
       aHeaders->AppendElement(msgHdr, PR_FALSE);
     }
   }
 
   return rv;
 }
+
+NS_MSG_BASE PRBool ParseString(const char *string, const char *delims, nsCStringArray& array)
+{
+  if (string && *string && delims && *delims) {
+    PRInt32 count = array.Count();
+    nsCString copy(string);
+    char *buffer = copy.BeginWriting();
+    char *token;
+    while ((token = NS_strtok(delims, &buffer)) != nsnull) {
+      if (!array.AppendCString(nsDependentCString(token))) {
+        while (array.Count() > count)
+          array.RemoveCStringAt(array.Count() - 1);
+        return PR_FALSE;
+      }
+    }
+  }
+  return PR_TRUE;
+}
+
+NS_MSG_BASE PRBool ParseString(const nsACString& string, char delimiter, nsCStringArray& array)
+{
+  if (string.IsEmpty())
+    return PR_TRUE;
+
+  PRInt32 count = array.Count();
+  PRInt32 start = 0;
+  for (;;) {
+    PRInt32 end = string.FindChar(delimiter, start);
+    if (end != start && !array.AppendCString(Substring(string, start, end)))
+      break;
+    if (end == -1)
+      return PR_TRUE;
+    start = end + 1;
+  }
+
+  while (array.Count() > count)
+    array.RemoveCStringAt(array.Count() - 1);
+  return PR_FALSE;
+}
+
+#ifdef MOZILLA_1_9_1_BRANCH
+NS_MSG_BASE PRBool ParseString(const nsACString& string, char delimiter, nsTArray<nsCString>& array)
+{
+  if (string.IsEmpty())
+    return PR_TRUE;
+
+  PRUint32 count = array.Length();
+  PRInt32 start = 0;
+  for (;;) {
+    PRInt32 end = string.FindChar(delimiter, start);
+    if (end != start && !array.AppendElement(Substring(string, start, end)))
+      break;
+    if (end == -1)
+      return PR_TRUE;
+    start = end + 1;
+  }
+
+  array.RemoveElementsAt(count, array.Length() - count);
+  return PR_FALSE;
+}
+#endif
--- a/mailnews/base/util/nsMsgUtils.h
+++ b/mailnews/base/util/nsMsgUtils.h
@@ -207,10 +207,54 @@ NS_MSG_BASE char *MsgEscapeHTML(const ch
 
 NS_MSG_BASE PRUnichar *MsgEscapeHTML(const PRUnichar *aSourceBuffer,
                                      PRInt32 aSourceBufferLen);
 
 // Converts an array of nsMsgKeys plus a database, to an array of nsIMsgDBHdrs.
 NS_MSG_BASE nsresult MsgGetHeadersFromKeys(nsIMsgDatabase *aDB, const nsTArray<nsMsgKey> &aKeys,
                                            nsIMutableArray *aHeaders);
 
+/**
+ * Parses a given string using the delimiters passed in. Items parsed from the
+ * string will be appended to the array.
+ *
+ * @param string
+ *        The string to parse.
+ * @param delims
+ *        A set of delimter characters.
+ * @param array
+ *        The array to append tokens to.
+ * @deprecated This call needs to be converted to the nsTArray<nsCString> api.
+ */
+NS_MSG_BASE PRBool ParseString(const char *string, const char *delims, nsCStringArray& array);
+
+/**
+ * Parses a given string using the delimiter passed in. Items parsed from the
+ * string will be appended to the array.
+ *
+ * @param string
+ *        The string to parse.
+ * @param delimiter
+ *        A delimter character.
+ * @param array
+ *        The array to append tokens to.
+ * @deprecated Use an nsTArray<nsCString> instead of an nsCStringArray.
+ */
+NS_MSG_BASE PRBool ParseString(const nsACString& string, char delimiter, nsCStringArray& array);
+
+#ifdef MOZILLA_1_9_1_BRANCH
+/**
+ * Parses a given string using the delimiter passed in. Items parsed from the
+ * string will be appended to the array. This version is only used on the
+ * MOZILLA_1_9_1_BRANCH as the trunk already has a suitable function.
+ *
+ * @param string
+ *        The string to parse.
+ * @param delimiter
+ *        A delimter character.
+ * @param array
+ *        The array to append tokens to.
+ */
+NS_MSG_BASE PRBool ParseString(const nsACString& string, char delimiter, nsTArray<nsCString>& array);
 #endif
 
+#endif
+
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -529,17 +529,17 @@ mime_generate_headers (nsMsgCompFields *
     nsCOMPtr <nsINntpService> nntpService = do_GetService("@mozilla.org/messenger/nntpservice;1");
     if (NS_FAILED(rv) || !nntpService) {
       *status = NS_ERROR_FAILURE;
       return nsnull;
     }
 
     nsCString newsgroupsHeaderVal;
     nsCString newshostHeaderVal;
-    rv = nntpService->GenerateNewsHeaderValsForPosting(n2, getter_Copies(newsgroupsHeaderVal), getter_Copies(newshostHeaderVal));
+    rv = nntpService->GenerateNewsHeaderValsForPosting(nsDependentCString(n2), getter_Copies(newsgroupsHeaderVal), getter_Copies(newshostHeaderVal));
     if (NS_FAILED(rv)) 
     {
       *status = rv;
       return nsnull;
     }
 
     // fixme:the newsgroups header had better be encoded as the server-side
     // character encoding, but this |charset| might be different from it.
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -1388,27 +1388,27 @@ nsresult nsMsgComposeService::AddGlobalH
       nsCString currentHtmlDomainList;
       rv = prefBranch->GetCharPref(USER_CURRENT_HTMLDOMAINLIST_PREF_NAME, getter_Copies(currentHtmlDomainList));
       NS_ENSURE_SUCCESS(rv,rv);
 
       nsCAutoString newHtmlDomainList(currentHtmlDomainList);
       // Get the current html domain list into new list var
       nsCStringArray htmlDomainArray;
       if (!currentHtmlDomainList.IsEmpty())
-        htmlDomainArray.ParseString(currentHtmlDomainList.get(), DOMAIN_DELIMITER);
+        ParseString(currentHtmlDomainList.get(), DOMAIN_DELIMITER, htmlDomainArray);
 
       // Get user's current Plaintext domain set for send format
       nsCString currentPlaintextDomainList;
       rv = prefBranch->GetCharPref(USER_CURRENT_PLAINTEXTDOMAINLIST_PREF_NAME, getter_Copies(currentPlaintextDomainList));
       NS_ENSURE_SUCCESS(rv,rv);
 
       // Get the current plaintext domain list into new list var
       nsCStringArray plaintextDomainArray;
       if (!currentPlaintextDomainList.IsEmpty())
-        plaintextDomainArray.ParseString(currentPlaintextDomainList.get(), DOMAIN_DELIMITER);
+        ParseString(currentPlaintextDomainList.get(), DOMAIN_DELIMITER, plaintextDomainArray);
 
       if (htmlDomainArray.Count() || plaintextDomainArray.Count()) {
         // Tokenize the data and add each html domain if it is not alredy there in
         // the user's current html or plaintext domain lists
         char *newData = globalHtmlDomainList.BeginWriting();
         char *token = NS_strtok(DOMAIN_DELIMITER, &newData);
 
         nsCAutoString htmlDomain;
--- a/mailnews/compose/src/nsMsgSendLater.cpp
+++ b/mailnews/compose/src/nsMsgSendLater.cpp
@@ -706,17 +706,17 @@ nsresult nsMsgSendLater::SetOrigMsgDispo
   // or forward of.
   nsCString originalMsgURIs;
   nsCString queuedDisposition;
   mMessage->GetStringProperty(ORIG_URI_PROPERTY, getter_Copies(originalMsgURIs));
   mMessage->GetStringProperty(QUEUED_DISPOSITION_PROPERTY, getter_Copies(queuedDisposition));
   if (!queuedDisposition.IsEmpty())
   {
     nsCStringArray uriArray;
-    uriArray.ParseString(originalMsgURIs.get(), ",");
+    ParseString(originalMsgURIs, ',', uriArray);
     for (PRInt32 i = 0; i < uriArray.Count(); i++)
     {
       nsCOMPtr <nsIMsgDBHdr> msgHdr;
       nsresult rv = GetMsgDBHdrFromURI(uriArray[i]->get(), getter_AddRefs(msgHdr));
       NS_ENSURE_SUCCESS(rv,rv);
       if (msgHdr)
       {
         // get the folder for the message resource
--- a/mailnews/compose/src/nsSmtpService.cpp
+++ b/mailnews/compose/src/nsSmtpService.cpp
@@ -400,17 +400,17 @@ nsSmtpService::loadSmtpServers()
 
     //Get the pref in a tempServerList and then parse it to see if it has dupes.
     //if so remove the dupes and then create the serverList.
     if (!tempServerList.IsEmpty()) {
 
       // Tokenize the data and add each smtp server if it is not already there 
       // in the user's current smtp server list
       nsCStringArray servers;
-      servers.ParseString(tempServerList.get(), SERVER_DELIMITER);
+      ParseString(tempServerList.get(), SERVER_DELIMITER, servers);
       nsCAutoString tempSmtpServer;
       for (PRInt32 i = 0; i < servers.Count(); i++)
       {
           if (servers.IndexOf(* (servers[i])) == i) {
             tempSmtpServer.Assign(* (servers[i]));
             tempSmtpServer.StripWhitespace();
             if (!serverList.IsEmpty())
               serverList += SERVER_DELIMITER;
@@ -463,17 +463,17 @@ nsSmtpService::loadSmtpServers()
       NS_ENSURE_SUCCESS(rv,rv);
 
       // Update the smtp server list if needed
       if ((appendSmtpServersCurrentVersion <= appendSmtpServersDefaultVersion)) {
         // If there are pre-configured servers, add them to the existing server list
         if (!appendServerList.IsEmpty()) {
           if (!serverList.IsEmpty()) {
             nsCStringArray existingSmtpServersArray;
-            existingSmtpServersArray.ParseString(serverList.get(), SERVER_DELIMITER);
+            ParseString(serverList.get(), SERVER_DELIMITER, existingSmtpServersArray);
 
             // Tokenize the data and add each smtp server if it is not already there 
             // in the user's current smtp server list
             char *newSmtpServerStr = appendServerList.BeginWriting(); 
             char *token = NS_strtok(SERVER_DELIMITER, &newSmtpServerStr);
 
             nsCAutoString newSmtpServer;
             while (token) {
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -392,17 +392,17 @@ nsImapProtocol::nsImapProtocol() : nsMsg
                                 getter_AddRefs(prefString));
     if (prefString)
       prefString->ToString(getter_Copies(mAcceptLanguages));
 
     nsCString customDBHeaders;
     prefBranch->GetCharPref("mailnews.customDBHeaders",
                             getter_Copies(customDBHeaders));
 
-    mCustomDBHeaders.ParseString(customDBHeaders.get(), " ");
+    ParseString(customDBHeaders, ' ', mCustomDBHeaders);
   }
 
     // ***** Thread support *****
   m_thread = nsnull;
   m_dataAvailableMonitor = nsnull;
   m_urlReadyToRunMonitor = nsnull;
   m_pseudoInterruptMonitor = nsnull;
   m_dataMemberMonitor = nsnull;
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -3902,17 +3902,17 @@ nsresult nsMsgLocalMailFolder::ChangeKey
       NS_ENSURE_SUCCESS(rv, rv);
       PRUint32 messageOffset;
       message->GetMessageOffset(&messageOffset);
       PRUint32 statusOffset = 0;
       (void)message->GetStatusOffset(&statusOffset);
       PRUint32 desiredOffset = messageOffset + statusOffset;
 
       nsCStringArray keywordArray;
-      keywordArray.ParseString(nsCString(aKeywords).get(), " ");
+      ParseString(aKeywords, ' ', keywordArray);
       for (PRInt32 j = 0; j < keywordArray.Count(); j++)
       {
         nsCAutoString header;
         nsCAutoString keywords;
         PRBool done = PR_FALSE;
         PRUint32 len = 0;
         nsCAutoString keywordToWrite(" ");
 
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -521,17 +521,17 @@ nsParseMailMessageState::nsParseMailMess
   // "x-spam-score" property of nsMsgHdr to the value of the header.
   m_customDBHeaderValues = nsnull;
   nsCString customDBHeaders;
   nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (pPrefBranch)
   {
      pPrefBranch->GetCharPref("mailnews.customDBHeaders",  getter_Copies(customDBHeaders));
      ToLowerCase(customDBHeaders);
-     m_customDBHeaders.ParseString(customDBHeaders.get(), " ");
+     ParseString(customDBHeaders, ' ', m_customDBHeaders);
      if (m_customDBHeaders.Count())
      {
        m_customDBHeaderValues = new struct message_header [m_customDBHeaders.Count()];
        if (!m_customDBHeaderValues)
          m_customDBHeaders.Clear();
      }
   }
   Clear();
@@ -1535,18 +1535,18 @@ int nsParseMailMessageState::FinalizeHea
           m_newMsgHdr->SetPriority(nsMsgPriority::none);
         if (keywords)
         {
           // When there are many keywords, some may not have been written
           // to the message file, so add extra keywords from the backup
           nsCAutoString oldKeywords;
           m_newMsgHdr->GetStringProperty("keywords", getter_Copies(oldKeywords));
           nsCStringArray newKeywordArray, oldKeywordArray;
-          newKeywordArray.ParseString(keywords->value, " ");
-          oldKeywordArray.ParseString(oldKeywords.get(), " ");
+          ParseString(Substring(keywords->value, keywords->value + keywords->length), ' ', newKeywordArray);
+          ParseString(oldKeywords, ' ', oldKeywordArray);
           for (PRInt32 i = 0; i < oldKeywordArray.Count(); i++)
             if (newKeywordArray.IndexOf(*oldKeywordArray.CStringAt(i)) < 0)
               newKeywordArray.AppendCString(*oldKeywordArray.CStringAt(i));
           nsCAutoString newKeywords;
           for (PRInt32 i = 0; i < newKeywordArray.Count(); i++)
           {
             if (i)
               newKeywords.Append(" ");
--- a/mailnews/local/src/nsPop3Protocol.cpp
+++ b/mailnews/local/src/nsPop3Protocol.cpp
@@ -271,17 +271,17 @@ net_pop3_load_state(const char* searchho
       }
     }
     else
     {
       /* It's a line with a UIDL on it. */
       if (current)
       {
         nsCStringArray lineElems;
-        lineElems.ParseString(line.get(), " \t");
+        ParseString(line.get(), " \t", lineElems);
         if (lineElems.Count() < 2)
           continue;
         nsCString *flags = lineElems[0];
         nsCString *uidl = lineElems[1];
         nsCString *dateReceivedStr = lineElems[2]; // will be null if only 2 elements.
         PRUint32 dateReceived = TimeInSecondsFromPRTime(PR_Now()); // if we don't find a date str, assume now.
         if (dateReceivedStr && !dateReceivedStr->IsEmpty())
           dateReceived = atoi(dateReceivedStr->get());
--- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp
@@ -56,21 +56,60 @@
 #include "nsServiceManagerUtils.h"
 // hack: include this to fix opening news attachments.
 #include "nsINntpUrl.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIMimeConverter.h"
 #include "nsMsgMimeCID.h"
 #include "nsDateTimeFormatCID.h"
 #include "nsMsgUtils.h"
+#include "nsAutoPtr.h"
 #include "nsINetUtil.h"
 #include "nsMemory.h"
 
 #define VIEW_ALL_HEADERS 2
 
+/**
+ * A helper class to implement nsIUTF8StringEnumerator
+ */
+
+class nsMimeStringEnumerator : public nsIUTF8StringEnumerator {
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIUTF8STRINGENUMERATOR
+
+  template<class T>
+  nsCString* Append(T value) { return values.AppendElement(value); }
+
+protected:
+  nsTArray<nsCString> values;
+};
+
+NS_IMPL_ISUPPORTS1(nsMimeStringEnumerator, nsIUTF8StringEnumerator)
+
+NS_IMETHODIMP
+nsMimeStringEnumerator::HasMore(PRBool *result)
+{
+  NS_ENSURE_ARG_POINTER(result);
+  *result = values.Length() != 0;
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsMimeStringEnumerator::GetNext(nsACString& result)
+{
+  PRUint32 length = values.Length();
+  if (!length)
+    return NS_ERROR_UNEXPECTED;
+
+  length--;
+  result = values[length];
+  values.RemoveElementAt(length);
+  return NS_OK;
+}
+
 /*
  * nsMimeHtmlEmitter definitions....
  */
 nsMimeHtmlDisplayEmitter::nsMimeHtmlDisplayEmitter() : nsMimeBaseEmitter()
 {
   mFirst = PR_TRUE;
   mSkipAttachment = PR_FALSE;
 }
@@ -150,38 +189,37 @@ nsMimeHtmlDisplayEmitter::GetHeaderSink(
   *aHeaderSink = mHeaderSink;
   NS_IF_ADDREF(*aHeaderSink);
   return rv;
 }
 
 nsresult nsMimeHtmlDisplayEmitter::BroadcastHeaders(nsIMsgHeaderSink * aHeaderSink, PRInt32 aHeaderMode, PRBool aFromNewsgroup)
 {
   // two string enumerators to pass out to the header sink
-  nsCOMPtr<nsIUTF8StringEnumerator> headerNameEnumerator;
-  nsCOMPtr<nsIUTF8StringEnumerator> headerValueEnumerator;
+  nsRefPtr<nsMimeStringEnumerator> headerNameEnumerator = new nsMimeStringEnumerator();
+  NS_ENSURE_TRUE(headerNameEnumerator, NS_ERROR_OUT_OF_MEMORY);
+  nsRefPtr<nsMimeStringEnumerator> headerValueEnumerator = new nsMimeStringEnumerator();
+  NS_ENSURE_TRUE(headerValueEnumerator, NS_ERROR_OUT_OF_MEMORY);
 
-  // CStringArrays which we can pass into the enumerators
-  nsCStringArray headerNameArray;
-  nsCStringArray headerValueArray;
   nsCString extraExpandedHeaders;
   nsCStringArray extraExpandedHeadersArray;
   nsCAutoString convertedDateString;
 
   PRBool displayOriginalDate = PR_FALSE;
   nsresult rv;
   nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
   if (pPrefBranch)
   {
     pPrefBranch->GetBoolPref("mailnews.display.original_date", &displayOriginalDate);
     pPrefBranch->GetCharPref("mailnews.headers.extraExpandedHeaders", getter_Copies(extraExpandedHeaders));
     // todo - should make this upper case
     if (!extraExpandedHeaders.IsEmpty())
     {
       ToLowerCase(extraExpandedHeaders);
-      extraExpandedHeadersArray.ParseString(extraExpandedHeaders.get(), " ");
+      ParseString(extraExpandedHeaders, ' ', extraExpandedHeadersArray);
     }
 
   }
 
   for (PRInt32 i=0; i<mHeaderArray->Count(); i++)
   {
     headerInfoType * headerInfo = (headerInfoType *) mHeaderArray->ElementAt(i);
     if ( (!headerInfo) || (!headerInfo->name) || (!(*headerInfo->name)) || (!headerInfo->value) || (!(*headerInfo->value)))
@@ -208,31 +246,24 @@ nsresult nsMimeHtmlDisplayEmitter::Broad
          (!extraExpandedHeadersArray.Count() || (ToLowerCase(headerStr),
             extraExpandedHeadersArray.IndexOf(headerStr) == -1)))
             continue;
     }
 
     if (!PL_strcasecmp("Date", headerInfo->name) && !displayOriginalDate)
     {
       GenerateDateString(headerValue, convertedDateString);
-      headerValueArray.AppendCString(convertedDateString);
+      headerValueEnumerator->Append(convertedDateString);
     }
     else // append the header value as is
-      headerValueArray.AppendCString(nsCString(headerValue));
+      headerValueEnumerator->Append(headerValue);
 
-    // XXX: TODO If nsCStringArray were converted over to take nsACStrings instead of nsCStrings, we can just
-    // wrap these strings with a nsDependentCString which would avoid making a duplicate copy of the string
-    // like we are doing here....
-    headerNameArray.AppendCString(nsCString(headerInfo->name));
+    headerNameEnumerator->Append(headerInfo->name);
   }
 
-  // turn our string arrays into enumerators
-  NS_NewUTF8StringEnumerator(getter_AddRefs(headerNameEnumerator), &headerNameArray);
-  NS_NewUTF8StringEnumerator(getter_AddRefs(headerValueEnumerator), &headerValueArray);
-
   aHeaderSink->ProcessHeaders(headerNameEnumerator, headerValueEnumerator, aFromNewsgroup);
   return rv;
 }
 
 NS_IMETHODIMP nsMimeHtmlDisplayEmitter::WriteHTMLHeaders()
 {
   // if we aren't broadcasting headers OR printing...just do whatever
   // our base class does...
--- a/mailnews/mime/src/mimeobj.cpp
+++ b/mailnews/mime/src/mimeobj.cpp
@@ -46,16 +46,17 @@
 #include "mimeobj.h"
 #include "prmem.h"
 #include "plstr.h"
 #include "prio.h"
 #include "mimebuf.h"
 #include "prlog.h"
 #include "nsMimeTypes.h"
 #include "nsMimeStringResources.h"
+#include "nsMsgUtils.h"
 #include "mimemsg.h"
 #include "mimemapl.h"
 
 /* Way to destroy any notions of modularity or class hierarchy, Terry! */
 # include "mimetpla.h"
 # include "mimethtm.h"
 # include "mimecont.h"
 
@@ -207,23 +208,22 @@ MimeObject_parse_begin (MimeObject *obj)
     obj->options->state->separator_suppressed_p = PR_TRUE; /* no first sep */
     const char *delParts = PL_strcasestr(obj->options->url, "&del=");
     const char *detachLocations = PL_strcasestr(obj->options->url, "&detachTo=");
     if (delParts)
     {
       const char *delEnd = PL_strcasestr(delParts + 1, "&");
       if (!delEnd)
         delEnd = delParts + strlen(delParts);
-      nsCAutoString partsToDel(Substring(delParts + 5, delEnd));
-      obj->options->state->partsToStrip.ParseString(partsToDel.get(), ",");
+      ParseString(Substring(delParts + 5, delEnd), ',', obj->options->state->partsToStrip);
     }
     if (detachLocations)
     {
       detachLocations += 10; // advance past "&detachTo="
-      obj->options->state->detachToFiles.ParseString(detachLocations, ",");
+      ParseString(nsDependentCString(detachLocations), ',', obj->options->state->detachToFiles);
     }
   }
 
   /* Decide whether this object should be output or not... */
   if (!obj->options || !obj->options->output_fn
     /* if we are decomposing the message in files and processing a multipart object,
        we must not output it without parsing it first */
      || (obj->options->decompose_file_p && obj->options->decompose_file_output_fn &&
--- a/mailnews/news/build/Makefile.in
+++ b/mailnews/news/build/Makefile.in
@@ -77,18 +77,17 @@ SHARED_LIBRARY_LIBS = ../src/$(LIB_PREFI
 
 ifeq ($(USE_SHORT_LIBNAME),1)
 EXTRA_DSO_LIBS += msgbsutl
 else
 EXTRA_DSO_LIBS += msgbaseutil
 endif
 
 EXTRA_DSO_LDOPTS = \
-		-L$(DIST)/bin \
-		-L$(DIST)/lib \
+		$(LIBS_DIR) \
 		$(MOZDEPTH)/rdf/util/src/internal/$(LIB_PREFIX)rdfutil_s.$(LIB_SUFFIX) \
 		$(EXTRA_DSO_LIBS) \
 		$(MOZ_COMPONENT_LIBS) \
 		$(MOZ_UNICHARUTIL_LIBS) \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/mailnews/news/public/nsINntpService.idl
+++ b/mailnews/news/public/nsINntpService.idl
@@ -44,30 +44,30 @@
 
 interface nsIURI;
 interface nsIStreamListener;  
 interface nsIFile;
 interface nsIMsgWindow;
 interface nsIMsgFolder;
 interface nsICacheSession;
 
-[scriptable, uuid(2777d192-fb8b-46b1-8c4c-8aa8ca62b011)]
+[scriptable, uuid(ecd8087f-f71a-4d44-a285-4caacd57f217)]
 interface nsINntpService : nsISupports {
   
   /* newsgroupsList is a comma separated list of newsgroups, which may be
    * in news://host/group or group form
    * "news://host/group1,news://host/group2" or "group1,group2"
    *
    * newsgroupsHeaderVal is a comma separated list of groups in the group form
    * "group1,group2"
    *
    * newshostHeaderVal is a single hostname.
    * "host"
    */
-  void generateNewsHeaderValsForPosting(in string newsgroupsList, out string newsgroupsHeaderVal, out string newshostHeaderVal);
+  void generateNewsHeaderValsForPosting(in ACString newsgroupsList, out string newsgroupsHeaderVal, out string newshostHeaderVal);
 
   nsIURI postMessage(in nsIFile aFileToPost, in string newsgroupNames, in string aAccountKey, in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow);
 
   nsIURI getNewNews(in nsINntpIncomingServer nntpServer, in string uri, in boolean getOld, in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow);
 
   nsIURI cancelMessage(in string cancelURL, in string messageURI, in nsISupports aConsumer, in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow);
  
   void getListOfGroupsOnServer(in nsINntpIncomingServer nntpServer, in nsIMsgWindow aMsgWindow, in boolean getOnlyNew);
--- a/mailnews/news/src/nsNNTPNewsgroupList.cpp
+++ b/mailnews/news/src/nsNNTPNewsgroupList.cpp
@@ -134,29 +134,29 @@ nsNNTPNewsgroupList::Initialize(nsINntpU
 
   nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(m_newsFolder, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   rv = folder->GetFilterList(m_msgWindow, getter_AddRefs(m_filterList));
   NS_ENSURE_SUCCESS(rv,rv);
   nsCString ngHeaders;
   m_filterList->GetArbitraryHeaders(ngHeaders);
-  m_filterHeaders.ParseString(ngHeaders.get(), " ");
+  ParseString(ngHeaders, ' ', m_filterHeaders);
 
   nsCOMPtr<nsIMsgIncomingServer> server;
   rv = folder->GetServer(getter_AddRefs(server));
   NS_ENSURE_SUCCESS(rv,rv);
 
   rv = server->GetFilterList(m_msgWindow, getter_AddRefs(m_serverFilterList));
   NS_ENSURE_SUCCESS(rv,rv);
   nsCAutoString servHeaders;
   m_serverFilterList->GetArbitraryHeaders(servHeaders);
 
   nsCStringArray servArray;
-  servArray.ParseString(servHeaders.get(), " ");
+  ParseString(servHeaders, ' ', servArray);
 
   // servArray may have duplicates already in m_filterHeaders.
   for (PRInt32 i = 0; i < servArray.Count(); i++)
   {
     if (m_filterHeaders.IndexOf(*(servArray[i])) == -1)
       m_filterHeaders.AppendCString(*(servArray[i]));
   }
   return NS_OK;
--- a/mailnews/news/src/nsNntpService.cpp
+++ b/mailnews/news/src/nsNntpService.cpp
@@ -819,40 +819,38 @@ nsNntpService::SetUpNntpUrlForPosting(co
   if (!*newsUrlSpec) return NS_ERROR_FAILURE;
   return NS_OK;
 }
 ////////////////////////////////////////////////////////////////////////////////
 // nsINntpService support
 ////////////////////////////////////////////////////////////////////////////////
 // XXX : may not work with non-ASCII newsgroup names and IDN hostnames
 NS_IMETHODIMP
-nsNntpService::GenerateNewsHeaderValsForPosting(const char *newsgroupsList, char **newsgroupsHeaderVal, char **newshostHeaderVal)
+nsNntpService::GenerateNewsHeaderValsForPosting(const nsACString& newsgroupsList, char **newsgroupsHeaderVal, char **newshostHeaderVal)
 {
   nsresult rv = NS_OK;
 
-  NS_ENSURE_ARG_POINTER(newsgroupsList);
   NS_ENSURE_ARG_POINTER(newsgroupsHeaderVal);
   NS_ENSURE_ARG_POINTER(newshostHeaderVal);
-  NS_ENSURE_ARG_POINTER(*newsgroupsList);
 
   // newsgroupsList can be a comma separated list of these:
   // news://host/group
   // news://group
   // host/group
   // group
   //
   // we are not going to allow the user to cross post to multiple hosts.
   // if we detect that, we stop and return error.
 
   nsCAutoString host;
   nsCAutoString str;
   nsCAutoString newsgroups;
 
   nsCStringArray list;
-  list.ParseString(newsgroupsList, ",");
+  ParseString(newsgroupsList, ',', list);
   for (PRInt32 index = 0; index < list.Count(); index++)
   {
     list[index]->StripWhitespace();
     if (!list[index]->IsEmpty())
     {
       nsCAutoString currentHost;
       nsCAutoString theRest;
       // does str start with "news:/"?