From 03af6b3cbea844c1ea274d21c6b4a75e2cdcd53b Mon Sep 17 00:00:00 2001 From: "mscott%netscape.com" Date: Thu, 22 Jun 2000 22:37:22 +0000 Subject: [PATCH] 10802 --> implement open attachment r=bienvenu --- mailnews/imap/src/nsImapService.cpp | 116 ++++++++++++++++++++---- mailnews/imap/src/nsImapService.h | 5 +- mailnews/local/src/nsMailboxService.cpp | 68 +++++++++----- mailnews/news/src/nsNntpService.cpp | 21 ++--- 4 files changed, 154 insertions(+), 56 deletions(-) diff --git a/mailnews/imap/src/nsImapService.cpp b/mailnews/imap/src/nsImapService.cpp index a410ec619009..3703e0e9a09b 100644 --- a/mailnews/imap/src/nsImapService.cpp +++ b/mailnews/imap/src/nsImapService.cpp @@ -38,6 +38,7 @@ #include "nsIImapMockChannel.h" #include "nsImapUtils.h" #include "nsIDocShell.h" +#include "nsIDocShellLoadInfo.h" #include "nsIRDFService.h" #include "nsIEventQueueService.h" #include "nsXPIDLString.h" @@ -72,11 +73,12 @@ static PRBool gMIMEOnDemand = PR_FALSE; NS_IMPL_THREADSAFE_ADDREF(nsImapService); NS_IMPL_THREADSAFE_RELEASE(nsImapService); -NS_IMPL_QUERY_INTERFACE4(nsImapService, +NS_IMPL_QUERY_INTERFACE5(nsImapService, nsIImapService, nsIMsgMessageService, nsIProtocolHandler, - nsIMsgProtocolInfo) + nsIMsgProtocolInfo, + nsIMsgMessageFetchPartService) nsImapService::nsImapService() { @@ -290,16 +292,75 @@ NS_IMETHODIMP nsImapService::GetUrlForUri(const char *aMessageURI, nsIURI **aURL return rv; } -/* readonly attribute canFetchMimeParts; */ -NS_IMETHODIMP nsImapService::GetCanFetchMimeParts(PRBool *canFetchMimeParts) +NS_IMETHODIMP nsImapService::OpenAttachment(const char *aContentType, const char *aUrl, + const char *aMessageUri, + nsISupports *aDisplayConsumer, + nsIMsgWindow *aMsgWindow, + nsIUrlListener *aUrlListener) { - if (!canFetchMimeParts) return NS_ERROR_NULL_POINTER; - *canFetchMimeParts = PR_TRUE; - return NS_OK; + nsresult rv = NS_OK; + // okay this is a little tricky....we may have to fetch the mime part + // or it may already be downloaded for us....the only way i can tell to + // distinguish the two events is to search for ?section or ?part + + nsCAutoString uri = aMessageUri; + nsCAutoString urlString = aUrl; + urlString.ReplaceSubstring("/;section", "?section"); + + // more stuff i don't understand + PRInt32 sectionPos = urlString.Find("?section"); + // if we have a section field then we must be dealing with a mime part we need to fetchf + if (sectionPos > 0) + { + nsCAutoString mimePart; + + urlString.Right(mimePart, urlString.Length() - sectionPos); + uri.Append(mimePart); + uri += "&type="; + uri += aContentType; + } + else + { + // try to extract the specific part number out from the url string + uri += "?"; + const char *part = PL_strstr(aUrl, "part="); + uri += part; + uri += "&type="; + uri += aContentType; + } + + nsCOMPtr folder; + nsXPIDLCString msgKey; + nsXPIDLCString uriMimePart; + nsCAutoString folderURI; + nsMsgKey key; + + rv = DecomposeImapURI(uri, getter_AddRefs(folder), getter_Copies(msgKey)); + rv = nsParseImapMessageURI(uri, folderURI, &key, getter_Copies(uriMimePart)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr imapMessageSink(do_QueryInterface(folder, &rv)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr imapUrl; + nsCAutoString urlSpec; + PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder); + rv = CreateStartOfImapUrl(uri, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator); + if (NS_FAILED(rv)) + return rv; + if (uriMimePart) + { + rv = FetchMimePart(imapUrl, nsIImapUrl::nsImapOpenMimePart, folder, imapMessageSink, + nsnull, aDisplayConsumer, msgKey, uriMimePart); + } + } // if we got a message sink + } // if we parsed the message uri + + return rv; } /* void OpenAttachment (in nsIURI aURI, in nsISupports aDisplayConsumer, in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener, out nsIURI aURL); */ -NS_IMETHODIMP nsImapService::OpenAttachment(nsIURI *aURI, const char *aMessageURI, nsISupports *aDisplayConsumer, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI **aURL) +NS_IMETHODIMP nsImapService::FetchMimePart(nsIURI *aURI, const char *aMessageURI, nsISupports *aDisplayConsumer, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI **aURL) { nsresult rv = NS_OK; nsCOMPtr folder; @@ -425,15 +486,18 @@ nsresult nsImapService::FetchMimePart(nsIImapUrl * aImapUrl, // create a protocol instance to handle the request. // NOTE: once we start working with multiple connections, this step will be much more complicated...but for now // just create a connection and process the request. - NS_ASSERTION (aImapUrl && aImapMailFolder && aImapMessage,"Oops ... null pointer"); - if (!aImapUrl || !aImapMailFolder || !aImapMessage) - return NS_ERROR_NULL_POINTER; + NS_ASSERTION (aImapUrl && aImapMailFolder && aImapMessage,"Oops ... null pointer"); + if (!aImapUrl || !aImapMailFolder || !aImapMessage) + return NS_ERROR_NULL_POINTER; - nsCAutoString urlSpec; - rv = SetImapUrlSink(aImapMailFolder, aImapUrl); + nsCAutoString urlSpec; + rv = SetImapUrlSink(aImapMailFolder, aImapUrl); + nsImapAction actionToUse = aImapAction; + if (actionToUse == nsImapUrl::nsImapOpenMimePart) + actionToUse = nsIImapUrl::nsImapMsgFetch; - rv = aImapUrl->SetImapMessageSink(aImapMessage); - if (NS_SUCCEEDED(rv)) + rv = aImapUrl->SetImapMessageSink(aImapMessage); + if (NS_SUCCEEDED(rv)) { nsXPIDLCString currentSpec; nsCOMPtr url = do_QueryInterface(aImapUrl); @@ -466,7 +530,7 @@ nsresult nsImapService::FetchMimePart(nsIImapUrl * aImapUrl, // const char *. hopefully they will fix it soon. rv = url->SetSpec((char *) urlSpec.GetBuffer()); - rv = aImapUrl->SetImapAction(aImapAction /* nsIImapUrl::nsImapMsgFetch */); + rv = aImapUrl->SetImapAction(actionToUse /* nsIImapUrl::nsImapMsgFetch */); if (aImapMailFolder && aDisplayConsumer) { nsCOMPtr aMsgIncomingServer; @@ -486,7 +550,19 @@ nsresult nsImapService::FetchMimePart(nsIImapUrl * aImapUrl, nsCOMPtr docShell(do_QueryInterface(aDisplayConsumer, &rv)); if (NS_SUCCEEDED(rv) && docShell) - rv = docShell->LoadURI(url, nsnull); + { + nsCOMPtr loadInfo; + // DIRTY LITTLE HACK --> if we are opening an attachment we want the docshell to + // treat this load as if it were a user click event. Then the dispatching stuff will be much + // happier. + if (aImapAction == nsImapUrl::nsImapOpenMimePart) + { + docShell->CreateLoadInfo(getter_AddRefs(loadInfo)); + loadInfo->SetLoadType(nsIDocShellLoadInfo::loadLink); + } + + rv = docShell->LoadURI(url, loadInfo); + } else { nsCOMPtr aStreamListener = do_QueryInterface(aDisplayConsumer, &rv); @@ -814,7 +890,7 @@ nsImapService::FetchMessage(nsIImapUrl * aImapUrl, // const char *. hopefully they will fix it soon. rv = url->SetSpec((char *) urlSpec.GetBuffer()); - rv = aImapUrl->SetImapAction(aImapAction /* nsIImapUrl::nsImapMsgFetch */); + rv = aImapUrl->SetImapAction(aImapAction); if (aImapMailFolder && aDisplayConsumer) { nsCOMPtr aMsgIncomingServer; @@ -834,7 +910,9 @@ nsImapService::FetchMessage(nsIImapUrl * aImapUrl, nsCOMPtr docShell(do_QueryInterface(aDisplayConsumer, &rv)); if (NS_SUCCEEDED(rv) && docShell) - rv = docShell->LoadURI(url, nsnull); + { + rv = docShell->LoadURI(url, nsnull); + } else { nsCOMPtr aStreamListener = do_QueryInterface(aDisplayConsumer, &rv); diff --git a/mailnews/imap/src/nsImapService.h b/mailnews/imap/src/nsImapService.h index 383499bb5cd9..2d0e47f45dfc 100644 --- a/mailnews/imap/src/nsImapService.h +++ b/mailnews/imap/src/nsImapService.h @@ -39,6 +39,7 @@ class nsIMsgStatusFeedback; class nsImapService : public nsIImapService, public nsIMsgMessageService, + public nsIMsgMessageFetchPartService, public nsIProtocolHandler, public nsIMsgProtocolInfo { @@ -63,7 +64,9 @@ public: //////////////////////////////////////////////////////////////////////////////////////// // we suppport the nsIProtocolHandler interface //////////////////////////////////////////////////////////////////////////////////////// - NS_DECL_NSIPROTOCOLHANDLER + NS_DECL_NSIPROTOCOLHANDLER + + NS_DECL_NSIMSGMESSAGEFETCHPARTSERVICE protected: PRUnichar GetHierarchyDelimiter(nsIMsgFolder* aMsgFolder); diff --git a/mailnews/local/src/nsMailboxService.cpp b/mailnews/local/src/nsMailboxService.cpp index 6bc950075b2c..73bb03d9cc23 100644 --- a/mailnews/local/src/nsMailboxService.cpp +++ b/mailnews/local/src/nsMailboxService.cpp @@ -40,6 +40,7 @@ #include "nsMsgUtils.h" #include "nsIStreamConverterService.h" #include "nsNetUtil.h" +#include "nsIDocShellLoadInfo.h" static NS_DEFINE_CID(kIStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID); @@ -129,7 +130,11 @@ nsresult nsMailboxService::FetchMessage(const char* aMessageURI, nsresult rv = NS_OK; nsCOMPtr mailboxurl; - rv = PrepareMessageUrl(aMessageURI, aUrlListener, mailboxAction, getter_AddRefs(mailboxurl), aMsgWindow); + nsMailboxAction actionToUse = mailboxAction; + if (mailboxAction == nsIMailboxUrl::ActionOpenAttachment) + actionToUse = nsIMailboxUrl::ActionDisplayMessage; + + rv = PrepareMessageUrl(aMessageURI, aUrlListener, actionToUse , getter_AddRefs(mailboxurl), aMsgWindow); if (NS_SUCCEEDED(rv)) { @@ -141,9 +146,20 @@ nsresult nsMailboxService::FetchMessage(const char* aMessageURI, // instead of running the mailbox url like we used to, let's try to run the url in the docshell... nsCOMPtr docShell(do_QueryInterface(aDisplayConsumer, &rv)); - // if we were given a webshell, run the url in the docshell..otherwise just run it normally. + // if we were given a docShell, run the url in the docshell..otherwise just run it normally. if (NS_SUCCEEDED(rv) && docShell) - rv = docShell->LoadURI(url, nsnull); + { + nsCOMPtr loadInfo; + // DIRTY LITTLE HACK --> if we are opening an attachment we want the docshell to + // treat this load as if it were a user click event. Then the dispatching stuff will be much + // happier. + if (mailboxAction == nsIMailboxUrl::ActionOpenAttachment) + { + docShell->CreateLoadInfo(getter_AddRefs(loadInfo)); + loadInfo->SetLoadType(nsIDocShellLoadInfo::loadLink); + } + rv = docShell->LoadURI(url, loadInfo); + } else rv = RunMailboxUrl(url, aDisplayConsumer); } @@ -167,10 +183,24 @@ nsresult nsMailboxService::DisplayMessage(const char* aMessageURI, nsIMailboxUrl::ActionDisplayMessage, aCharsetOveride, aURL); } -/* void OpenAttachment (in nsIURI aURI, in nsISupports aDisplayConsumer, in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener, out nsIURI aURL); */ -NS_IMETHODIMP nsMailboxService::OpenAttachment(nsIURI *aURI, const char *aMessageURI, nsISupports *aDisplayConsumer, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI **aURL) +NS_IMETHODIMP nsMailboxService::OpenAttachment(const char *aContentType, const char *aUrl, + const char *aMessageUri, + nsISupports *aDisplayConsumer, + nsIMsgWindow *aMsgWindow, + nsIUrlListener *aUrlListener) { - return NS_ERROR_NOT_IMPLEMENTED; + nsCAutoString partMsgUrl = aMessageUri; + + // try to extract the specific part number out from the url string + partMsgUrl += "?"; + const char *part = PL_strstr(aUrl, "part="); + partMsgUrl += part; + partMsgUrl += "&type="; + partMsgUrl += aContentType; + return FetchMessage(partMsgUrl, aDisplayConsumer, + aMsgWindow,aUrlListener, + nsIMailboxUrl::ActionOpenAttachment, nsnull, nsnull); + } @@ -190,14 +220,15 @@ nsMailboxService::SaveMessageToDisk(const char *aMessageURI, if (NS_SUCCEEDED(rv)) { - nsCOMPtr msgUrl = do_QueryInterface(mailboxurl); - if (msgUrl) - { - msgUrl->SetMessageFile(aFile); - msgUrl->SetAddDummyEnvelope(aAddDummyEnvelope); - msgUrl->SetCanonicalLineEnding(canonicalLineEnding); - } - nsCOMPtr url = do_QueryInterface(mailboxurl); + nsCOMPtr msgUrl = do_QueryInterface(mailboxurl); + if (msgUrl) + { + msgUrl->SetMessageFile(aFile); + msgUrl->SetAddDummyEnvelope(aAddDummyEnvelope); + msgUrl->SetCanonicalLineEnding(canonicalLineEnding); + } + + nsCOMPtr url = do_QueryInterface(mailboxurl); rv = RunMailboxUrl(url); } @@ -217,15 +248,6 @@ NS_IMETHODIMP nsMailboxService::GetUrlForUri(const char *aMessageURI, nsIURI **a return rv; } -/* readonly attribute canFetchMimeParts; */ -NS_IMETHODIMP nsMailboxService::GetCanFetchMimeParts(PRBool *canFetchMimeParts) -{ - if (!canFetchMimeParts) return NS_ERROR_NULL_POINTER; - *canFetchMimeParts = PR_FALSE; - return NS_OK; -} - - nsresult nsMailboxService::DisplayMessageNumber(const char *url, PRUint32 aMessageNumber, nsISupports * aDisplayConsumer, diff --git a/mailnews/news/src/nsNntpService.cpp b/mailnews/news/src/nsNntpService.cpp index 95991dc9c069..b05d83b3aa31 100644 --- a/mailnews/news/src/nsNntpService.cpp +++ b/mailnews/news/src/nsNntpService.cpp @@ -212,22 +212,17 @@ nsresult nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aD return rv; } -/* void OpenAttachment (in nsIURI aURI, in nsISupports aDisplayConsumer, in nsIMsgWindow aMsgWindow, in nsIUrlListener aUrlListener, out nsIURI aURL); */ -NS_IMETHODIMP nsNntpService::OpenAttachment(nsIURI *aURI, const char *aMessageURI, nsISupports *aDisplayConsumer, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI **aURL) + +NS_IMETHODIMP nsNntpService::OpenAttachment(const char *aContentType, const char *aUrl, + const char *aMessageUri, + nsISupports *aDisplayConsumer, + nsIMsgWindow *aMsgWindow, + nsIUrlListener *aUrlListener) { - return NS_ERROR_NOT_IMPLEMENTED; + // news doesn't know anything about opening attachments.... + return NS_ERROR_NOT_IMPLEMENTED; } - -/* readonly attribute canFetchMimeParts; */ -NS_IMETHODIMP nsNntpService::GetCanFetchMimeParts(PRBool *canFetchMimeParts) -{ - if (!canFetchMimeParts) return NS_ERROR_NULL_POINTER; - *canFetchMimeParts = PR_FALSE; - return NS_OK; -} - - NS_IMETHODIMP nsNntpService::GetUrlForUri(const char *aMessageURI, nsIURI **aURL, nsIMsgWindow *aMsgWindow) { nsresult rv = NS_OK;