Bug 790852 - Make nsIMimeHeaders use the new MIME parser, part 1: use nsCString in nsIMimeHeaders. r=rkent, sr=Neil
authorJoshua Cranmer <Pidgeot18@gmail.com>
Wed, 30 May 2012 09:03:08 -0500
changeset 14766 510be186d4c77b3c7201f3692ac549b541849663
parent 14765 3ac1f861d15164573cc5dd2232e99d3564f388cd
child 14767 b0ee9c28b03ad6d2ddbed587d35e931dc6a4958e
push id867
push userbugzilla@standard8.plus.com
push dateMon, 01 Apr 2013 20:44:27 +0000
treeherdercomm-beta@797726b8d244 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrkent, Neil
bugs790852
Bug 790852 - Make nsIMimeHeaders use the new MIME parser, part 1: use nsCString in nsIMimeHeaders. r=rkent, sr=Neil
mail/components/search/WinSearchIntegration.js
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/compose/src/nsMsgCompose.cpp
mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
mailnews/extensions/mdn/test/unit/test_askuser.js
mailnews/extensions/mdn/test/unit/test_mdnFlags.js
mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
mailnews/mime/public/nsIMimeHeaders.idl
mailnews/mime/src/nsMimeHeaders.cpp
mailnews/mime/src/nsStreamConverter.cpp
mailnews/mime/test/unit/test_mimeContentType.js
--- a/mail/components/search/WinSearchIntegration.js
+++ b/mail/components/search/WinSearchIntegration.js
@@ -269,17 +269,17 @@ let SearchIntegration =
                                                contentType);
 
         // To get the Received header, we need to parse the message headers.
         // We only need the first header, which contains the latest received
         // date
         let headers = this._message.split(/\r\n\r\n|\r\r|\n\n/, 1)[0];
         let mimeHeaders = Cc["@mozilla.org/messenger/mimeheaders;1"]
                             .createInstance(Ci.nsIMimeHeaders);
-        mimeHeaders.initialize(headers, headers.length);
+        mimeHeaders.initialize(headers);
         let receivedHeader = mimeHeaders.extractHeader("Received", false);
 
         this._outputStream.writeString("From: " + this._msgHdr.author + CRLF);
         // If we're a newsgroup, then add the name of the folder as the
         // newsgroups header
         if (folder instanceof Ci.nsIMsgNewsFolder)
           this._outputStream.writeString("Newsgroups: " + folder.name + CRLF);
         else
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -5440,21 +5440,21 @@ NS_IMETHODIMP nsMsgDBFolder::GetMsgTextF
         break;
     }
 
     // There's no point in processing if we can't get the body
     if (bytesRead > bytesToRead)
       break;
 
     // Process the headers, looking for things we need
-    rv = mimeHeaders->Initialize(msgHeaders.get(), msgHeaders.Length());
+    rv = mimeHeaders->Initialize(msgHeaders);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString contentTypeHdr;
-    mimeHeaders->ExtractHeader("Content-Type", false, getter_Copies(contentTypeHdr));
+    mimeHeaders->ExtractHeader("Content-Type", false, contentTypeHdr);
 
     // Get the content type
     // If we don't have a content type, then we assign text/plain
     // this is in violation of the RFC for multipart/digest, though
     // Also, if we've just passed an end boundary, we're going to ignore this.
     if (!justPassedEndBoundary && contentTypeHdr.IsEmpty())
       contentType.Assign(NS_LITERAL_STRING("text/plain"));
     else
@@ -5492,17 +5492,17 @@ NS_IMETHODIMP nsMsgDBFolder::GetMsgTextF
       {
         nsAutoString charsetW;
         mimeHdrParam->GetParameter(contentTypeHdr, "charset", EmptyCString(), false, nullptr, charsetW);
         charset.Assign(NS_ConvertUTF16toUTF8(charsetW));
       }
 
       // Finally, get the encoding
       nsAutoCString encodingHdr;
-      mimeHeaders->ExtractHeader("Content-Transfer-Encoding", false, getter_Copies(encodingHdr));
+      mimeHeaders->ExtractHeader("Content-Transfer-Encoding", false, encodingHdr);
       if (!encodingHdr.IsEmpty())
         mimeHdrParam->GetParameter(encodingHdr, nullptr, EmptyCString(), false, nullptr, encoding);
 
       if (encoding.LowerCaseEqualsLiteral(ENCODING_BASE64))
         isBase64 = true;
     }
 
     // We need to consume the rest, until the next headers
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -2479,51 +2479,50 @@ NS_IMETHODIMP QuotingOutputStreamListene
       if (!mMimeConverter)
       {
         mMimeConverter = do_GetService(NS_MIME_CONVERTER_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       nsCString charset;
       compFields->GetCharacterSet(getter_Copies(charset));
 
-      mHeaders->ExtractHeader(HEADER_FROM, true, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_FROM, true, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), from);
 
-      mHeaders->ExtractHeader(HEADER_TO, true, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_TO, true, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), to);
 
-      mHeaders->ExtractHeader(HEADER_CC, true, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_CC, true, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), cc);
 
-      mHeaders->ExtractHeader(HEADER_MAIL_FOLLOWUP_TO, true,
-                              getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_MAIL_FOLLOWUP_TO, true, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), mailFollowupTo);
 
-      mHeaders->ExtractHeader(HEADER_REPLY_TO, false, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_REPLY_TO, false, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), replyTo);
 
-      mHeaders->ExtractHeader(HEADER_MAIL_REPLY_TO, true, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_MAIL_REPLY_TO, true, outCString);
       ConvertRawBytesToUTF16(outCString, charset.get(), mailReplyTo);
 
-      mHeaders->ExtractHeader(HEADER_NEWSGROUPS, false, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_NEWSGROUPS, false, outCString);
       if (!outCString.IsEmpty())
         mMimeConverter->DecodeMimeHeader(outCString.get(), charset.get(),
                                          false, true, newgroups);
 
-      mHeaders->ExtractHeader(HEADER_FOLLOWUP_TO, false, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_FOLLOWUP_TO, false, outCString);
       if (!outCString.IsEmpty())
         mMimeConverter->DecodeMimeHeader(outCString.get(), charset.get(),
                                          false, true, followUpTo);
 
-      mHeaders->ExtractHeader(HEADER_MESSAGE_ID, false, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_MESSAGE_ID, false, outCString);
       if (!outCString.IsEmpty())
         mMimeConverter->DecodeMimeHeader(outCString.get(), charset.get(),
                                          false, true, messageId);
 
-      mHeaders->ExtractHeader(HEADER_REFERENCES, false, getter_Copies(outCString));
+      mHeaders->ExtractHeader(HEADER_REFERENCES, false, outCString);
       if (!outCString.IsEmpty())
         mMimeConverter->DecodeMimeHeader(outCString.get(), charset.get(),
                                          false, true, references);
 
       nsCOMPtr<nsIMsgHeaderParser> parser =
         do_GetService(NS_MAILNEWS_MIME_HEADER_PARSER_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2695,32 +2694,32 @@ NS_IMETHODIMP QuotingOutputStreamListene
           // handle Mail-Followup-To (http://cr.yp.to/proto/replyto.html)
 
           compFields->SetTo(mailFollowupTo);
           compFields->SetCc(EmptyString());
         }
 
         // Preserve BCC for the reply-to-self case (can be known if replying
         // from the Sent folder).
-        mHeaders->ExtractHeader(HEADER_BCC, true, getter_Copies(outCString));
+        mHeaders->ExtractHeader(HEADER_BCC, true, outCString);
         if (!outCString.IsEmpty())
         {
           nsAutoString bcc;
           ConvertRawBytesToUTF16(outCString, charset.get(), bcc);
           compFields->SetBcc(bcc);
         }
       }
       else if (type == nsIMsgCompType::ReplyToList)
       {
         if (isReplyToSelf)
         {
           compFields->SetTo(to);
         }
         else {
-          mHeaders->ExtractHeader(HEADER_LIST_POST, true, getter_Copies(outCString));
+          mHeaders->ExtractHeader(HEADER_LIST_POST, true, outCString);
           if (!outCString.IsEmpty())
             mMimeConverter->DecodeMimeHeader(outCString.get(), charset.get(),
                                              false, true, listPost);
 
           if (!listPost.IsEmpty())
           {
             int32_t startPos = listPost.Find("<mailto:");
             int32_t endPos = listPost.FindChar('>', startPos);
--- a/mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
+++ b/mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
@@ -321,18 +321,18 @@ bool nsMsgMdnGenerator::MailAddrMatch(co
 bool nsMsgMdnGenerator::NotInToOrCc()
 {
     DEBUG_MDN("nsMsgMdnGenerator::NotInToOrCc");
     nsCString reply_to;
     nsCString to;
     nsCString cc;
 
     m_identity->GetReplyTo(reply_to);
-    m_headers->ExtractHeader(HEADER_TO, true, getter_Copies(to));
-    m_headers->ExtractHeader(HEADER_CC, true, getter_Copies(cc));
+    m_headers->ExtractHeader(HEADER_TO, true, to);
+    m_headers->ExtractHeader(HEADER_CC, true, cc);
 
   // start with a simple check
   if ((!to.IsEmpty() && PL_strcasestr(to.get(), m_email.get())) ||
       (!cc.IsEmpty() && PL_strcasestr(cc.get(), m_email.get()))) {
       return false;
   }
 
   if ((!reply_to.IsEmpty() && !to.IsEmpty() && PL_strcasestr(to.get(), reply_to.get())) ||
@@ -346,18 +346,17 @@ bool nsMsgMdnGenerator::ValidateReturnPa
 {
     DEBUG_MDN("nsMsgMdnGenerator::ValidateReturnPath");
     // ValidateReturnPath applies to Automatic Send Mode only. If we were not
     // in auto send mode we simply by passing the check
     if (!m_autoSend)
         return m_reallySendMdn;
 
     nsCString returnPath;
-    m_headers->ExtractHeader(HEADER_RETURN_PATH, false,
-                             getter_Copies(returnPath));
+    m_headers->ExtractHeader(HEADER_RETURN_PATH, false, returnPath);
     if (returnPath.IsEmpty())
     {
       m_autoSend = false;
       return m_reallySendMdn;
     }
     m_autoSend = MailAddrMatch(returnPath.get(), m_dntRrt.get());
     return m_reallySendMdn;
 }
@@ -535,17 +534,17 @@ nsresult nsMsgMdnGenerator::CreateFirstP
         return rv;
 
     receipt_string.AppendLiteral(" - ");
 
     char * encodedReceiptString = nsMsgI18NEncodeMimePartIIStr(NS_ConvertUTF16toUTF8(receipt_string).get(), false,
                                                                "UTF-8", 0, conformToStandard);
 
     nsCString subject;
-    m_headers->ExtractHeader(HEADER_SUBJECT, false, getter_Copies(subject));
+    m_headers->ExtractHeader(HEADER_SUBJECT, false, subject);
     convbuf = nsMsgI18NEncodeMimePartIIStr(subject.Length() ? subject.get() : "[no subject]",
                                            false, m_charset.get(), 0, conformToStandard);
     tmpBuffer = PR_smprintf("Subject: %s%s" CRLF,
                              encodedReceiptString,
                             (convbuf ? convbuf : (subject.Length() ? subject.get() :
                               "[no subject]")));
 
     PUSH_N_FREE_STRING(tmpBuffer);
@@ -556,18 +555,17 @@ nsresult nsMsgMdnGenerator::CreateFirstP
     tmpBuffer = PR_smprintf("To: %s" CRLF, convbuf ? convbuf :
                             m_dntRrt.get());
     PUSH_N_FREE_STRING(tmpBuffer);
 
     PR_Free(convbuf);
 
   // *** This is not in the spec. I am adding this so we could do
   // threading
-    m_headers->ExtractHeader(HEADER_MESSAGE_ID, false,
-                             getter_Copies(m_messageId));
+    m_headers->ExtractHeader(HEADER_MESSAGE_ID, false, m_messageId);
 
     if (!m_messageId.IsEmpty())
     {
       if (*m_messageId.get() == '<')
           tmpBuffer = PR_smprintf("References: %s" CRLF, m_messageId.get());
       else
           tmpBuffer = PR_smprintf("References: <%s>" CRLF, m_messageId.get());
       PUSH_N_FREE_STRING(tmpBuffer);
@@ -690,17 +688,17 @@ nsresult nsMsgMdnGenerator::CreateSecond
         tmpBuffer = PR_smprintf("Reporting-UA: %s" CRLF,
                                 userAgentString.get());
         PUSH_N_FREE_STRING(tmpBuffer);
       }
     }
 
     nsCString originalRecipient;
     m_headers->ExtractHeader(HEADER_ORIGINAL_RECIPIENT, false,
-                             getter_Copies(originalRecipient));
+                             originalRecipient);
 
     if (!originalRecipient.IsEmpty())
     {
         tmpBuffer = PR_smprintf("Original-Recipient: %s" CRLF,
                                 originalRecipient.get());
         PUSH_N_FREE_STRING(tmpBuffer);
     }
 
@@ -770,17 +768,17 @@ nsresult nsMsgMdnGenerator::CreateThirdP
 
 nsresult nsMsgMdnGenerator::OutputAllHeaders()
 {
     DEBUG_MDN("nsMsgMdnGenerator::OutputAllHeaders");
     nsCString all_headers;
     int32_t all_headers_size = 0;
     nsresult rv = NS_OK;
 
-    rv = m_headers->GetAllHeaders(getter_Copies(all_headers));
+    rv = m_headers->GetAllHeaders(all_headers);
     if (NS_FAILED(rv))
         return rv;
     all_headers_size = all_headers.Length();
     char *buf = (char *) all_headers.get(),
         *buf_end = (char *) all_headers.get()+all_headers_size;
     char *start = buf, *end = buf;
 
     while (buf < buf_end)
@@ -883,30 +881,30 @@ nsresult nsMsgMdnGenerator::InitAndProce
     if (accountManager && m_server)
     {
         if (!m_identity)
         {
           // check if this is a message delivered to the global inbox,
           // in which case we find the originating account's identity.
           nsCString accountKey;
           m_headers->ExtractHeader(HEADER_X_MOZILLA_ACCOUNT_KEY, false,
-                               getter_Copies(accountKey));
+                                   accountKey);
           nsCOMPtr <nsIMsgAccount> account;
           if (!accountKey.IsEmpty())
             accountManager->GetAccount(accountKey, getter_AddRefs(account));
           if (account)
             account->GetIncomingServer(getter_AddRefs(m_server));
 
           if (m_server)
           {
             // Find the correct identity based on the "To:" and "Cc:" header
             nsCString mailTo;
             nsCString mailCC;
-            m_headers->ExtractHeader(HEADER_TO, true, getter_Copies(mailTo));
-            m_headers->ExtractHeader(HEADER_CC, true, getter_Copies(mailCC));
+            m_headers->ExtractHeader(HEADER_TO, true, mailTo);
+            m_headers->ExtractHeader(HEADER_CC, true, mailCC);
             nsCOMPtr<nsIArray> servIdentities;
             accountManager->GetIdentitiesForServer(m_server, getter_AddRefs(servIdentities));
             if (servIdentities)
             {
               nsCOMPtr<nsIMsgIdentity> ident;
               nsCString identEmail;
               uint32_t count = 0;
               servIdentities->GetLength(&count);
@@ -987,20 +985,20 @@ nsresult nsMsgMdnGenerator::InitAndProce
             }
         }
     }
 
     rv = m_folder->GetCharset(m_charset);
     if (m_mdnEnabled)
     {
         m_headers->ExtractHeader(HEADER_DISPOSITION_NOTIFICATION_TO, false,
-                                 getter_Copies(m_dntRrt));
+                                 m_dntRrt);
         if (m_dntRrt.IsEmpty())
             m_headers->ExtractHeader(HEADER_RETURN_RECEIPT_TO, false,
-                                     getter_Copies(m_dntRrt));
+                                     m_dntRrt);
         if (!m_dntRrt.IsEmpty() && ProcessSendMode() && ValidateReturnPath())
         {
             if (!m_autoSend)
             {
                 *needToAskUser = true;
                 rv = NS_OK;
             }
             else
--- a/mailnews/extensions/mdn/test/unit/test_askuser.js
+++ b/mailnews/extensions/mdn/test/unit/test_askuser.js
@@ -18,17 +18,17 @@ function run_test()
   var headers = 
     "from: alice@t1.example.com\r\n" + 
     "to: bob@t2.exemple.net\r\n" + 
     "return-path: alice@t1.example.com\r\n" +
     "Disposition-Notification-To: alice@t1.example.com\r\n";
 
   let mimeHdr = Components.classes["@mozilla.org/messenger/mimeheaders;1"]
                   .createInstance(Components.interfaces.nsIMimeHeaders);
-  mimeHdr.initialize(headers, headers.length);
+  mimeHdr.initialize(headers);
   let receivedHeader = mimeHdr.extractHeader("To", false);
   dump(receivedHeader+"\n");
 
   let localFolder = gLocalInboxFolder.QueryInterface(Ci.nsIMsgLocalMailFolder);
   gLocalInboxFolder.addMessage("From \r\n"+ headers + "\r\nhello\r\n");
   // Need to setup some prefs  
   Services.prefs.setBoolPref("mail.mdn.report.enabled", true);
   Services.prefs.setIntPref("mail.mdn.report.not_in_to_cc", 2);
--- a/mailnews/extensions/mdn/test/unit/test_mdnFlags.js
+++ b/mailnews/extensions/mdn/test/unit/test_mdnFlags.js
@@ -26,17 +26,17 @@ function run_test()
   var headers = 
     "from: alice@t1.example.com\r\n" +
     "to: bob@t2.exemple.net\r\n" +
     "return-path: alice@t1.example.com\r\n" +
     "Disposition-Notification-To: alice@t1.example.com\r\n";
 
   let mimeHdr = Components.classes["@mozilla.org/messenger/mimeheaders;1"]
                   .createInstance(Components.interfaces.nsIMimeHeaders);
-  mimeHdr.initialize(headers, headers.length);
+  mimeHdr.initialize(headers);
   let receivedHeader = mimeHdr.extractHeader("To", false);
 
   let localFolder = gLocalInboxFolder.QueryInterface(Ci.nsIMsgLocalMailFolder);
   gLocalInboxFolder.addMessage("From \r\n"+ headers + "\r\nhello\r\n");
   // Need to setup some prefs  
   Services.prefs.setBoolPref("mail.mdn.report.enabled", true);
   Services.prefs.setIntPref("mail.mdn.report.not_in_to_cc", 2);
   Services.prefs.setIntPref("mail.mdn.report.other", 2);
--- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
+++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp
@@ -648,17 +648,17 @@ nsMimeBaseEmitter::AddAllHeaders(const n
   if (mDocHeader) //We want to set only the main headers of a message, not the potentially embedded one
   {
     nsresult rv;
     nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(mURL));
     if (msgurl)
     {
         nsCOMPtr<nsIMimeHeaders> mimeHeaders = do_CreateInstance(NS_IMIMEHEADERS_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
-        mimeHeaders->Initialize(allheaders.BeginReading(), allheaders.Length());
+        mimeHeaders->Initialize(allheaders);
         msgurl->SetMimeHeaders(mimeHeaders);
     }
   }
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // The following code is responsible for formatting headers in a manner that is
--- a/mailnews/mime/public/nsIMimeHeaders.idl
+++ b/mailnews/mime/public/nsIMimeHeaders.idl
@@ -10,21 +10,31 @@
 #define NS_IMIMEHEADERS_CONTRACTID \
   "@mozilla.org/messenger/mimeheaders;1"
 // {9C4DA772-07EB-11d3-8EE5-00A024669799}
 #define NS_IMIMEHEADERS_CID \
     { 0x13e16677, 0x6648, 0x11d3, \
     { 0xa7, 0x2f, 0x0, 0x60, 0xb0, 0xeb, 0x39, 0xb5 } }
 %}
 
-/* 
- * nsIMimeHeaders Interface declaration 
+/** 
+ * An interface that can extract individual headers from a body of headers.
  */ 
-[scriptable, uuid(13E16676-6648-11d3-A72F-0060B0EB39B5)]
+[scriptable, uuid(877af00d-1ce8-446a-b4ce-b7cb1edd2791)]
 interface nsIMimeHeaders : nsISupports {
-  void initialize([const] in string allHeaders, in long allHeadersSize);
-  string extractHeader ([const] in string headerName, in boolean getAllOfThem);
-  readonly attribute string allHeaders;
+  /// Feed in the text of headers
+  void initialize(in ACString allHeaders);
+
+  /**
+   * Get the text of a header.
+   *
+   * Leading and trailing whitespace from headers will be stripped from the
+   * return value. If getAllOfThem is set to true, then the returned string will
+   * have all of the values of the header, in order, joined with the ',\n\t',
+   * where the newline is the appropriate newline for the current platform.
+   *
+   * If the header is not present, then the returned value is NULL.
+   */
+  ACString extractHeader(in string headerName, in boolean getAllOfThem);
+
+  /// The current text of all header data.
+  readonly attribute ACString allHeaders;
 };
-
-%{C++
-nsresult NS_NewMimeHeaders(const nsIID &aIID, void ** aInstancePtrResult);
-%}
--- a/mailnews/mime/src/nsMimeHeaders.cpp
+++ b/mailnews/mime/src/nsMimeHeaders.cpp
@@ -1,60 +1,58 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "msgCore.h"    // precompiled header...
 #include "nsMimeHeaders.h"
-#include "prmem.h"
 
 nsMimeHeaders::nsMimeHeaders() :
   mHeaders(nullptr)
 {
 }
 
 nsMimeHeaders::~nsMimeHeaders()
 {
   if (mHeaders)
     MimeHeaders_free(mHeaders);
 }
 
 NS_IMPL_ISUPPORTS1(nsMimeHeaders, nsIMimeHeaders)
 
-nsresult nsMimeHeaders::Initialize(const char *aAllHeaders, int32_t allHeadersSize)
+nsresult nsMimeHeaders::Initialize(const nsACString &aAllHeaders)
 {
   /* just in case we want to reuse the object, cleanup...*/
   if (mHeaders)
     MimeHeaders_free(mHeaders);
 
   mHeaders = MimeHeaders_new();
   if (mHeaders)
     // XXX This function returns -1 in some paths, not nsresult
-    return static_cast<nsresult>(MimeHeaders_parse_line(aAllHeaders, allHeadersSize, mHeaders));
+    return static_cast<nsresult>(MimeHeaders_parse_line(
+      aAllHeaders.BeginReading(), aAllHeaders.Length(), mHeaders));
 
   return NS_ERROR_OUT_OF_MEMORY;
 }
 
-nsresult nsMimeHeaders::ExtractHeader(const char *headerName, bool getAllOfThem, char **_retval)
+nsresult nsMimeHeaders::ExtractHeader(const char *headerName, bool allOfThem,
+    nsACString &retval)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
   NS_ENSURE_TRUE(mHeaders, NS_ERROR_NOT_INITIALIZED);
 
-  *_retval = MimeHeaders_get(mHeaders, headerName, false, getAllOfThem);
+  // The external API doesn't have nsACString::Adopt, so we need to use a
+  // temporary string for adoption instead.
+  nsCString tempString;
+  tempString.Adopt(MimeHeaders_get(mHeaders, headerName, false, allOfThem));
+  retval = tempString;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsMimeHeaders::GetAllHeaders(char **_retval)
+NS_IMETHODIMP nsMimeHeaders::GetAllHeaders(nsACString &allHeaders)
 {
-  NS_ENSURE_ARG_POINTER(_retval);
   NS_ENSURE_TRUE(mHeaders, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_TRUE(mHeaders->all_headers, NS_ERROR_NULL_POINTER);
 
-  char *allHeaders = (char *) NS_Alloc(mHeaders->all_headers_fp + 1);
-  NS_ENSURE_TRUE(allHeaders, NS_ERROR_OUT_OF_MEMORY);
-
-  memcpy(allHeaders, mHeaders->all_headers, mHeaders->all_headers_fp);
-  *(allHeaders + mHeaders->all_headers_fp) = 0;
-  *_retval = allHeaders;
+  allHeaders.Assign(mHeaders->all_headers, mHeaders->all_headers_fp);
 
   return NS_OK;
 }
--- a/mailnews/mime/src/nsStreamConverter.cpp
+++ b/mailnews/mime/src/nsStreamConverter.cpp
@@ -1040,17 +1040,18 @@ nsStreamConverter::OnStopRequest(nsIRequ
       if (workHeaders)
       {
         nsresult rv;
         nsCOMPtr<nsIMimeHeaders> mimeHeaders = do_CreateInstance(NS_IMIMEHEADERS_CONTRACTID, &rv);
 
         if (NS_SUCCEEDED(rv))
         {
           if (*workHeaders)
-            mimeHeaders->Initialize((*workHeaders)->all_headers, (*workHeaders)->all_headers_fp);
+            mimeHeaders->Initialize(Substring((*workHeaders)->all_headers,
+              (*workHeaders)->all_headers_fp));
           mMimeStreamConverterListener->OnHeadersReady(mimeHeaders);
         }
         else
           mMimeStreamConverterListener->OnHeadersReady(nullptr);
       }
 
       mMimeStreamConverterListener = nullptr; // release our reference
     }
--- a/mailnews/mime/test/unit/test_mimeContentType.js
+++ b/mailnews/mime/test/unit/test_mimeContentType.js
@@ -62,16 +62,16 @@ function run_test()
       null,
     }
   ];
 
   let mimeHdr = Components.classes["@mozilla.org/messenger/mimeheaders;1"]
                   .createInstance(Components.interfaces.nsIMimeHeaders);
 
   for (let i = 0; i < headers.length; i++) {
-    mimeHdr.initialize(headers[i].header, headers[i].header.length);
+    mimeHdr.initialize(headers[i].header);
     let receivedHeader = mimeHdr.extractHeader("Content-Type", false);
 
     dump("\nTesting Content-Type: " + receivedHeader + " == " + headers[i].result + "\n");
 
     do_check_eq(receivedHeader, headers[i].result);
   }
 }