From 554b7d4aeb0c917f5d4e12b13d34909a6496d203 Mon Sep 17 00:00:00 2001 From: "bienvenu%nventure.com" Date: Wed, 1 Jun 2005 19:04:21 +0000 Subject: [PATCH] extend support for opening .eml files in a stand-alone msg window, sr=mscott, a=chofmann 241212 --- mail/base/content/msgHdrViewOverlay.js | 30 +++++++++ mailnews/base/src/nsMessenger.cpp | 61 ++++++++++++++++++- .../src/nsBayesianFilter.cpp | 5 ++ mailnews/local/src/nsMailboxProtocol.cpp | 38 ++++++------ mailnews/local/src/nsMailboxUrl.cpp | 36 +++++++++++ mailnews/mime/public/nsIMimeMiscStatus.idl | 3 +- mailnews/mime/src/mimei.cpp | 3 + mailnews/mime/src/nsStreamConverter.cpp | 6 ++ 8 files changed, 161 insertions(+), 21 deletions(-) diff --git a/mail/base/content/msgHdrViewOverlay.js b/mail/base/content/msgHdrViewOverlay.js index 759cfd319ef2..5613fb31af65 100644 --- a/mail/base/content/msgHdrViewOverlay.js +++ b/mail/base/content/msgHdrViewOverlay.js @@ -516,6 +516,15 @@ var messageHeaderSink = { setSecurityInfo: function(aSecurityInfo) { this.mSecurityInfo = aSecurityInfo; + }, + + mDummyMsgHeader: null, + + getDummyMsgHeader: function() + { + if (!this.mDummyMsgHeader) + this.mDummyMsgHeader = new nsDummyMsgHeader(); + return this.mDummyMsgHeader; } }; @@ -1608,3 +1617,24 @@ nsFlavorDataProvider.prototype = } } + +function nsDummyMsgHeader() +{ +} + +nsDummyMsgHeader.prototype = +{ + QueryInterface : function(iid) + { + if (iid.equals(Components.interfaces.nsIMsgDBHdr) || + iid.equals(Components.interfaces.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + + mMessageSize : 0, + + setMessageSize : function(aMessageSize) {mMessageSize = aMessageSize;}, + getMessageSize : function() {return mMessageSize;}, + folder : function() {return null;} +}; diff --git a/mailnews/base/src/nsMessenger.cpp b/mailnews/base/src/nsMessenger.cpp index 8b63e4bbe9ba..503e37e12254 100644 --- a/mailnews/base/src/nsMessenger.cpp +++ b/mailnews/base/src/nsMessenger.cpp @@ -71,6 +71,7 @@ #include "nsIStreamListener.h" #include "nsIStreamConverterService.h" #include "nsNetUtil.h" +#include "nsIFileURL.h" // rdf #include "nsIRDFCompositeDataSource.h" @@ -101,7 +102,7 @@ #include "nsMsgBaseCID.h" #include "nsIMsgAccountManager.h" #include "nsIMsgMailSession.h" - +#include "nsIMailboxUrl.h" #include "nsIMsgFolder.h" #include "nsMsgFolderFlags.h" #include "nsIMsgIncomingServer.h" @@ -112,7 +113,7 @@ #include "nsMsgRDFUtils.h" #include "nsIMsgHdr.h" - +#include "nsIMimeMiscStatus.h" // compose #include "nsMsgCompCID.h" #include "nsMsgI18N.h" @@ -614,6 +615,8 @@ nsMessenger::LoadURL(nsIDOMWindowInternal *aWin, const char *aURL) { NS_ENSURE_ARG_POINTER(aURL); + nsresult rv; + SetDisplayCharset("UTF-8"); NS_ConvertASCIItoUTF16 uriString(aURL); @@ -623,14 +626,54 @@ nsMessenger::LoadURL(nsIDOMWindowInternal *aWin, const char *aURL) uriString.StripChars("\r\n"); NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE); + PRBool loadingFromFile = PR_FALSE; + PRInt64 fileSize; + + if (StringBeginsWith(uriString, NS_LITERAL_STRING("file:"))) + { + + nsCOMPtr fileUri; + rv = NS_NewURI(getter_AddRefs(fileUri), uriString); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr fileUrl = do_QueryInterface(fileUri, &rv); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr file; + rv = fileUrl->GetFile(getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); + file->GetFileSize(&fileSize); + uriString.ReplaceSubstring(NS_LITERAL_STRING("file:"), NS_LITERAL_STRING("mailbox:")); + uriString.Append(NS_LITERAL_STRING("&number=0")); + loadingFromFile = PR_TRUE; + } + nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), uriString); + rv = NS_NewURI(getter_AddRefs(uri), uriString); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); nsCOMPtr msgurl = do_QueryInterface(uri); if (msgurl) + { msgurl->SetMsgWindow(mMsgWindow); + if (loadingFromFile) + { + nsCOMPtr mailboxUrl = do_QueryInterface(msgurl, &rv); + mailboxUrl->SetMessageSize((PRUint32) fileSize); + nsCOMPtr headerSink; + // need to tell the header sink to capture some headers to create a fake db header + // so we can do reply to a .eml file or a rfc822 msg attachment. + mMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink)); + if (headerSink) + { + nsCOMPtr dummyHeader; + headerSink->GetDummyMsgHeader(getter_AddRefs(dummyHeader)); + if (dummyHeader) + { + dummyHeader->SetMessageSize((PRUint32) fileSize); + } + } + } + } nsCOMPtr loadInfo; rv = mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo)); @@ -687,6 +730,18 @@ nsMessenger::SaveAttachment(nsIFileSpec * fileSpec, } urlString = url; + // strip out ?type=x-message-display because it confuses libmime + + PRInt32 typeIndex = urlString.Find("?type=x-message-display"); + if (typeIndex != kNotFound) + { + urlString.Cut(typeIndex, sizeof("?type=x-message-display") - 1); + // we also need to replace the next '&' with '?' + PRInt32 firstPartIndex = urlString.FindChar('&'); + if (firstPartIndex != kNotFound) + urlString.SetCharAt('?', firstPartIndex); + } + urlString.ReplaceSubstring("/;section", "?section"); nsresult rv = CreateStartupUrl(urlString.get(), getter_AddRefs(URL)); diff --git a/mailnews/extensions/bayesian-spam-filter/src/nsBayesianFilter.cpp b/mailnews/extensions/bayesian-spam-filter/src/nsBayesianFilter.cpp index 001bbbb6b8d3..411b06f13929 100644 --- a/mailnews/extensions/bayesian-spam-filter/src/nsBayesianFilter.cpp +++ b/mailnews/extensions/bayesian-spam-filter/src/nsBayesianFilter.cpp @@ -782,6 +782,11 @@ NS_IMETHODIMP TokenStreamListener::SetSecurityInfo(nsISupports * aSecurityInfo) return NS_OK; } +NS_IMETHODIMP TokenStreamListener::GetDummyMsgHeader(nsIMsgDBHdr **aMsgDBHdr) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + /* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */ NS_IMETHODIMP TokenStreamListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) { diff --git a/mailnews/local/src/nsMailboxProtocol.cpp b/mailnews/local/src/nsMailboxProtocol.cpp index 18cf06b9a2bb..caddf19cdf60 100644 --- a/mailnews/local/src/nsMailboxProtocol.cpp +++ b/mailnews/local/src/nsMailboxProtocol.cpp @@ -412,27 +412,31 @@ PRInt32 nsMailboxProtocol::DoneReadingMessage() PRInt32 nsMailboxProtocol::SetupMessageExtraction() { - // Determine the number of bytes we are going to need to read out of the - // mailbox url.... - nsCOMPtr msgHdr; - nsresult rv = NS_OK; - + // Determine the number of bytes we are going to need to read out of the + // mailbox url.... + nsCOMPtr msgHdr; + nsresult rv = NS_OK; + NS_ASSERTION(m_runningUrl, "Not running a url"); if (m_runningUrl) { - nsCOMPtr msgUrl = do_QueryInterface(m_runningUrl, &rv); - NS_ENSURE_SUCCESS(rv,rv); - rv = msgUrl->GetMessageHeader(getter_AddRefs(msgHdr)); - if (NS_SUCCEEDED(rv) && msgHdr) - { - PRUint32 messageSize = 0; - msgHdr->GetMessageSize(&messageSize); - m_runningUrl->SetMessageSize(messageSize); - } - else - NS_ASSERTION(PR_FALSE, "couldn't get message header"); + PRUint32 messageSize = 0; + m_runningUrl->GetMessageSize(&messageSize); + if (!messageSize) + { + nsCOMPtr msgUrl = do_QueryInterface(m_runningUrl, &rv); + NS_ENSURE_SUCCESS(rv,rv); + rv = msgUrl->GetMessageHeader(getter_AddRefs(msgHdr)); + if (NS_SUCCEEDED(rv) && msgHdr) + { + msgHdr->GetMessageSize(&messageSize); + m_runningUrl->SetMessageSize(messageSize); + } + else + NS_ASSERTION(PR_FALSE, "couldn't get message header"); + } } - return rv; + return rv; } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/mailnews/local/src/nsMailboxUrl.cpp b/mailnews/local/src/nsMailboxUrl.cpp index 99441e6ef92f..9a2e223e9b2b 100644 --- a/mailnews/local/src/nsMailboxUrl.cpp +++ b/mailnews/local/src/nsMailboxUrl.cpp @@ -58,6 +58,7 @@ #include "nsIMsgFolder.h" #include "prprf.h" #include "nsISupportsObsolete.h" +#include "nsIMsgMailSession.h" // we need this because of an egcs 1.0 (and possibly gcc) compiler bug // that doesn't allow you to call ::nsISupports::GetIID() inside of a class @@ -289,6 +290,23 @@ nsresult nsMailboxUrl::GetMsgHdrForKey(nsMsgKey msgKey, nsIMsgDBHdr ** aMsgHdr) rv = msgDBService->OpenMailDBFromFileSpec(dbFileSpec, PR_FALSE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(mailDB)); if (NS_SUCCEEDED(rv) && mailDB) // did we get a db back? rv = mailDB->GetMsgHdrForKey(msgKey, aMsgHdr); + else + { + if (!m_msgWindow) + { + nsCOMPtr mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mailSession->GetTopmostMsgWindow(getter_AddRefs(m_msgWindow)); + } + // maybe this is .eml file we're trying to read. See if we can get a header from the header sink. + if (m_msgWindow) + { + nsCOMPtr headerSink; + m_msgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink)); + if (headerSink) + return headerSink->GetDummyMsgHeader(aMsgHdr); + } + } } else rv = NS_ERROR_NULL_POINTER; @@ -486,6 +504,24 @@ NS_IMETHODIMP nsMailboxUrl::GetFolderCharset(char ** aCharacterSet) { nsCOMPtr folder; nsresult rv = GetFolder(getter_AddRefs(folder)); +#if 0 + if (NS_FAILED(rv)) + { + nsCOMPtr pls; + nsCOMPtr prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + rv = prefBranch->GetComplexValue("mailnews.view_default_charset", + NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(pls)); + if (NS_SUCCEEDED(rv)) + { + nsXPIDLString ucsval; + pls->ToString(getter_Copies(ucsval)); + if (ucsval) + *aCharacterSet = ToNewCString(ucsval); + return rv; + } + } +#endif NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_TRUE(folder, NS_ERROR_FAILURE); folder->GetCharset(aCharacterSet); diff --git a/mailnews/mime/public/nsIMimeMiscStatus.idl b/mailnews/mime/public/nsIMimeMiscStatus.idl index d280eeb162ee..623eeed58f2e 100644 --- a/mailnews/mime/public/nsIMimeMiscStatus.idl +++ b/mailnews/mime/public/nsIMimeMiscStatus.idl @@ -60,7 +60,7 @@ interface nsIMimeMiscStatus : nsISupports{ // this is a simple interface which allows someone to listen to all the headers // that are discovered by mime. We can use this when displaying a message to update // the msg header in JS. -[scriptable, uuid(34362984-C7A0-47b2-8BA3-6B67C4AD986F)] +[scriptable, uuid(0d6ebe53-de30-4797-9a8e-5f9be68d472c)] interface nsIMsgHeaderSink : nsISupports { // You must finish consuming the iterators before returning from processHeaders. aHeaderNames and aHeaderValues will ALWAYS have the same @@ -82,4 +82,5 @@ interface nsIMsgHeaderSink : nsISupports attribute nsISupports securityInfo; void onMsgHasRemoteContent(in nsIMsgDBHdr aMsgHdr); + nsIMsgDBHdr getDummyMsgHeader(); }; diff --git a/mailnews/mime/src/mimei.cpp b/mailnews/mime/src/mimei.cpp index 1feace43c1b8..96df6194b8f6 100644 --- a/mailnews/mime/src/mimei.cpp +++ b/mailnews/mime/src/mimei.cpp @@ -424,6 +424,9 @@ void getMsgHdrForCurrentURL(MimeDisplayOptions *opts, nsIMsgDBHdr ** aMsgHdr) msgURI = do_QueryInterface(uri); if (msgURI) { + msgURI->GetMessageHeader(aMsgHdr); + if (*aMsgHdr) + return; nsXPIDLCString rdfURI; msgURI->GetUri(getter_Copies(rdfURI)); if (rdfURI.get()) diff --git a/mailnews/mime/src/nsStreamConverter.cpp b/mailnews/mime/src/nsStreamConverter.cpp index 37777fcb6eac..b74f62cd5bb7 100644 --- a/mailnews/mime/src/nsStreamConverter.cpp +++ b/mailnews/mime/src/nsStreamConverter.cpp @@ -418,6 +418,12 @@ nsStreamConverter::DetermineOutputFormat(const char *aUrl, nsMimeOutputType *aNe // content type appended to it...if it does, we want to remember // that as mOutputFormat const char * typeField = FindQueryElementData(queryPart, "type="); + if (typeField && !strncmp(typeField, "x-message-display", sizeof("x-message-display") - 1)) + { + const char *secondTypeField = FindQueryElementData(typeField, "type="); + if (secondTypeField) + typeField = secondTypeField; + } if (typeField) { // store the real content type...mOutputFormat gets deleted later on...