From ffc4d709f6cdd7a51b3d3fdf22ed5ce0fec59d5f Mon Sep 17 00:00:00 2001 From: "jefft%netscape.com" Date: Thu, 13 Apr 2000 22:19:48 +0000 Subject: [PATCH] fixed bug 21742 -- [FEATURE] Save all attachments; r=mscott --- mailnews/base/public/nsIMessenger.idl | 1 + .../resources/content/msgHdrViewOverlay.js | 66 +++- .../resources/content/msgHdrViewOverlay.xul | 2 - mailnews/base/src/nsMessenger.cpp | 362 +++++++++++++----- mailnews/base/src/nsMessenger.h | 2 + mailnews/imap/src/nsImapProtocol.cpp | 8 +- mailnews/imap/src/nsImapProtocol.h | 2 + .../mime/emitters/src/nsMimeBaseEmitter.cpp | 6 + .../mime/emitters/src/nsMimeHtmlEmitter.cpp | 11 + .../mime/emitters/src/nsMimeHtmlEmitter.h | 1 + mailnews/mime/public/nsIMimeEmitter.idl | 2 + mailnews/mime/public/nsIMimeMiscStatus.idl | 4 +- mailnews/mime/src/mimemoz2.cpp | 24 ++ mailnews/mime/src/mimemoz2.h | 1 + 14 files changed, 389 insertions(+), 103 deletions(-) diff --git a/mailnews/base/public/nsIMessenger.idl b/mailnews/base/public/nsIMessenger.idl index 1b31f7ca8c5c..2dc231e4f363 100644 --- a/mailnews/base/public/nsIMessenger.idl +++ b/mailnews/base/public/nsIMessenger.idl @@ -98,6 +98,7 @@ interface nsIMessenger : nsISupports { void SetDocumentCharset(in wstring characterSet); void saveAs(in string url, in boolean asFile, in nsIMsgIdentity identity, in nsIMsgWindow aMsgWindow); void openAttachment(in string url, in string displayName, in string messageUri); + void saveAllAttachments(in unsigned long count, [array, size_is(count)] in string urlArray, [array, size_is(count)] in string displayNameArray, [array, size_is(count)] in string messageUriArray); void find(); void findAgain(); }; diff --git a/mailnews/base/resources/content/msgHdrViewOverlay.js b/mailnews/base/resources/content/msgHdrViewOverlay.js index e151972a1d6e..51baa4aacceb 100644 --- a/mailnews/base/resources/content/msgHdrViewOverlay.js +++ b/mailnews/base/resources/content/msgHdrViewOverlay.js @@ -40,6 +40,11 @@ var currentHeaderData; var gNumAddressesToShow = 3; var gShowUserAgent = false; +// attachments array +var attachmentUrlArray = new Array(); +var attachmentDisplayNameArray = new Array(); +var attachmentMessageUriArray = new Array(); + var msgHeaderParser = Components.classes[msgHeaderParserProgID].getService(Components.interfaces.nsIMsgHeaderParser); var abAddressCollector = Components.classes[abAddressCollectorProgID].getService(Components.interfaces.nsIAbAddressCollecter); @@ -185,6 +190,18 @@ var messageHeaderSink = { } AddAttachmentToMenu(displayName, commandString); + + var count = attachmentUrlArray.length; + // dump ("** attachment count**" + count + "\n"); + if (count < 0) count = 0; + attachmentUrlArray[count] = url; + attachmentDisplayNameArray[count] = escape(displayName); + attachmentMessageUriArray[count] = uri; + }, + + onEndAllAttachments: function() + { + AddSaveAllAttachmentsMenu(); } }; @@ -226,25 +243,21 @@ function OpenAttachURL(url, displayName, messageUri) function AddAttachmentToMenu(name, oncommand) { var popup = document.getElementById("attachmentPopup"); - if ( popup && (popup.childNodes.length >= 2) ) + if (popup) { var item = document.createElement('menuitem'); if ( item ) { // popup.removeAttribute('menugenerated'); - var child = popup.childNodes[popup.childNodes.length - 2]; - - var bigMenu = document.getElementById('attachmentMenu'); - - popup.insertBefore(item, child); + popup.appendChild(item); item.setAttribute('value', name); item.setAttribute('oncommand', oncommand); } var button = document.getElementById("attachmentButton"); if (button) - button.setAttribute("value", popup.childNodes.length - 2); + button.setAttribute("value", popup.childNodes.length); } var attachBox = document.getElementById("attachmentBox"); @@ -252,19 +265,56 @@ function AddAttachmentToMenu(name, oncommand) attachBox.removeAttribute("hide"); } +function SaveAllAttachments() +{ + try + { + messenger.saveAllAttachments(attachmentUrlArray.length, + attachmentUrlArray, + attachmentDisplayNameArray, + attachmentMessageUriArray); + } + catch (ex) + { + dump ("** failed to save all attachments ** \n"); + } +} + +function AddSaveAllAttachmentsMenu() +{ + var popup = document.getElementById("attachmentPopup"); + if (popup && popup.childNodes.length > 1) + { + var separator = document.createElement('menuseparator'); + var item = document.createElement('menuitem'); + if (separator && item) + { + popup.appendChild(separator); + popup.appendChild(item); + item.setAttribute('value', "Save All..."); + item.setAttribute('oncommand', "SaveAllAttachments()"); + } + } +} + function ClearAttachmentMenu() { var popup = document.getElementById("attachmentPopup"); if ( popup ) { - while ( popup.childNodes.length > 2 ) + while ( popup.childNodes.length ) popup.removeChild(popup.childNodes[0]); } var attachBox = document.getElementById("attachmentBox"); if (attachBox) attachBox.setAttribute("hide", "true"); + + // reset attachments name array + attachmentUrlArray.length = 0; + attachmentDisplayNameArray.length = 0; + attachmentMessageUriArray.length = 0; } // Assumes that all the child nodes of the parent div need removed..leaving diff --git a/mailnews/base/resources/content/msgHdrViewOverlay.xul b/mailnews/base/resources/content/msgHdrViewOverlay.xul index d7fe1bb4b355..f3138ad51b5b 100644 --- a/mailnews/base/resources/content/msgHdrViewOverlay.xul +++ b/mailnews/base/resources/content/msgHdrViewOverlay.xul @@ -71,8 +71,6 @@ Rights Reserved. - - diff --git a/mailnews/base/src/nsMessenger.cpp b/mailnews/base/src/nsMessenger.cpp index 8e2f89b061ec..54b01b4c1955 100644 --- a/mailnews/base/src/nsMessenger.cpp +++ b/mailnews/base/src/nsMessenger.cpp @@ -195,6 +195,8 @@ ConvertBufToPlainText(nsString &aConBuf) // jefft - this is a rather obscured class serves for Save Message As File, // Save Message As Template, and Save Attachment to a file // +class nsSaveAllAttachmentsState; + class nsSaveAsListener : public nsIUrlListener, public nsIMsgCopyServiceListener, public nsIStreamListener @@ -216,6 +218,7 @@ public: nsCOMPtr m_channel; nsXPIDLCString m_templateUri; nsMessenger *m_messenger; // not ref counted + nsSaveAllAttachmentsState *m_saveAllAttachmentsState; // rhp: For character set handling PRBool m_doCharsetConversion; @@ -224,6 +227,23 @@ public: nsString m_msgBuffer; }; +class nsSaveAllAttachmentsState +{ +public: + nsSaveAllAttachmentsState(PRUint32 count, const char **urlArray, + const char **displayNameArray, + const char **messageUriArray, + const char *directoryName); + virtual ~nsSaveAllAttachmentsState(); + + PRUint32 m_count; + PRUint32 m_curIndex; + char* m_directoryName; + char** m_urlArray; + char** m_displayNameArray; + char** m_messageUriArray; +}; + // // nsMessenger // @@ -453,6 +473,106 @@ nsMessenger::OpenURL(const char * url) return NS_OK; } +nsresult +nsMessenger::SaveAttachment(nsIFileSpec * fileSpec, + const char * unescapedUrl, + const char * messageUri, + void *closure) +{ + nsIMsgMessageService * messageService = nsnull; + nsSaveAsListener *aListener = nsnull; + nsSaveAllAttachmentsState *saveState= (nsSaveAllAttachmentsState*) closure; + nsAutoString from, to; + nsCOMPtr channelSupport; + nsCOMPtr convertedListener; + nsAutoString urlString; + char *urlCString = nsnull; + nsCOMPtr aURL; + PRBool canFetchMimeParts = PR_FALSE; + nsCAutoString fullMessageUri = messageUri; + nsresult rv = NS_OK; + + fileSpec->MakeUnique(); + NS_WITH_SERVICE(nsIStreamConverterService, + streamConverterService, + kIStreamConverterServiceCID, &rv); + if (NS_FAILED(rv)) goto done; + + aListener = new nsSaveAsListener(fileSpec, this); + if (!aListener) + { + rv = NS_ERROR_OUT_OF_MEMORY; + goto done; + } + NS_ADDREF(aListener); + + if (saveState) + aListener->m_saveAllAttachmentsState = saveState; + + urlString = unescapedUrl; + + urlString.ReplaceSubstring("/;section", "?section"); + urlCString = urlString.ToNewCString(); + + rv = CreateStartupUrl(urlCString, getter_AddRefs(aURL)); + nsCRT::free(urlCString); + + if (NS_FAILED(rv)) goto done; + + rv = GetMessageServiceFromURI(messageUri, &messageService); + if (NS_FAILED(rv)) goto done; + + messageService->GetCanFetchMimeParts(&canFetchMimeParts); + + if (canFetchMimeParts) + { + PRInt32 sectionPos = urlString.Find("?section"); + nsString mimePart; + + urlString.Right(mimePart, urlString.Length() - sectionPos); + fullMessageUri.Append(mimePart); + + messageUri = fullMessageUri.GetBuffer(); + } + { + aListener->m_channel = null_nsCOMPtr(); + rv = NS_NewInputStreamChannel(getter_AddRefs(aListener->m_channel), + aURL, + nsnull, // inputStream + nsnull, // contentType + -1); + if (NS_FAILED(rv)) goto done; + + from = MESSAGE_RFC822; + to = "text/xul"; + + channelSupport = do_QueryInterface(aListener->m_channel); + + rv = streamConverterService->AsyncConvertData( + from.GetUnicode(), to.GetUnicode(), aListener, + channelSupport, getter_AddRefs(convertedListener)); + if (NS_FAILED(rv)) goto done; + + if (canFetchMimeParts) + rv = messageService->OpenAttachment(aURL, messageUri, convertedListener, + mMsgWindow, nsnull,nsnull); + else + rv = messageService->DisplayMessage(messageUri, + convertedListener,mMsgWindow, + nsnull, nsnull); + } + +done: + if (messageService) + ReleaseMessageServiceFromURI(unescapedUrl, messageService); + + if (NS_FAILED(rv)) + { + NS_IF_RELEASE(aListener); + Alert("saveAttachmentFailed"); + } + return rv; +} NS_IMETHODIMP nsMessenger::OpenAttachment(const char * url, const char * displayName, @@ -461,27 +581,10 @@ nsMessenger::OpenAttachment(const char * url, const char * displayName, // *** for now OpenAttachment is really a SaveAttachment nsresult rv = NS_ERROR_OUT_OF_MEMORY; char *unescapedUrl = nsnull; - nsIMsgMessageService * messageService = nsnull; - nsSaveAsListener *aListener = nsnull; - nsAutoString from, to; nsCOMPtr aSpec; nsCOMPtr fileSpec; - nsCOMPtr channelSupport; - nsCOMPtr convertedListener; - nsAutoString urlString; - char *urlCString = nsnull; char * unescapedDisplayName = nsnull; - nsCOMPtr aURL; nsAutoString tempStr; - PRBool canFetchMimeParts = PR_FALSE; - nsCAutoString fullMessageUri = messageUri; - - NS_WITH_SERVICE(nsIStreamConverterService, - streamConverterService, - kIStreamConverterServiceCID, &rv); - if (NS_FAILED(rv)) goto done; - - rv = NS_ERROR_OUT_OF_MEMORY; if (!url) goto done; @@ -521,7 +624,7 @@ nsMessenger::OpenAttachment(const char * url, const char * displayName, nsIFileSpecWithUI::eAllFiles); nsCRT::free(unescapedDisplayName); - if (rv = NS_ERROR_ABORT) + if (rv == NS_ERROR_ABORT) { rv = NS_OK; goto done; @@ -531,84 +634,73 @@ nsMessenger::OpenAttachment(const char * url, const char * displayName, aSpec = do_QueryInterface(fileSpec, &rv); if (NS_FAILED(rv)) goto done; - aListener = new nsSaveAsListener(aSpec, this); - if (!aListener) - { - rv = NS_ERROR_OUT_OF_MEMORY; - goto done; - } - NS_ADDREF(aListener); - - urlString = unescapedUrl; - - urlString.ReplaceSubstring("/;section", "?section"); - urlCString = urlString.ToNewCString(); - - rv = CreateStartupUrl(urlCString, getter_AddRefs(aURL)); - nsCRT::free(urlCString); - - if (NS_FAILED(rv)) goto done; - - rv = GetMessageServiceFromURI(messageUri, &messageService); - if (NS_FAILED(rv)) goto done; - - messageService->GetCanFetchMimeParts(&canFetchMimeParts); - - if (canFetchMimeParts) - { - PRInt32 sectionPos = urlString.Find("?section"); - nsString mimePart; - - urlString.Right(mimePart, urlString.Length() - sectionPos); - fullMessageUri.Append(mimePart); - -// nsCOMPtr streamListener = do_QueryInterface((nsIStreamListener *) aListener); -// nsCOMPtr supportsListener = streamListener; - messageUri = fullMessageUri.GetBuffer(); -// rv = messageService->DisplayMessage(fullMessageUri.GetBuffer(), -// supportsListener, mMsgWindow, -// nsnull, nsnull); - - } - { - aListener->m_channel = null_nsCOMPtr(); - rv = NS_NewInputStreamChannel(getter_AddRefs(aListener->m_channel), - aURL, - nsnull, // inputStream - nsnull, // contentType - -1); - if (NS_FAILED(rv)) goto done; - - from = MESSAGE_RFC822; - to = "text/xul"; - - channelSupport = do_QueryInterface(aListener->m_channel); - - rv = streamConverterService->AsyncConvertData( - from.GetUnicode(), to.GetUnicode(), aListener, - channelSupport, getter_AddRefs(convertedListener)); - if (NS_FAILED(rv)) goto done; - - if (canFetchMimeParts) - rv = messageService->OpenAttachment(aURL, messageUri, convertedListener, mMsgWindow, nsnull,nsnull); - else - rv = messageService->DisplayMessage(messageUri, - convertedListener,mMsgWindow, - nsnull, nsnull); - } + rv = SaveAttachment(aSpec, unescapedUrl, messageUri, nsnull); done: - if (messageService) - ReleaseMessageServiceFromURI(unescapedUrl, messageService); - PR_FREEIF(unescapedUrl); + return rv; +} - if (NS_FAILED(rv)) + +NS_IMETHODIMP +nsMessenger::SaveAllAttachments(PRUint32 count, const char **urlArray, + const char **displayNameArray, + const char **messageUriArray) +{ + nsresult rv = NS_ERROR_OUT_OF_MEMORY; + nsCOMPtr uFileSpec; + nsCOMPtr fileSpec; + nsFileSpec aFileSpec; + nsXPIDLCString dirName; + char *unescapedUrl = nsnull, *unescapedName = nsnull, *tempCStr = nsnull; + nsAutoString tempStr; + nsSaveAllAttachmentsState *saveState = nsnull; + + uFileSpec = getter_AddRefs(NS_CreateFileSpecWithUI()); + if (!uFileSpec) goto done; + + rv = uFileSpec->ChooseDirectory("Save All Attachments", + getter_Copies(dirName)); + if (rv == NS_ERROR_ABORT) { - NS_IF_RELEASE(aListener); - Alert("saveAttachmentFailed"); + rv = NS_OK; + goto done; } - return rv; + if (NS_FAILED(rv)) goto done; + rv = NS_NewFileSpec(getter_AddRefs(fileSpec)); + if (NS_FAILED(rv)) goto done; + + saveState = new nsSaveAllAttachmentsState(count, urlArray, + displayNameArray, + messageUriArray, + (const char*) dirName); + { + nsFileURL fileUrl((const char *) dirName); + nsFilePath dirPath(fileUrl); + unescapedUrl = PL_strdup(urlArray[0]); + nsUnescape(unescapedUrl); + unescapedName = PL_strdup(displayNameArray[0]); + nsUnescape(unescapedName); + rv = ConvertToUnicode("UTF-8", unescapedName, tempStr); + if (NS_FAILED(rv)) goto done; + rv = ConvertFromUnicode(nsMsgI18NFileSystemCharset(), tempStr, + &tempCStr); + if (NS_FAILED(rv)) goto done; + PR_FREEIF(unescapedName); + unescapedName = tempCStr; + aFileSpec = dirPath; + aFileSpec += unescapedName; + fileSpec->SetFromFileSpec(aFileSpec); + rv = SaveAttachment(fileSpec, unescapedUrl, messageUriArray[0], + (void *)saveState); + if (NS_FAILED(rv)) goto done; + } +done: + + PR_FREEIF (unescapedUrl); + PR_FREEIF (unescapedName); + + return rv; } @@ -1519,6 +1611,7 @@ nsSaveAsListener::nsSaveAsListener(nsIFileSpec* aSpec, nsMessenger *aMessenger) m_charset = ""; m_outputFormat = ""; m_msgBuffer = ""; + m_saveAllAttachmentsState = nsnull; } nsSaveAsListener::~nsSaveAsListener() @@ -1687,6 +1780,56 @@ nsSaveAsListener::OnStopRequest(nsIChannel* aChannel, nsISupports* aSupport, m_outputStream = null_nsCOMPtr(); } + if (m_saveAllAttachmentsState) + { + m_saveAllAttachmentsState->m_curIndex++; + if (m_saveAllAttachmentsState->m_curIndex < + m_saveAllAttachmentsState->m_count) + { + char * unescapedUrl = nsnull, * unescapedName = nsnull, + * tempCStr = nsnull; + nsAutoString tempStr; + nsSaveAllAttachmentsState *state = m_saveAllAttachmentsState; + PRUint32 i = state->m_curIndex; + nsFileURL fileUrl(state->m_directoryName); + nsFilePath dirPath(fileUrl); + nsCOMPtr fileSpec; + nsFileSpec aFileSpec; + + rv = NS_NewFileSpec(getter_AddRefs(fileSpec)); + if (NS_FAILED(rv)) goto done; + unescapedUrl = PL_strdup(state->m_urlArray[i]); + nsUnescape(unescapedUrl); + unescapedName = PL_strdup(state->m_displayNameArray[i]); + nsUnescape(unescapedName); + rv = ConvertToUnicode("UTF-8", unescapedName, tempStr); + if (NS_FAILED(rv)) goto done; + rv = ConvertFromUnicode(nsMsgI18NFileSystemCharset(), tempStr, + &tempCStr); + if (NS_FAILED(rv)) goto done; + PR_FREEIF(unescapedName); + unescapedName = tempCStr; + aFileSpec = dirPath; + aFileSpec += unescapedName; + fileSpec->SetFromFileSpec(aFileSpec); + rv = m_messenger->SaveAttachment(fileSpec, unescapedUrl, + state->m_messageUriArray[i], + (void *)state); + done: + if (NS_FAILED(rv)) + { + delete state; + m_saveAllAttachmentsState = nsnull; + } + PR_FREEIF(unescapedUrl); + PR_FREEIF(unescapedName); + } + else + { + delete m_saveAllAttachmentsState; + m_saveAllAttachmentsState = nsnull; + } + } Release(); // all done kill ourself return NS_OK; } @@ -1775,3 +1918,42 @@ nsMessenger::GetString(const PRUnichar *aStringName) else return nsCRT::strdup(aStringName); } + +nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(PRUint32 count, + const char **urlArray, + const char **nameArray, + const char **uriArray, + const char *dirName) +{ + PRUint32 i; + NS_ASSERTION(count && urlArray && nameArray && uriArray && dirName, + "fatal - invalid parameters\n"); + + m_count = count; + m_curIndex = 0; + m_urlArray = new char*[count]; + m_displayNameArray = new char*[count]; + m_messageUriArray = new char*[count]; + for (i = 0; i < count; i++) + { + m_urlArray[i] = nsCRT::strdup(urlArray[i]); + m_displayNameArray[i] = nsCRT::strdup(nameArray[i]); + m_messageUriArray[i] = nsCRT::strdup(uriArray[i]); + } + m_directoryName = nsCRT::strdup(dirName); +} + +nsSaveAllAttachmentsState::~nsSaveAllAttachmentsState() +{ + PRUint32 i; + for (i = 0; i < m_count; i++) + { + nsCRT::free(m_urlArray[i]); + nsCRT::free(m_displayNameArray[i]); + nsCRT::free(m_messageUriArray[i]); + } + delete m_urlArray; + delete m_displayNameArray; + delete m_messageUriArray; + nsCRT::free(m_directoryName); +} diff --git a/mailnews/base/src/nsMessenger.h b/mailnews/base/src/nsMessenger.h index 0e42f9b903e4..a40b3ea02df2 100644 --- a/mailnews/base/src/nsMessenger.h +++ b/mailnews/base/src/nsMessenger.h @@ -46,6 +46,8 @@ public: NS_DECL_NSIMESSENGER nsresult Alert(const char * stringName); + nsresult SaveAttachment(nsIFileSpec *fileSpec, const char* unescapedUrl, + const char* messageUri, void *closure); protected: nsresult DoDelete(nsIRDFCompositeDataSource* db, nsISupportsArray *srcArray, nsISupportsArray *deletedArray); diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp index d60d2a485576..3b3013032643 100644 --- a/mailnews/imap/src/nsImapProtocol.cpp +++ b/mailnews/imap/src/nsImapProtocol.cpp @@ -818,7 +818,7 @@ nsImapProtocol::PseudoInterruptMsgLoad(nsIImapUrl *aImapUrl, PRBool *interrupted nsAutoCMonitor(this); - if (m_runningUrl) + if (m_runningUrl && !TestFlag(IMAP_CLEAN_UP_URL_STATE)) { nsImapAction imapAction; m_runningUrl->GetImapAction(&imapAction); @@ -1148,7 +1148,9 @@ PRBool nsImapProtocol::ProcessCurrentURL() rv = m_channelListener->OnStopRequest(m_mockChannel, m_channelContext, NS_OK, nsnull); m_lastActiveTime = PR_Now(); // ** jt -- is this the best place for time stamp - PseudoInterrupt(PR_FALSE); // clear this, because we must be done interrupting? + PseudoInterrupt(PR_FALSE); // clear this, because we must be done + // interrupting? + SetFlag(IMAP_CLEAN_UP_URL_STATE); if (NS_SUCCEEDED(rv) && GetConnectionStatus() >= 0 && GetServerStateParser().LastCommandSuccessful() && m_imapMiscellaneousSink && m_runningUrl) { @@ -1168,6 +1170,8 @@ PRBool nsImapProtocol::ProcessCurrentURL() ReleaseUrlState(); ResetProgressInfo(); m_urlInProgress = PR_FALSE; + ClearFlag(IMAP_CLEAN_UP_URL_STATE); + // now try queued urls, now that we've released this connection. if (m_imapServerSink && GetConnectionStatus() >= 0) { diff --git a/mailnews/imap/src/nsImapProtocol.h b/mailnews/imap/src/nsImapProtocol.h index 16af5e399831..af19cec6283e 100644 --- a/mailnews/imap/src/nsImapProtocol.h +++ b/mailnews/imap/src/nsImapProtocol.h @@ -74,6 +74,8 @@ class nsIMsgIncomingServer; #define IMAP_CONNECTION_IS_OPEN 0x00000004 /* is the connection currently open? */ #define IMAP_WAITING_FOR_DATA 0x00000008 +#define IMAP_CLEAN_UP_URL_STATE 0x00000010 // processing clean up url state + class nsImapProtocol : public nsIImapProtocol, public nsIRunnable { public: diff --git a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp index e38d25d299f8..72469615db52 100644 --- a/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeBaseEmitter.cpp @@ -349,6 +349,12 @@ nsMimeBaseEmitter::EndAttachment() return NS_OK; } +nsresult +nsMimeBaseEmitter::EndAllAttachments() +{ + return NS_OK; +} + NS_IMETHODIMP nsMimeBaseEmitter::AddAttachmentField(const char *field, const char *value) { diff --git a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp index a97c5f7e4aca..ddd7f7b042ed 100644 --- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp +++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.cpp @@ -356,6 +356,17 @@ nsMimeHtmlDisplayEmitter::EndAttachment() return NS_OK; } +nsresult +nsMimeHtmlDisplayEmitter::EndAllAttachments() +{ + nsresult rv = NS_OK; + nsCOMPtr headerSink; + rv = GetHeaderSink(getter_AddRefs(headerSink)); + if (headerSink) + headerSink->OnEndAllAttachments(); + return rv; +} + nsresult nsMimeHtmlDisplayEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten) { diff --git a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h index c5c732e5288c..3219446b3c66 100644 --- a/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h +++ b/mailnews/mime/emitters/src/nsMimeHtmlEmitter.h @@ -49,6 +49,7 @@ public: PRBool aNotDownloaded); NS_IMETHOD AddAttachmentField(const char *field, const char *value); NS_IMETHOD EndAttachment(); + NS_IMETHOD EndAllAttachments(); // Body handling routines NS_IMETHOD WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten); diff --git a/mailnews/mime/public/nsIMimeEmitter.idl b/mailnews/mime/public/nsIMimeEmitter.idl index 9e7db8d4bd8b..3fd4c1b6c565 100644 --- a/mailnews/mime/public/nsIMimeEmitter.idl +++ b/mailnews/mime/public/nsIMimeEmitter.idl @@ -65,6 +65,8 @@ interface nsIMimeEmitter : nsISupports{ void AddAttachmentField([const] in string field, [const] in string value); void EndAttachment(); + void EndAllAttachments(); + // Body handling routines void StartBody(in PRBool bodyOnly, [const] in string msgID, [const] in string outCharset); void WriteBody([const] in string buf, in PRUint32 size, out PRUint32 amountWritten); diff --git a/mailnews/mime/public/nsIMimeMiscStatus.idl b/mailnews/mime/public/nsIMimeMiscStatus.idl index 2604ff230b10..040c1fe31cec 100644 --- a/mailnews/mime/public/nsIMimeMiscStatus.idl +++ b/mailnews/mime/public/nsIMimeMiscStatus.idl @@ -51,5 +51,7 @@ interface nsIMsgHeaderSink : nsISupports{ // make a sandwhich around header processing..... void onStartHeaders(); void onEndHeaders(); - void handleAttachment(in string url, in wstring displayName, in string uri, in boolean aNotDownloaded); + void handleAttachment(in string url, in wstring displayName, in string + uri, in boolean aNotDownloaded); + void onEndAllAttachments(); }; diff --git a/mailnews/mime/src/mimemoz2.cpp b/mailnews/mime/src/mimemoz2.cpp index 583e2e2553ca..c076bcb9a409 100644 --- a/mailnews/mime/src/mimemoz2.cpp +++ b/mailnews/mime/src/mimemoz2.cpp @@ -510,6 +510,7 @@ NotifyEmittersOfAttachmentList(MimeDisplayOptions *opt, ++i; ++tmp; } + mimeEmitterEndAllAttachments(opt); } // Utility to create a nsIURI object... @@ -1518,6 +1519,29 @@ mimeEmitterEndAttachment(MimeDisplayOptions *opt) return NS_ERROR_FAILURE; } +extern "C" nsresult +mimeEmitterEndAllAttachments(MimeDisplayOptions *opt) +{ + // Check for draft processing... + if (NoEmitterProcessing(opt->format_out)) + return NS_OK; + + mime_stream_data *msd = GetMSD(opt); + if (!msd) + return NS_ERROR_FAILURE; + + if (msd->output_emitter) + { + nsIMimeEmitter *emitter = (nsIMimeEmitter *)msd->output_emitter; + if (emitter) + return emitter->EndAllAttachments(); + else + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + extern "C" nsresult mimeEmitterStartBody(MimeDisplayOptions *opt, PRBool bodyOnly, const char *msgID, const char *outCharset) { diff --git a/mailnews/mime/src/mimemoz2.h b/mailnews/mime/src/mimemoz2.h index 6297ffc76639..8c5e67aa29fd 100644 --- a/mailnews/mime/src/mimemoz2.h +++ b/mailnews/mime/src/mimemoz2.h @@ -141,6 +141,7 @@ extern "C" nsresult mimeEmitterAddHeaderField(MimeDisplayOptions *opt, const extern "C" nsresult mimeEmitterStartAttachment(MimeDisplayOptions *opt, const char *name, const char *contentType, const char *url, PRBool aNotDownloaded); extern "C" nsresult mimeEmitterEndAttachment(MimeDisplayOptions *opt); +extern "C" nsresult mimeEmitterEndAllAttachments(MimeDisplayOptions *opt); extern "C" nsresult mimeEmitterStartBody(MimeDisplayOptions *opt, PRBool bodyOnly, const char *msgID, const char *outCharset); extern "C" nsresult mimeEmitterEndBody(MimeDisplayOptions *opt); extern "C" nsresult mimeEmitterEndHeader(MimeDisplayOptions *opt);