fix reply/ forward inline/edit as new for .eml files with inline images, r=neil, sr=standard8, bug 351109
authorDavid Bienvenu <bienvenu@nventure.com>
Thu, 10 Nov 2011 16:22:57 -0800
changeset 9845 8867ea4e1147f3ff5c507ab05a5c65823843f72e
parent 9844 8cb20fb12d717cf6b3816fe89a09214dc8151b0d
child 9846 ae509ec7b1233f136f6b3625782ee132ab7aa798
push id336
push userbugzilla@standard8.plus.com
push dateTue, 31 Jan 2012 22:15:45 +0000
treeherdercomm-beta@54945f5d278d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersneil, standard8, bug
bugs351109
fix reply/ forward inline/edit as new for .eml files with inline images, r=neil, sr=standard8, bug 351109
mailnews/base/public/nsIMsgMailNewsUrl.idl
mailnews/compose/public/nsIMsgQuote.idl
mailnews/compose/src/nsMsgCompose.cpp
mailnews/compose/src/nsMsgCompose.h
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/src/nsMsgQuote.cpp
mailnews/imap/src/nsImapUrl.cpp
mailnews/local/src/nsMailboxUrl.cpp
mailnews/local/src/nsMailboxUrl.h
mailnews/news/src/nsNntpUrl.cpp
--- a/mailnews/base/public/nsIMsgMailNewsUrl.idl
+++ b/mailnews/base/public/nsIMsgMailNewsUrl.idl
@@ -134,17 +134,17 @@ interface nsIMsgMailNewsUrl : nsIURL {
 // Several url types (mailbox, imap, nntp) have similar properties because they can
 // represent mail messages. For instance, these urls can be have URI 
 // equivalents which represent a message. 
 // We want to provide the app the ability to get the URI for the 
 // url. This URI to URL mapping doesn't exist for all mailnews urls...hence I'm
 // grouping it into a separate interface...
 //////////////////////////////////////////////////////////////////////////////////
 
-[scriptable, uuid(1a7340d8-be3c-4fb6-919d-152fb3074da7)]
+[scriptable, uuid(388a37ec-2e1a-4a4f-9d8b-189bedf1bda2)]
 interface nsIMsgMessageUrl : nsISupports {
   // get and set the RDF URI associated with the url. Note, not all urls have
   // had uri's set on them so be prepared to handle cases where this string is empty.
   attribute string uri;
   // used by imap, pop and nntp in order to implement save message to disk
   attribute nsIFile messageFile;
   attribute boolean AddDummyEnvelope;  
   attribute boolean canonicalLineEnding;
@@ -153,17 +153,17 @@ interface nsIMsgMessageUrl : nsISupports
   /**
    *  A message db header for that message.
    *  
    *  @note This attribute is not guaranteed to be set, so callers that
    *  actually require an nsIMsgDBHdr will need to use the uri attribute
    *  on this interface to get the  appropriate nsIMsgMessageService and
    *  then get the header from there.
    */
-  readonly attribute nsIMsgDBHdr messageHeader;
+  attribute nsIMsgDBHdr messageHeader;
 };
 
 //////////////////////////////////////////////////////////////////////////////////
 // This is a very small interface which I'm grouping with the mailnewsUrl interface.
 // I want to isolate out all the I18N specific information that may be associated with
 // any given mailnews url. This gives I18N their own "sandbox" of routines they can add
 // and tweak as they see fit. For now it contains mostly charset information.
 //////////////////////////////////////////////////////////////////////////////////
--- a/mailnews/compose/public/nsIMsgQuote.idl
+++ b/mailnews/compose/public/nsIMsgQuote.idl
@@ -34,28 +34,31 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsISupports.idl"
 #include "nsIMsgQuotingOutputStreamListener.idl"
 #include "nsIChannel.idl"
 #include "nsIMimeStreamConverter.idl"
 
-[scriptable, uuid(5e601eed-95e8-4598-8917-26fe983e2803)]
+interface nsIMsgDBHdr;
+
+[scriptable, uuid(f79b1d55-f546-4ed5-9f75-9428e35c4eff)]
 interface nsIMsgQuote : nsISupports {
 
  /**
   * Quote a particular message specified by its URI.
   *
   * @param charset optional parameter - if set, force the message to be
   *                quoted using this particular charset
   */
   void quoteMessage(in string msgURI, in boolean quoteHeaders,
                     in nsIMsgQuotingOutputStreamListener streamListener,
-                    in string charset, in boolean headersOnly);
+                    in string charset, in boolean headersOnly,
+                    in nsIMsgDBHdr aOrigHdr);
 
   readonly attribute nsIMimeStreamConverterListener quoteListener;
   readonly attribute nsIChannel quoteChannel;
   readonly attribute nsIMsgQuotingOutputStreamListener streamListener;
 };
 
 [scriptable, uuid(1EC75AD9-88DE-11d3-989D-001083010E9B)]
 interface nsIMsgQuoteListener : nsIMimeStreamConverterListener
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -3140,56 +3140,65 @@ nsMsgCompose::QuoteMessage(const char *m
 
   if (!mQuoteStreamListener)
     return NS_ERROR_FAILURE;
   NS_ADDREF(mQuoteStreamListener);
 
   mQuoteStreamListener->SetComposeObj(this);
 
   rv = mQuote->QuoteMessage(msgURI, PR_FALSE, mQuoteStreamListener,
-                            mCharsetOverride ? m_compFields->GetCharacterSet() : "", PR_FALSE);
+                            mCharsetOverride ? m_compFields->GetCharacterSet() : "",
+                            PR_FALSE, msgHdr);
   return rv;
 }
 
 nsresult
-nsMsgCompose::QuoteOriginalMessage(const char *originalMsgURI, PRInt32 what) // New template
+nsMsgCompose::QuoteOriginalMessage() // New template
 {
   nsresult    rv;
 
   mQuotingToFollow = PR_FALSE;
 
   // Create a mime parser (nsIStreamConverter)!
   mQuote = do_CreateInstance(NS_MSGQUOTE_CONTRACTID, &rv);
   if (NS_FAILED(rv) || !mQuote)
     return NS_ERROR_FAILURE;
 
   bool bAutoQuote = true;
   m_identity->GetAutoQuote(&bAutoQuote);
 
   nsCOMPtr <nsIMsgDBHdr> originalMsgHdr = mOrigMsgHdr;
   if (!originalMsgHdr)
   {
-    rv = GetMsgDBHdrFromURI(originalMsgURI, getter_AddRefs(originalMsgHdr));
+    rv = GetMsgDBHdrFromURI(mOriginalMsgURI.get(), getter_AddRefs(originalMsgHdr));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  bool fileUrl = StringBeginsWith(mOriginalMsgURI, NS_LITERAL_CSTRING("file:"));
+  if (fileUrl)
+  {
+    mOriginalMsgURI.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
+    mOriginalMsgURI.AppendLiteral("?number=0");
+  }
+
   // Create the consumer output stream.. this will receive all the HTML from libmime
   mQuoteStreamListener =
-    new QuotingOutputStreamListener(originalMsgURI, originalMsgHdr, what != 1,
+    new QuotingOutputStreamListener(mOriginalMsgURI.get(), originalMsgHdr, mWhatHolder != 1,
                                     !bAutoQuote || !mHtmlToQuote.IsEmpty(), m_identity,
                                     mQuoteCharset.get(), mCharsetOverride, PR_TRUE, mHtmlToQuote);
 
   if (!mQuoteStreamListener)
     return NS_ERROR_FAILURE;
   NS_ADDREF(mQuoteStreamListener);
 
   mQuoteStreamListener->SetComposeObj(this);
 
-  rv = mQuote->QuoteMessage(originalMsgURI, what != 1, mQuoteStreamListener,
-                            mCharsetOverride ? mQuoteCharset.get() : "", !bAutoQuote);
+  rv = mQuote->QuoteMessage(mOriginalMsgURI.get(), mWhatHolder != 1, mQuoteStreamListener,
+                            mCharsetOverride ? mQuoteCharset.get() : "",
+                            !bAutoQuote, originalMsgHdr);
   return rv;
 }
 
 //CleanUpRecipient will remove un-necessary "<>" when a recipient as an address without name
 void nsMsgCompose::CleanUpRecipients(nsString& recipients)
 {
   PRUint16 i;
   bool startANewRecipient = true;
@@ -4083,17 +4092,17 @@ nsMsgCompose::BuildQuotedMessageAndSigna
   // This should never happen...if it does, just bail out...
   //
   NS_ASSERTION(m_editor, "BuildQuotedMessageAndSignature but no editor!\n");
   if (!m_editor)
     return NS_ERROR_FAILURE;
 
   // We will fire off the quote operation and wait for it to
   // finish before we actually do anything with Ender...
-  return QuoteOriginalMessage(mOriginalMsgURI.get(), mWhatHolder);
+  return QuoteOriginalMessage();
 }
 
 //
 // This will process the signature file for the user. This method
 // will always append the results to the mMsgBody member variable.
 //
 nsresult
 nsMsgCompose::ProcessSignature(nsIMsgIdentity *identity, bool aQuoted, nsString *aMsgBody)
--- a/mailnews/compose/src/nsMsgCompose.h
+++ b/mailnews/compose/src/nsMsgCompose.h
@@ -74,17 +74,17 @@ class nsMsgCompose : public nsIMsgCompos
 	NS_DECL_NSIMSGCOMPOSE
 
   /* nsIMsgSendListener interface */
   NS_DECL_NSIMSGSENDLISTENER
 
 private:
 
  // Deal with quoting issues...
-	nsresult                      QuoteOriginalMessage(const char * originalMsgURI, PRInt32 what); // New template
+	nsresult                      QuoteOriginalMessage(); // New template
   nsresult                      SetQuotingToFollow(bool aVal);
   nsresult                      ConvertHTMLToText(nsILocalFile *aSigFile, nsString &aSigData);
   nsresult                      ConvertTextToHTML(nsILocalFile *aSigFile, nsString &aSigData);
   bool                          IsEmbeddedObjectSafe(const char * originalScheme,
                                                      const char * originalHost,
                                                      const char * originalPath,
                                                      nsIDOMNode * object);
   nsresult                      ResetUrisForEmbeddedObjects();
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -1596,25 +1596,35 @@ nsMsgComposeService::RunMessageThroughMi
   }
   mimeConverter->SetOverrideComposeFormat(aOverrideComposeFormat);
   mimeConverter->SetIdentity(aIdentity);
   mimeConverter->SetOriginalMsgURI(aOriginalMsgURI);
   mimeConverter->SetOrigMsgHdr(aOrigMsgHdr);
 
   nsCOMPtr<nsIURI> url;
   bool fileUrl = StringBeginsWith(aMsgURI, NS_LITERAL_CSTRING("file:"));
+  nsCString mailboxUri(aMsgURI);
+  if (fileUrl)
+  {
+    // We loaded a .eml file from a file: url. Construct equivalent mailbox url.
+    mailboxUri.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
+    mailboxUri.Append(NS_LITERAL_CSTRING("&number=0"));
+    // Need this to prevent nsMsgCompose::TagEmbeddedObjects from setting
+    // inline images as moz-do-not-send.
+    mimeConverter->SetOriginalMsgURI(mailboxUri.get());
+  }
   if (fileUrl || PromiseFlatCString(aMsgURI).Find("&type=application/x-message-display") >= 0)
-    rv = NS_NewURI(getter_AddRefs(url), aMsgURI);
+    rv = NS_NewURI(getter_AddRefs(url), mailboxUri);
   else
     rv = messageService->GetUrlForUri(PromiseFlatCString(aMsgURI).get(), getter_AddRefs(url), aMsgWindow);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // ignore errors here - it's not fatal, and in the case of mailbox messages,
   // we're always passing in an invalid spec...
-  (void )url->SetSpec(aMsgURI);
+  (void )url->SetSpec(mailboxUri);
 
   // if we are forwarding a message and that message used a charset over ride
   // then use that over ride charset instead of the charset specified in the message
   nsCString mailCharset;
   if (aMsgWindow)
   {
     bool charsetOverride;
     if (NS_SUCCEEDED(aMsgWindow->GetCharsetOverride(&charsetOverride)) && charsetOverride)
--- a/mailnews/compose/src/nsMsgQuote.cpp
+++ b/mailnews/compose/src/nsMsgQuote.cpp
@@ -142,30 +142,40 @@ NS_IMETHODIMP nsMsgQuote::GetStreamListe
     rv = NS_ERROR_NULL_POINTER;
 
   return rv;
 }
 
 nsresult
 nsMsgQuote::QuoteMessage(const char *msgURI, bool quoteHeaders,
                          nsIMsgQuotingOutputStreamListener * aQuoteMsgStreamListener,
-                         const char * aMsgCharSet, bool headersOnly)
+                         const char * aMsgCharSet, bool headersOnly,
+                         nsIMsgDBHdr *aMsgHdr)
 {
   nsresult  rv;
   if (!msgURI)
     return NS_ERROR_INVALID_ARG;
 
   mQuoteHeaders = quoteHeaders;
   mStreamListener = aQuoteMsgStreamListener;
 
   nsCAutoString msgUri(msgURI);
   bool fileUrl = !strncmp(msgURI, "file:", 5);
   bool forwardedMessage = PL_strstr(msgURI, "&realtype=message/rfc822") != nsnull;
   nsCOMPtr<nsIURI> aURL;
-  if (fileUrl || forwardedMessage)
+  if (fileUrl)
+  {
+    msgUri.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
+    msgUri.AppendLiteral("?number=0");
+    rv = NS_NewURI(getter_AddRefs(aURL), msgUri);
+    nsCOMPtr<nsIMsgMessageUrl> mailUrl(do_QueryInterface(aURL));
+    if (mailUrl)
+      mailUrl->SetMessageHeader(aMsgHdr);
+  }
+  else if (forwardedMessage)
     rv = NS_NewURI(getter_AddRefs(aURL), msgURI);
   else
   {
     nsCOMPtr <nsIMsgMessageService> msgService;
     rv = GetMessageServiceFromURI(nsDependentCString(msgURI), getter_AddRefs(msgService));
     if (NS_FAILED(rv)) return rv;
     rv = msgService->GetUrlForUri(msgURI, getter_AddRefs(aURL), nsnull);
   }
--- a/mailnews/imap/src/nsImapUrl.cpp
+++ b/mailnews/imap/src/nsImapUrl.cpp
@@ -1553,8 +1553,12 @@ NS_IMETHODIMP nsImapUrl::SetStoreOffline
 NS_IMETHODIMP nsImapUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
 {
   nsCString uri;
   nsresult rv = GetUri(getter_Copies(uri));
   NS_ENSURE_SUCCESS(rv, rv);
   return GetMsgDBHdrFromURI(uri.get(), aMsgHdr);
 }
 
+NS_IMETHODIMP nsImapUrl::SetMessageHeader(nsIMsgDBHdr *aMsgHdr)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
--- a/mailnews/local/src/nsMailboxUrl.cpp
+++ b/mailnews/local/src/nsMailboxUrl.cpp
@@ -256,19 +256,30 @@ nsresult nsMailboxUrl::GetMsgHdrForKey(n
   else
     rv = NS_ERROR_NULL_POINTER;
 
   return rv;
 }
 
 NS_IMETHODIMP nsMailboxUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
 {
+  if (m_dummyHdr)
+  {
+    NS_IF_ADDREF(*aMsgHdr = m_dummyHdr);
+    return NS_OK;
+  }
   return GetMsgHdrForKey(m_messageKey, aMsgHdr);
 }
 
+NS_IMETHODIMP nsMailboxUrl::SetMessageHeader(nsIMsgDBHdr *aMsgHdr)
+{
+  m_dummyHdr = aMsgHdr;
+  return NS_OK;
+}
+
 NS_IMPL_GETSET(nsMailboxUrl, AddDummyEnvelope, bool, m_addDummyEnvelope)
 NS_IMPL_GETSET(nsMailboxUrl, CanonicalLineEnding, bool, m_canonicalLineEnding)
 
 NS_IMETHODIMP
 nsMailboxUrl::GetOriginalSpec(char **aSpec)
 {
   if (!aSpec || m_originalSpec.IsEmpty())
     return NS_ERROR_NULL_POINTER;
--- a/mailnews/local/src/nsMailboxUrl.h
+++ b/mailnews/local/src/nsMailboxUrl.h
@@ -91,16 +91,19 @@ protected:
   nsCOMPtr<nsIStreamListener> m_mailboxCopyHandler;
 
   nsMailboxAction m_mailboxAction; // the action this url represents...parse mailbox, display messages, etc.
   nsCOMPtr <nsILocalFile>  m_filePath;
   char *m_messageID;
   PRUint32 m_messageSize;
   nsMsgKey m_messageKey;
   nsCString m_file;
+  // This is currently only set when we're doing something with a .eml file.
+  // If that changes, we should change the name of this var.
+  nsCOMPtr<nsIMsgDBHdr> m_dummyHdr;
 
   // used by save message to disk
   nsCOMPtr<nsIFile> m_messageFile;
   bool                  m_addDummyEnvelope;
   bool                  m_canonicalLineEnding;
   nsresult ParseSearchPart();
 
   // for multiple msg move/copy
--- a/mailnews/news/src/nsNntpUrl.cpp
+++ b/mailnews/news/src/nsNntpUrl.cpp
@@ -391,16 +391,21 @@ nsresult nsNntpUrl::SetMessageToPost(nsI
 
 nsresult nsNntpUrl::GetMessageToPost(nsINNTPNewsgroupPost **aPost)
 {
   NS_ENSURE_ARG_POINTER(aPost);
   NS_IF_ADDREF(*aPost = m_newsgroupPost);
   return NS_OK;
 }
 
+NS_IMETHODIMP nsNntpUrl::SetMessageHeader(nsIMsgDBHdr *aMsgHdr)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 NS_IMETHODIMP nsNntpUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
 {
   nsresult rv;
 
   nsCOMPtr <nsINntpService> nntpService = do_GetService(NS_NNTPSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsCOMPtr <nsIMsgMessageService> msgService = do_QueryInterface(nntpService, &rv);