mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 11:40:13 +01:00
3386 lines
122 KiB
C++
3386 lines
122 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "msgCore.h" // precompiled header...
|
|
#include "nsMsgImapCID.h"
|
|
|
|
#include "netCore.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIComponentManager.h"
|
|
|
|
#include "nsIIMAPHostSessionList.h"
|
|
#include "nsImapService.h"
|
|
#include "nsImapUrl.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIMsgFolder.h"
|
|
#include "nsIMsgImapMailFolder.h"
|
|
#include "nsIImapIncomingServer.h"
|
|
#include "nsIImapServerSink.h"
|
|
#include "nsIImapMockChannel.h"
|
|
#include "nsImapUtils.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIDocShellLoadInfo.h"
|
|
#include "nsIRDFService.h"
|
|
#include "nsIEventQueueService.h"
|
|
#include "nsXPIDLString.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsRDFCID.h"
|
|
#include "nsEscape.h"
|
|
#include "nsIMsgStatusFeedback.h"
|
|
#include "nsIPrefBranch.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsILoadGroup.h"
|
|
#include "nsIMsgAccountManager.h"
|
|
#include "nsMsgBaseCID.h"
|
|
#include "nsMsgFolderFlags.h"
|
|
#include "nsISubscribableServer.h"
|
|
#include "nsIDirectoryService.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsIWebNavigation.h"
|
|
#include "nsImapStringBundle.h"
|
|
#include "plbase64.h"
|
|
#include "nsImapOfflineSync.h"
|
|
#include "nsIMsgHdr.h"
|
|
#include "nsMsgUtils.h"
|
|
#include "nsICacheService.h"
|
|
#include "nsIStreamListenerTee.h"
|
|
#include "nsNetCID.h"
|
|
#include "nsMsgI18N.h"
|
|
#include "nsIOutputStream.h"
|
|
#include "nsIInputStream.h"
|
|
#include "nsICopyMsgStreamListener.h"
|
|
#include "nsIFileStream.h"
|
|
#include "nsIMsgParseMailMsgState.h"
|
|
#include "nsMsgLocalCID.h"
|
|
#include "nsIOutputStream.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIDocShellLoadInfo.h"
|
|
#include "nsIDOMWindowInternal.h"
|
|
#include "nsIMessengerWindowService.h"
|
|
#include "nsIWindowMediator.h"
|
|
#include "nsIPrompt.h"
|
|
#include "nsIWindowWatcher.h"
|
|
#include "nsImapProtocol.h"
|
|
#include "nsIMsgMailSession.h"
|
|
#include "nsIStreamConverterService.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsInt64.h"
|
|
|
|
#define PREF_MAIL_ROOT_IMAP "mail.root.imap" // old - for backward compatibility only
|
|
#define PREF_MAIL_ROOT_IMAP_REL "mail.root.imap-rel"
|
|
|
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
|
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
|
|
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
|
|
|
|
|
static const char sequenceString[] = "SEQUENCE";
|
|
static const char uidString[] = "UID";
|
|
|
|
static PRBool gInitialized = PR_FALSE;
|
|
static PRInt32 gMIMEOnDemandThreshold = 15000;
|
|
static PRBool gMIMEOnDemand = PR_FALSE;
|
|
|
|
NS_IMPL_THREADSAFE_ADDREF(nsImapService)
|
|
NS_IMPL_THREADSAFE_RELEASE(nsImapService)
|
|
NS_IMPL_QUERY_INTERFACE6(nsImapService,
|
|
nsIImapService,
|
|
nsIMsgMessageService,
|
|
nsIProtocolHandler,
|
|
nsIMsgProtocolInfo,
|
|
nsIMsgMessageFetchPartService,
|
|
nsIContentHandler)
|
|
|
|
nsImapService::nsImapService()
|
|
{
|
|
mPrintingOperation = PR_FALSE;
|
|
if (!gInitialized)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
|
if (NS_SUCCEEDED(rv) && prefBranch)
|
|
{
|
|
prefBranch->GetBoolPref("mail.imap.mime_parts_on_demand", &gMIMEOnDemand);
|
|
prefBranch->GetIntPref("mail.imap.mime_parts_on_demand_threshold", &gMIMEOnDemandThreshold);
|
|
}
|
|
gInitialized = PR_TRUE;
|
|
}
|
|
}
|
|
|
|
nsImapService::~nsImapService()
|
|
{
|
|
}
|
|
|
|
PRUnichar nsImapService::GetHierarchyDelimiter(nsIMsgFolder* aMsgFolder)
|
|
{
|
|
PRUnichar delimiter = '/';
|
|
if (aMsgFolder)
|
|
{
|
|
nsCOMPtr<nsIMsgImapMailFolder> imapFolder = do_QueryInterface(aMsgFolder);
|
|
if (imapFolder)
|
|
imapFolder->GetHierarchyDelimiter(&delimiter);
|
|
}
|
|
return delimiter;
|
|
}
|
|
|
|
// N.B., this returns an escaped folder name, appropriate for putting in a url.
|
|
nsresult
|
|
nsImapService::GetFolderName(nsIMsgFolder* aImapFolder,
|
|
char **folderName)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIMsgImapMailFolder> aFolder(do_QueryInterface(aImapFolder, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsXPIDLCString onlineName;
|
|
// online name is in imap utf-7 - leave it that way
|
|
rv = aFolder->GetOnlineName(getter_Copies(onlineName));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (onlineName.IsEmpty())
|
|
{
|
|
char *uri = nsnull;
|
|
rv = aImapFolder->GetURI(&uri);
|
|
if (NS_FAILED(rv)) return rv;
|
|
char * hostname = nsnull;
|
|
rv = aImapFolder->GetHostname(&hostname);
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = nsImapURI2FullName(kImapRootURI, hostname, uri, getter_Copies(onlineName));
|
|
PR_Free(uri);
|
|
PR_Free(hostname);
|
|
}
|
|
// if the hierarchy delimiter is not '/', then we want to escape slashes;
|
|
// otherwise, we do want to escape slashes.
|
|
// we want to escape slashes and '^' first, otherwise, nsEscape will lose them
|
|
PRBool escapeSlashes = (GetHierarchyDelimiter(aImapFolder) != (PRUnichar) '/');
|
|
if (escapeSlashes && (const char *) onlineName)
|
|
{
|
|
char* escapedOnlineName;
|
|
rv = nsImapUrl::EscapeSlashes((const char *) onlineName, &escapedOnlineName);
|
|
if (NS_SUCCEEDED(rv))
|
|
onlineName.Adopt(escapedOnlineName);
|
|
}
|
|
// need to escape everything else
|
|
*folderName = nsEscape((const char *) onlineName, url_Path);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIMsgWindow *aMsgWindow,
|
|
nsIURI ** aURL)
|
|
{
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (WeAreOffline())
|
|
return NS_MSG_ERROR_OFFLINE;
|
|
|
|
PRBool canOpenThisFolder = PR_TRUE;
|
|
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(aImapMailFolder);
|
|
if (imapFolder)
|
|
imapFolder->GetCanIOpenThisFolder(&canOpenThisFolder);
|
|
|
|
if (!canOpenThisFolder)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aImapMailFolder, aUrlListener, urlSpec, hierarchySeparator);
|
|
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
// nsImapUrl::SetSpec() will set the imap action properly
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
// if no msg window, we won't put up error messages (this is almost certainly a biff-inspired get new msgs)
|
|
if (!aMsgWindow)
|
|
mailNewsUrl->SetSuppressErrorMsgs(PR_TRUE);
|
|
mailNewsUrl->SetMsgWindow(aMsgWindow);
|
|
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/select>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
rv = mailNewsUrl->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
imapUrl,
|
|
nsnull,
|
|
aURL);
|
|
}
|
|
} // if we have a url to run....
|
|
|
|
return rv;
|
|
}
|
|
|
|
// lite select, used to verify UIDVALIDITY while going on/offline
|
|
NS_IMETHODIMP
|
|
nsImapService::LiteSelectFolder(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/liteselect>", nsIImapUrl::nsImapLiteSelectFolder, aURL);
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::GetUrlForUri(const char *aMessageURI, nsIURI **aURL, nsIMsgWindow *aMsgWindow)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (PL_strstr(aMessageURI, "&type=application/x-message-display"))
|
|
return NS_NewURI(aURL, aMessageURI);
|
|
|
|
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
rv = DecomposeImapURI(aMessageURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(aMessageURI, getter_AddRefs(imapUrl), folder, nsnull, urlSpec, hierarchySeparator);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetImapUrlSink(folder, imapUrl);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(imapUrl);
|
|
PRBool useLocalCache = PR_FALSE;
|
|
folder->HasMsgOffline(atoi(msgKey), &useLocalCache);
|
|
mailnewsUrl->SetMsgIsInLocalCache(useLocalCache);
|
|
|
|
nsCOMPtr<nsIURI> url = do_QueryInterface(imapUrl);
|
|
url->GetSpec(urlSpec);
|
|
urlSpec.Append("fetch>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(folder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(msgKey);
|
|
rv = url->SetSpec(urlSpec);
|
|
imapUrl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::OpenAttachment(const char *aContentType,
|
|
const char *aFileName,
|
|
const char *aUrl,
|
|
const char *aMessageUri,
|
|
nsISupports *aDisplayConsumer,
|
|
nsIMsgWindow *aMsgWindow,
|
|
nsIUrlListener *aUrlListener)
|
|
{
|
|
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;
|
|
uri += "&filename=";
|
|
uri += aFileName;
|
|
}
|
|
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;
|
|
uri += "&filename=";
|
|
uri += aFileName;
|
|
}
|
|
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
nsXPIDLCString uriMimePart;
|
|
nsCAutoString folderURI;
|
|
nsMsgKey key;
|
|
|
|
rv = DecomposeImapURI(uri.get(), getter_AddRefs(folder), getter_Copies(msgKey));
|
|
rv = nsParseImapMessageURI(uri.get(), folderURI, &key, getter_Copies(uriMimePart));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(uri.get(), getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
urlSpec.Append("/fetch>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(folder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(msgKey.get());
|
|
urlSpec.Append(uriMimePart.get());
|
|
|
|
if (uriMimePart)
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailUrl (do_QueryInterface(imapUrl));
|
|
if (mailUrl)
|
|
{
|
|
mailUrl->SetSpec(urlSpec);
|
|
mailUrl->SetFileName(nsDependentCString(aFileName));
|
|
}
|
|
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;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::FetchMimePart(nsIURI *aURI, const char *aMessageURI, nsISupports *aDisplayConsumer, nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIURI **aURL)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
nsXPIDLCString mimePart;
|
|
nsCAutoString folderURI;
|
|
nsMsgKey key;
|
|
|
|
rv = DecomposeImapURI(aMessageURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
rv = nsParseImapMessageURI(aMessageURI, folderURI, &key, getter_Copies(mimePart));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(aURI);
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(aURI));
|
|
|
|
msgurl->SetMsgWindow(aMsgWindow);
|
|
msgurl->RegisterListener(aUrlListener);
|
|
|
|
if (mimePart)
|
|
{
|
|
return FetchMimePart(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
|
|
aURL, aDisplayConsumer, msgKey, mimePart);
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::DisplayMessage(const char* aMessageURI,
|
|
nsISupports * aDisplayConsumer,
|
|
nsIMsgWindow * aMsgWindow,
|
|
nsIUrlListener * aUrlListener,
|
|
const char * aCharsetOverride,
|
|
nsIURI ** aURL)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
nsXPIDLCString mimePart;
|
|
nsCAutoString folderURI;
|
|
nsMsgKey key;
|
|
nsCAutoString messageURI(aMessageURI);
|
|
|
|
PRInt32 typeIndex = messageURI.Find("&type=application/x-message-display");
|
|
if (typeIndex != kNotFound)
|
|
{
|
|
// This happens with forward inline of a message/rfc822 attachment opened in
|
|
// a standalone msg window.
|
|
// So, just cut to the chase and call AsyncOpen on a channel.
|
|
nsCOMPtr <nsIURI> uri;
|
|
messageURI.Cut(typeIndex, sizeof("&type=application/x-message-display") - 1);
|
|
rv = NS_NewURI(getter_AddRefs(uri), messageURI.get());
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (aURL)
|
|
NS_IF_ADDREF(*aURL = uri);
|
|
nsCOMPtr<nsIStreamListener> aStreamListener = do_QueryInterface(aDisplayConsumer, &rv);
|
|
if (NS_SUCCEEDED(rv) && aStreamListener)
|
|
{
|
|
nsCOMPtr<nsIChannel> aChannel;
|
|
nsCOMPtr<nsILoadGroup> aLoadGroup;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(uri, &rv);
|
|
if (NS_SUCCEEDED(rv) && mailnewsUrl)
|
|
mailnewsUrl->GetLoadGroup(getter_AddRefs(aLoadGroup));
|
|
|
|
rv = NewChannel(uri, getter_AddRefs(aChannel));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsISupports> aCtxt = do_QueryInterface(uri);
|
|
// now try to open the channel passing in our display consumer as the listener
|
|
return aChannel->AsyncOpen(aStreamListener, aCtxt);
|
|
}
|
|
}
|
|
rv = DecomposeImapURI(aMessageURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
if (msgKey.IsEmpty())
|
|
return NS_MSG_MESSAGE_NOT_FOUND;
|
|
rv = nsParseImapMessageURI(aMessageURI, folderURI, &key, getter_Copies(mimePart));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(aMessageURI, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (mimePart)
|
|
{
|
|
return FetchMimePart(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
|
|
aURL, aDisplayConsumer, msgKey, mimePart);
|
|
}
|
|
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
|
|
nsCOMPtr<nsIMsgI18NUrl> i18nurl (do_QueryInterface(imapUrl));
|
|
i18nurl->SetCharsetOverRide(aCharsetOverride);
|
|
|
|
PRUint32 messageSize;
|
|
PRBool useMimePartsOnDemand = gMIMEOnDemand;
|
|
PRBool shouldStoreMsgOffline = PR_FALSE;
|
|
PRBool hasMsgOffline = PR_FALSE;
|
|
|
|
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
|
|
|
if (imapMessageSink)
|
|
imapMessageSink->GetMessageSizeFromDB(msgKey, PR_TRUE, &messageSize);
|
|
|
|
msgurl->SetMsgWindow(aMsgWindow);
|
|
|
|
rv = msgurl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
|
|
|
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
|
{
|
|
nsCOMPtr<nsIImapIncomingServer>
|
|
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
|
if (NS_SUCCEEDED(rv) && aImapServer)
|
|
aImapServer->GetMimePartsOnDemand(&useMimePartsOnDemand);
|
|
}
|
|
|
|
nsCAutoString uriStr(aMessageURI);
|
|
PRInt32 keySeparator = uriStr.RFindChar('#');
|
|
if(keySeparator != -1)
|
|
{
|
|
PRInt32 keyEndSeparator = uriStr.FindCharInSet("/?&",
|
|
keySeparator);
|
|
PRInt32 mpodFetchPos = uriStr.Find("fetchCompleteMessage=true", PR_FALSE, keyEndSeparator);
|
|
if (mpodFetchPos != -1)
|
|
useMimePartsOnDemand = PR_FALSE;
|
|
}
|
|
|
|
if (folder)
|
|
{
|
|
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
|
|
folder->HasMsgOffline(key, &hasMsgOffline);
|
|
}
|
|
|
|
if (!useMimePartsOnDemand || (messageSize < (uint32) gMIMEOnDemandThreshold))
|
|
// allowedToBreakApart &&
|
|
// !GetShouldFetchAllParts() &&
|
|
// GetServerStateParser().ServerHasIMAP4Rev1Capability() &&
|
|
{
|
|
imapUrl->SetFetchPartsOnDemand(PR_FALSE);
|
|
// for now, lets try not adding these
|
|
msgurl->SetAddToMemoryCache(PR_TRUE);
|
|
}
|
|
else
|
|
{
|
|
// whenever we are displaying a message, we want to add it to the memory cache..
|
|
imapUrl->SetFetchPartsOnDemand(PR_TRUE);
|
|
// if we happen to fetch the whole message, note in the url
|
|
// whether we want to store this message offline.
|
|
imapUrl->SetShouldStoreMsgOffline(shouldStoreMsgOffline);
|
|
shouldStoreMsgOffline = PR_FALSE; // if we're fetching by parts, don't store offline
|
|
msgurl->SetAddToMemoryCache(PR_FALSE);
|
|
}
|
|
if (imapMessageSink && !hasMsgOffline)
|
|
imapMessageSink->SetNotifyDownloadedLines(shouldStoreMsgOffline);
|
|
|
|
if (hasMsgOffline)
|
|
msgurl->SetMsgIsInLocalCache(PR_TRUE);
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
|
PRBool forcePeek = PR_FALSE; // should the message fetch force a peak or a traditional fetch?
|
|
|
|
if (NS_SUCCEEDED(rv) && prefBranch)
|
|
prefBranch->GetBoolPref("mailnews.mark_message_read.delay", &forcePeek);
|
|
|
|
rv = FetchMessage(imapUrl, forcePeek ? nsIImapUrl::nsImapMsgFetchPeek : nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
|
|
aMsgWindow, aDisplayConsumer, msgKey, PR_FALSE, (mPrintingOperation) ? "print" : nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsresult nsImapService::FetchMimePart(nsIImapUrl * aImapUrl,
|
|
nsImapAction aImapAction,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIImapMessageSink * aImapMessage,
|
|
nsIURI ** aURL,
|
|
nsISupports * aDisplayConsumer,
|
|
const char *messageIdentifierList,
|
|
const char *mimePart)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// 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;
|
|
|
|
nsCAutoString urlSpec;
|
|
rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
|
nsImapAction actionToUse = aImapAction;
|
|
if (actionToUse == nsImapUrl::nsImapOpenMimePart)
|
|
actionToUse = nsIImapUrl::nsImapMsgFetch;
|
|
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(aImapUrl));
|
|
if (aImapMailFolder && msgurl && messageIdentifierList)
|
|
{
|
|
PRBool useLocalCache = PR_FALSE;
|
|
aImapMailFolder->HasMsgOffline(atoi(messageIdentifierList), &useLocalCache);
|
|
msgurl->SetMsgIsInLocalCache(useLocalCache);
|
|
}
|
|
rv = aImapUrl->SetImapMessageSink(aImapMessage);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> url = do_QueryInterface(aImapUrl);
|
|
url->GetSpec(urlSpec);
|
|
|
|
// rhp: If we are displaying this message for the purpose of printing, we
|
|
// need to append the header=print option.
|
|
//
|
|
if (mPrintingOperation)
|
|
urlSpec.Append("?header=print");
|
|
|
|
// mscott - this cast to a char * is okay...there's a bug in the XPIDL
|
|
// compiler that is preventing in string parameters from showing up as
|
|
// const char *. hopefully they will fix it soon.
|
|
rv = url->SetSpec(urlSpec);
|
|
|
|
rv = aImapUrl->SetImapAction(actionToUse /* nsIImapUrl::nsImapMsgFetch */);
|
|
if (aImapMailFolder && aDisplayConsumer)
|
|
{
|
|
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
|
rv = aImapMailFolder->GetServer(getter_AddRefs(aMsgIncomingServer));
|
|
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
|
{
|
|
PRBool interrupted;
|
|
nsCOMPtr<nsIImapIncomingServer>
|
|
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
|
if (NS_SUCCEEDED(rv) && aImapServer)
|
|
aImapServer->PseudoInterruptMsgLoad(aImapMailFolder, nsnull, &interrupted);
|
|
}
|
|
}
|
|
// if the display consumer is a docshell, then we should run the url in the docshell.
|
|
// otherwise, it should be a stream listener....so open a channel using AsyncRead
|
|
// and the provided stream listener....
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
|
|
if (NS_SUCCEEDED(rv) && docShell)
|
|
{
|
|
nsCOMPtr<nsIDocShellLoadInfo> 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, nsIWebNavigation::LOAD_FLAGS_NONE, PR_FALSE);
|
|
}
|
|
else
|
|
{
|
|
nsCOMPtr<nsIStreamListener> aStreamListener = do_QueryInterface(aDisplayConsumer, &rv);
|
|
if (NS_SUCCEEDED(rv) && aStreamListener)
|
|
{
|
|
nsCOMPtr<nsIChannel> aChannel;
|
|
nsCOMPtr<nsILoadGroup> aLoadGroup;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl, &rv);
|
|
if (NS_SUCCEEDED(rv) && mailnewsUrl)
|
|
mailnewsUrl->GetLoadGroup(getter_AddRefs(aLoadGroup));
|
|
|
|
rv = NewChannel(url, getter_AddRefs(aChannel));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsISupports> aCtxt = do_QueryInterface(url);
|
|
// now try to open the channel passing in our display consumer as the listener
|
|
rv = aChannel->AsyncOpen(aStreamListener, aCtxt);
|
|
}
|
|
else // do what we used to do before
|
|
{
|
|
// I'd like to get rid of this code as I believe that we always get a docshell
|
|
// or stream listener passed into us in this method but i'm not sure yet...
|
|
// I'm going to use an assert for now to figure out if this is ever getting called
|
|
#if defined(DEBUG_mscott) || defined(DEBUG_bienvenu)
|
|
NS_ASSERTION(0, "oops...someone still is reaching this part of the code");
|
|
#endif
|
|
nsCOMPtr<nsIEventQueue> queue;
|
|
// get the Event Queue for this thread...
|
|
nsCOMPtr<nsIEventQueueService> pEventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL);
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
//
|
|
// rhp: Right now, this is the same as simple DisplayMessage, but it will change
|
|
// to support print rendering.
|
|
//
|
|
NS_IMETHODIMP nsImapService::DisplayMessageForPrinting(const char* aMessageURI,
|
|
nsISupports * aDisplayConsumer,
|
|
nsIMsgWindow * aMsgWindow,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
mPrintingOperation = PR_TRUE;
|
|
nsresult rv = DisplayMessage(aMessageURI, aDisplayConsumer, aMsgWindow, aUrlListener, nsnull, aURL);
|
|
mPrintingOperation = PR_FALSE;
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::CopyMessage(const char * aSrcMailboxURI, nsIStreamListener *
|
|
aMailboxCopy, PRBool moveMessage,
|
|
nsIUrlListener * aUrlListener, nsIMsgWindow *aMsgWindow, nsIURI **aURL)
|
|
{
|
|
nsresult rv = NS_ERROR_NULL_POINTER;
|
|
nsCOMPtr<nsISupports> streamSupport;
|
|
if (!aSrcMailboxURI || !aMailboxCopy) return rv;
|
|
streamSupport = do_QueryInterface(aMailboxCopy, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
rv = DecomposeImapURI(aSrcMailboxURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
PRBool hasMsgOffline = PR_FALSE;
|
|
nsMsgKey key = atoi(msgKey);
|
|
|
|
rv = CreateStartOfImapUrl(aSrcMailboxURI, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
|
|
if (folder)
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
|
|
folder->HasMsgOffline(key, &hasMsgOffline);
|
|
if (msgurl)
|
|
msgurl->SetMsgIsInLocalCache(hasMsgOffline);
|
|
}
|
|
// now try to download the message
|
|
nsImapAction imapAction = nsIImapUrl::nsImapOnlineToOfflineCopy;
|
|
if (moveMessage)
|
|
imapAction = nsIImapUrl::nsImapOnlineToOfflineMove;
|
|
rv = FetchMessage(imapUrl,imapAction, folder, imapMessageSink,aMsgWindow, streamSupport, msgKey, PR_FALSE, nsnull, aURL);
|
|
} // if we got an imap message sink
|
|
} // if we decomposed the imap message
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::CopyMessages(nsMsgKeyArray *keys, nsIMsgFolder *srcFolder, nsIStreamListener *aMailboxCopy, PRBool moveMessage,
|
|
nsIUrlListener * aUrlListener, nsIMsgWindow *aMsgWindow, nsIURI **aURL)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsISupports> streamSupport;
|
|
if (!keys || !aMailboxCopy)
|
|
return NS_ERROR_NULL_POINTER;
|
|
streamSupport = do_QueryInterface(aMailboxCopy, &rv);
|
|
if (!streamSupport || NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIMsgFolder> folder = srcFolder;
|
|
nsXPIDLCString msgKey;
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
// we generate the uri for the first message so that way on down the line,
|
|
// GetMessage in nsCopyMessageStreamListener will get an unescaped username
|
|
// and be able to find the msg hdr. See bug 259656 for details
|
|
nsXPIDLCString uri;
|
|
srcFolder->GenerateMessageURI(keys->GetAt(0), getter_Copies(uri));
|
|
|
|
nsCString messageIds;
|
|
PRUint32 numKeys = keys->GetSize();
|
|
AllocateImapUidString(keys->GetArray(), numKeys, nsnull, messageIds);
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(uri, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
nsImapAction action;
|
|
if (moveMessage)
|
|
action = nsIImapUrl::nsImapOnlineToOfflineMove;
|
|
else
|
|
action = nsIImapUrl::nsImapOnlineToOfflineCopy;
|
|
imapUrl->SetCopyState(aMailboxCopy);
|
|
// now try to display the message
|
|
rv = FetchMessage(imapUrl, action, folder, imapMessageSink,
|
|
aMsgWindow, streamSupport, messageIds.get(), PR_FALSE, nsnull, aURL);
|
|
// ### end of copy operation should know how to do the delete.if this is a move
|
|
|
|
} // if we got an imap message sink
|
|
} // if we decomposed the imap message
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::Search(nsIMsgSearchSession *aSearchSession, nsIMsgWindow *aMsgWindow, nsIMsgFolder *aMsgFolder, const char *aSearchUri)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCAutoString folderURI;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCOMPtr <nsIUrlListener> urlListener = do_QueryInterface(aSearchSession);
|
|
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aMsgFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aMsgFolder, urlListener, urlSpec, hierarchySeparator);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
|
|
|
|
msgurl->SetMsgWindow(aMsgWindow);
|
|
msgurl->SetSearchSession(aSearchSession);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
rv = SetImapUrlSink(aMsgFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aMsgFolder, getter_Copies(folderName));
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
if (!aMsgWindow)
|
|
mailNewsUrl->SetSuppressErrorMsgs(PR_TRUE);
|
|
|
|
urlSpec.Append("/search>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append('>');
|
|
// escape aSearchUri so that IMAP special characters (i.e. '\')
|
|
// won't be replaced with '/' in NECKO.
|
|
// it will be unescaped in nsImapUrl::ParseUrl().
|
|
char *search_cmd = nsEscape((char *)aSearchUri, url_XAlphas);
|
|
urlSpec.Append(search_cmd);
|
|
nsCRT::free(search_cmd);
|
|
rv = mailNewsUrl->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIEventQueue> queue;
|
|
// get the Event Queue for this thread...
|
|
nsCOMPtr<nsIEventQueueService> pEventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = GetImapConnectionAndLoadUrl(queue, imapUrl, nsnull, nsnull);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// just a helper method to break down imap message URIs....
|
|
nsresult nsImapService::DecomposeImapURI(const char * aMessageURI, nsIMsgFolder ** aFolder, nsMsgKey *aMsgKey)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aMessageURI);
|
|
NS_ENSURE_ARG_POINTER(aFolder);
|
|
NS_ENSURE_ARG_POINTER(aMsgKey);
|
|
|
|
nsresult rv = NS_OK;
|
|
nsCAutoString folderURI;
|
|
rv = nsParseImapMessageURI(aMessageURI, folderURI, aMsgKey, nsnull);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
nsCOMPtr <nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1",&rv);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
nsCOMPtr<nsIRDFResource> res;
|
|
rv = rdf->GetResource(folderURI, getter_AddRefs(res));
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
rv = res->QueryInterface(NS_GET_IID(nsIMsgFolder), (void **) aFolder);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// just a helper method to break down imap message URIs....
|
|
nsresult nsImapService::DecomposeImapURI(const char * aMessageURI, nsIMsgFolder ** aFolder, char ** aMsgKey)
|
|
{
|
|
nsMsgKey msgKey;
|
|
nsresult rv;
|
|
rv = DecomposeImapURI(aMessageURI, aFolder, &msgKey);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
if (msgKey) {
|
|
nsCAutoString messageIdString;
|
|
messageIdString.AppendInt(msgKey);
|
|
*aMsgKey = ToNewCString(messageIdString);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::SaveMessageToDisk(const char *aMessageURI,
|
|
nsIFileSpec *aFile,
|
|
PRBool aAddDummyEnvelope,
|
|
nsIUrlListener *aUrlListener,
|
|
nsIURI **aURL,
|
|
PRBool canonicalLineEnding,
|
|
nsIMsgWindow *aMsgWindow)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsXPIDLCString msgKey;
|
|
|
|
rv = DecomposeImapURI(aMessageURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRBool hasMsgOffline = PR_FALSE;
|
|
|
|
if (folder)
|
|
folder->HasMsgOffline(atoi(msgKey), &hasMsgOffline);
|
|
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(aMessageURI, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIMsgMessageUrl> msgUrl = do_QueryInterface(imapUrl, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
msgUrl->SetMessageFile(aFile);
|
|
msgUrl->SetAddDummyEnvelope(aAddDummyEnvelope);
|
|
msgUrl->SetCanonicalLineEnding(canonicalLineEnding);
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(msgUrl);
|
|
if (mailnewsUrl)
|
|
mailnewsUrl->SetMsgIsInLocalCache(hasMsgOffline);
|
|
|
|
nsCOMPtr <nsIStreamListener> saveAsListener;
|
|
mailnewsUrl->GetSaveAsListener(aAddDummyEnvelope, aFile, getter_AddRefs(saveAsListener));
|
|
|
|
return FetchMessage(imapUrl, nsIImapUrl::nsImapSaveMessageToDisk, folder, imapMessageSink, aMsgWindow, saveAsListener, msgKey, PR_FALSE, nsnull, aURL);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* fetching RFC822 messages */
|
|
/* imap4://HOST>fetch><UID>>MAILBOXPATH>x */
|
|
/* 'x' is the message UID */
|
|
/* will set the 'SEEN' flag */
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::FetchMessage(nsIImapUrl * aImapUrl,
|
|
nsImapAction aImapAction,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIImapMessageSink * aImapMessage,
|
|
nsIMsgWindow *aMsgWindow,
|
|
nsISupports * aDisplayConsumer,
|
|
const char *messageIdentifierList,
|
|
PRBool aConvertDataToText,
|
|
const char *aAdditionalHeader,
|
|
nsIURI ** aURL)
|
|
{
|
|
// create a protocol instance to handle the request.
|
|
NS_ASSERTION (aImapUrl && aImapMailFolder && aImapMessage,"Oops ... null pointer");
|
|
if (!aImapUrl || !aImapMailFolder || !aImapMessage)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIURI> url = do_QueryInterface(aImapUrl);
|
|
if (WeAreOffline())
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(aImapUrl));
|
|
if (msgurl)
|
|
{
|
|
PRBool msgIsInLocalCache = PR_FALSE;
|
|
msgurl->GetMsgIsInLocalCache(&msgIsInLocalCache);
|
|
if (!msgIsInLocalCache)
|
|
{
|
|
nsCOMPtr<nsIMsgIncomingServer> server;
|
|
|
|
rv = aImapMailFolder->GetServer(getter_AddRefs(server));
|
|
if (server && aDisplayConsumer)
|
|
rv = server->DisplayOfflineMsg(aMsgWindow);
|
|
return rv;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aURL)
|
|
{
|
|
*aURL = url;
|
|
NS_IF_ADDREF(*aURL);
|
|
}
|
|
nsCAutoString urlSpec;
|
|
rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
|
|
|
rv = aImapUrl->SetImapMessageSink(aImapMessage);
|
|
url->GetSpec(urlSpec);
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
|
|
urlSpec.Append("fetch>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(messageIdentifierList);
|
|
|
|
if (aAdditionalHeader)
|
|
{
|
|
urlSpec.Append("?header=");
|
|
urlSpec.Append(aAdditionalHeader);
|
|
}
|
|
|
|
rv = url->SetSpec(urlSpec);
|
|
|
|
rv = aImapUrl->SetImapAction(aImapAction);
|
|
// if the display consumer is a docshell, then we should run the url in the docshell.
|
|
// otherwise, it should be a stream listener....so open a channel using AsyncRead
|
|
// and the provided stream listener....
|
|
|
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
|
|
if (aImapMailFolder && docShell)
|
|
{
|
|
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
|
rv = aImapMailFolder->GetServer(getter_AddRefs(aMsgIncomingServer));
|
|
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
|
{
|
|
PRBool interrupted;
|
|
nsCOMPtr<nsIImapIncomingServer>
|
|
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
|
if (NS_SUCCEEDED(rv) && aImapServer)
|
|
aImapServer->PseudoInterruptMsgLoad(aImapMailFolder, aMsgWindow, &interrupted);
|
|
}
|
|
}
|
|
if (NS_SUCCEEDED(rv) && docShell)
|
|
{
|
|
NS_ASSERTION(!aConvertDataToText, "can't convert to text when using docshell");
|
|
rv = docShell->LoadURI(url, nsnull, nsIWebNavigation::LOAD_FLAGS_NONE, PR_FALSE);
|
|
}
|
|
else
|
|
{
|
|
nsCOMPtr<nsIStreamListener> streamListener = do_QueryInterface(aDisplayConsumer, &rv);
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl, &rv);
|
|
if (aMsgWindow && mailnewsUrl)
|
|
mailnewsUrl->SetMsgWindow(aMsgWindow);
|
|
if (NS_SUCCEEDED(rv) && streamListener)
|
|
{
|
|
nsCOMPtr<nsIChannel> channel;
|
|
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
if (NS_SUCCEEDED(rv) && mailnewsUrl)
|
|
mailnewsUrl->GetLoadGroup(getter_AddRefs(loadGroup));
|
|
|
|
rv = NewChannel(url, getter_AddRefs(channel));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = channel->SetLoadGroup(loadGroup);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (aConvertDataToText)
|
|
{
|
|
nsCOMPtr<nsIStreamListener> conversionListener;
|
|
nsCOMPtr<nsIStreamConverterService> streamConverter = do_GetService("@mozilla.org/streamConverters;1", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = streamConverter->AsyncConvertData("message/rfc822",
|
|
"*/*",
|
|
streamListener, channel, getter_AddRefs(conversionListener));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
streamListener = conversionListener; // this is our new listener.
|
|
}
|
|
nsCOMPtr<nsISupports> aCtxt = do_QueryInterface(url);
|
|
// now try to open the channel passing in our display consumer as the listener
|
|
rv = channel->AsyncOpen(streamListener, aCtxt);
|
|
}
|
|
else // do what we used to do before
|
|
{
|
|
// I'd like to get rid of this code as I believe that we always get a docshell
|
|
// or stream listener passed into us in this method but i'm not sure yet...
|
|
// I'm going to use an assert for now to figure out if this is ever getting called
|
|
#if defined(DEBUG_mscott) || defined(DEBUG_bienvenu)
|
|
NS_ASSERTION(0, "oops...someone still is reaching this part of the code");
|
|
#endif
|
|
nsCOMPtr<nsIEventQueue> queue;
|
|
// get the Event Queue for this thread...
|
|
nsCOMPtr<nsIEventQueueService> pEventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// this method streams a message to the passed in consumer, with an optional stream converter
|
|
// and additional header (e.g., "header=filter")
|
|
NS_IMETHODIMP
|
|
nsImapService::StreamMessage(const char *aMessageURI, nsISupports *aConsumer,
|
|
nsIMsgWindow *aMsgWindow,
|
|
nsIUrlListener *aUrlListener,
|
|
PRBool aConvertData,
|
|
const char *aAdditionalHeader,
|
|
nsIURI **aURL)
|
|
{
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsXPIDLCString msgKey;
|
|
nsXPIDLCString mimePart;
|
|
nsCAutoString folderURI;
|
|
nsMsgKey key;
|
|
|
|
nsresult rv = DecomposeImapURI(aMessageURI, getter_AddRefs(folder), getter_Copies(msgKey));
|
|
if (msgKey.IsEmpty())
|
|
return NS_MSG_MESSAGE_NOT_FOUND;
|
|
rv = nsParseImapMessageURI(aMessageURI, folderURI, &key, getter_Copies(mimePart));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(folder, &rv));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(aMessageURI, getter_AddRefs(imapUrl), folder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
|
|
|
|
PRBool shouldStoreMsgOffline = PR_FALSE;
|
|
PRBool hasMsgOffline = PR_FALSE;
|
|
|
|
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
|
|
|
msgurl->SetMsgWindow(aMsgWindow);
|
|
|
|
rv = msgurl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
|
|
|
if (folder)
|
|
{
|
|
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
|
|
folder->HasMsgOffline(key, &hasMsgOffline);
|
|
}
|
|
|
|
imapUrl->SetFetchPartsOnDemand(PR_FALSE);
|
|
msgurl->SetAddToMemoryCache(PR_TRUE);
|
|
if (imapMessageSink)
|
|
imapMessageSink->SetNotifyDownloadedLines(shouldStoreMsgOffline);
|
|
|
|
if (hasMsgOffline)
|
|
msgurl->SetMsgIsInLocalCache(PR_TRUE);
|
|
|
|
rv = FetchMessage(imapUrl, nsIImapUrl::nsImapMsgFetchPeek, folder, imapMessageSink,
|
|
aMsgWindow, aConsumer, msgKey, aConvertData, aAdditionalHeader, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsImapService::CreateStartOfImapUrl(const char * aImapURI, nsIImapUrl ** imapUrl,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsCString & urlSpec,
|
|
PRUnichar &hierarchyDelimiter)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
char *hostname = nsnull;
|
|
nsXPIDLCString username;
|
|
nsXPIDLCString escapedUsername;
|
|
|
|
rv = aImapMailFolder->GetHostname(&hostname);
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = aImapMailFolder->GetUsername(getter_Copies(username));
|
|
if (NS_FAILED(rv))
|
|
{
|
|
PR_Free(hostname);
|
|
return rv;
|
|
}
|
|
|
|
if (((const char*)username) && username[0])
|
|
*((char **)getter_Copies(escapedUsername)) = nsEscape(username, url_XAlphas);
|
|
|
|
PRInt32 port = IMAP_PORT;
|
|
nsCOMPtr<nsIMsgIncomingServer> server;
|
|
rv = aImapMailFolder->GetServer(getter_AddRefs(server));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
server->GetPort(&port);
|
|
if (port == -1 || port == 0) port = IMAP_PORT;
|
|
}
|
|
|
|
// now we need to create an imap url to load into the connection. The url
|
|
// needs to represent a select folder action.
|
|
rv = CallCreateInstance(kImapUrlCID, imapUrl);
|
|
if (NS_SUCCEEDED(rv) && *imapUrl)
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(*imapUrl, &rv);
|
|
if (NS_SUCCEEDED(rv) && mailnewsUrl && aUrlListener)
|
|
mailnewsUrl->RegisterListener(aUrlListener);
|
|
nsCOMPtr<nsIMsgMessageUrl> msgurl(do_QueryInterface(*imapUrl));
|
|
(*imapUrl)->SetExternalLinkUrl(PR_FALSE);
|
|
msgurl->SetUri(aImapURI);
|
|
|
|
urlSpec = "imap://";
|
|
urlSpec.Append((const char *) escapedUsername);
|
|
urlSpec.Append('@');
|
|
urlSpec.Append(hostname);
|
|
urlSpec.Append(':');
|
|
|
|
urlSpec.AppendInt(port);
|
|
|
|
// *** jefft - force to parse the urlSpec in order to search for
|
|
// the correct incoming server
|
|
// mscott - this cast to a char * is okay...there's a bug in the XPIDL
|
|
// compiler that is preventing in string parameters from showing up as
|
|
// const char *. hopefully they will fix it soon.
|
|
rv = mailnewsUrl->SetSpec(urlSpec);
|
|
|
|
hierarchyDelimiter = kOnlineHierarchySeparatorUnknown;
|
|
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(aImapMailFolder);
|
|
if (imapFolder)
|
|
imapFolder->GetHierarchyDelimiter(&hierarchyDelimiter);
|
|
}
|
|
|
|
PR_Free(hostname);
|
|
return rv;
|
|
}
|
|
|
|
/* fetching the headers of RFC822 messages */
|
|
/* imap4://HOST>header><UID/SEQUENCE>>MAILBOXPATH>x */
|
|
/* 'x' is the message UID or sequence number list */
|
|
/* will not affect the 'SEEN' flag */
|
|
NS_IMETHODIMP
|
|
nsImapService::GetHeaders(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
// 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 (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),aImapMailFolder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
|
|
urlSpec.Append("/header>");
|
|
urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(char (hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(messageIdentifierList);
|
|
rv = uri->SetSpec(urlSpec);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
/* peeking at the start of msg bodies */
|
|
/* imap4://HOST>header><UID>>MAILBOXPATH>x>n */
|
|
/* 'x' is the message UID */
|
|
/* 'n' is the number of bytes to fetch */
|
|
/* will not affect the 'SEEN' flag */
|
|
NS_IMETHODIMP
|
|
nsImapService::GetBodyStart(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
const char *messageIdentifierList,
|
|
PRInt32 numBytes,
|
|
nsIURI ** aURL)
|
|
{
|
|
nsresult rv;
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgPreview);
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
urlSpec.Append("/previewBody>");
|
|
urlSpec.Append(uidString);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(char (hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(messageIdentifierList);
|
|
urlSpec.Append(">");
|
|
urlSpec.AppendInt(numBytes);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsImapService::FolderCommand(nsIEventQueue * clientEventQueue,
|
|
nsIMsgFolder * imapMailFolder,
|
|
nsIUrlListener * urlListener,
|
|
const char *command,
|
|
nsImapAction imapAction,
|
|
nsIURI ** url)
|
|
{
|
|
NS_ASSERTION (imapMailFolder && clientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!imapMailFolder || !clientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(imapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
imapMailFolder,
|
|
urlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
|
|
rv = imapUrl->SetImapAction(imapAction);
|
|
rv = SetImapUrlSink(imapMailFolder, imapUrl);
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
urlSpec.Append(command);
|
|
urlSpec.Append(char (hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
GetFolderName(imapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(clientEventQueue, imapUrl,
|
|
nsnull, url);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// Noop, used to update a folder (causes server to send changes).
|
|
NS_IMETHODIMP
|
|
nsImapService::Noop(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/selectnoop>", nsIImapUrl::nsImapSelectNoopFolder, aURL);
|
|
}
|
|
|
|
// FolderStatus, used to update message counts
|
|
NS_IMETHODIMP
|
|
nsImapService::UpdateFolderStatus(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/folderstatus>", nsIImapUrl::nsImapFolderStatus, aURL);
|
|
}
|
|
|
|
// Expunge, used to "compress" an imap folder,removes deleted messages.
|
|
NS_IMETHODIMP
|
|
nsImapService::Expunge(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/Expunge>", nsIImapUrl::nsImapExpungeFolder, aURL);
|
|
}
|
|
|
|
/* old-stle biff that doesn't download headers */
|
|
NS_IMETHODIMP
|
|
nsImapService::Biff(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
PRUint32 uidHighWater)
|
|
{
|
|
// static const char *formatString = "biff>%c%s>%ld";
|
|
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapExpungeFolder);
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
urlSpec.Append("/Biff>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.AppendInt(uidHighWater);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DeleteFolder(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener* aUrlListener,
|
|
nsIURI** aURL)
|
|
{
|
|
|
|
// If it's an aol server then use 'deletefolder' url to
|
|
// remove all msgs first and then remove the folder itself.
|
|
PRBool removeFolderAndMsgs = PR_FALSE;
|
|
nsCOMPtr<nsIMsgIncomingServer> server;
|
|
if (NS_SUCCEEDED(aImapMailFolder->GetServer(getter_AddRefs(server))) && server)
|
|
{
|
|
nsCOMPtr <nsIImapIncomingServer> imapServer = do_QueryInterface(server);
|
|
if (imapServer)
|
|
imapServer->GetIsAOLServer(&removeFolderAndMsgs);
|
|
}
|
|
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
removeFolderAndMsgs ? "/deletefolder>": "/delete>",
|
|
nsIImapUrl::nsImapDeleteFolder, aURL);
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DeleteMessages(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
nsresult rv;
|
|
// 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 (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
urlSpec.Append("/deletemsg>");
|
|
urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(char (hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(messageIdentifierList);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
// Delete all messages in a folder, used to empty trash
|
|
NS_IMETHODIMP
|
|
nsImapService::DeleteAllMessages(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/deleteallmsgs>", nsIImapUrl::nsImapSelectNoopFolder, aURL);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::AddMessageFlags(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
imapMessageFlagsType flags,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList,
|
|
"addmsgflags", flags, messageIdsAreUID);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::SubtractMessageFlags(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
imapMessageFlagsType flags,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList,
|
|
"subtractmsgflags", flags, messageIdsAreUID);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::SetMessageFlags(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
imapMessageFlagsType flags,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
return DiddleFlags(aClientEventQueue, aImapMailFolder, aUrlListener, aURL, messageIdentifierList,
|
|
"setmsgflags", flags, messageIdsAreUID);
|
|
}
|
|
|
|
nsresult nsImapService::DiddleFlags(nsIEventQueue * aClientEventQueue,
|
|
nsIMsgFolder * aImapMailFolder,
|
|
nsIUrlListener * aUrlListener,
|
|
nsIURI ** aURL,
|
|
const char *messageIdentifierList,
|
|
const char *howToDiddle,
|
|
imapMessageFlagsType flags,
|
|
PRBool messageIdsAreUID)
|
|
{
|
|
// 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 (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null pointer");
|
|
if (!aImapMailFolder || !aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgFetch);
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
urlSpec.Append('/');
|
|
urlSpec.Append(howToDiddle);
|
|
urlSpec.Append('>');
|
|
urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(messageIdentifierList);
|
|
urlSpec.Append('>');
|
|
urlSpec.AppendInt(flags);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsImapService::SetImapUrlSink(nsIMsgFolder* aMsgFolder,
|
|
nsIImapUrl* aImapUrl)
|
|
{
|
|
nsresult rv = NS_ERROR_NULL_POINTER;
|
|
nsISupports* aInst = nsnull;
|
|
nsCOMPtr <nsIMsgIncomingServer> incomingServer;
|
|
nsCOMPtr <nsIImapServerSink> imapServerSink;
|
|
|
|
NS_ASSERTION (aMsgFolder && aImapUrl, "Oops ... null pointers");
|
|
if (!aMsgFolder || !aImapUrl)
|
|
return rv;
|
|
|
|
rv = aMsgFolder->GetServer(getter_AddRefs(incomingServer));
|
|
if (NS_SUCCEEDED(rv) && incomingServer)
|
|
{
|
|
imapServerSink = do_QueryInterface(incomingServer);
|
|
if (imapServerSink)
|
|
aImapUrl->SetImapServerSink(imapServerSink);
|
|
}
|
|
|
|
rv = aMsgFolder->QueryInterface(NS_GET_IID(nsIImapMailFolderSink),
|
|
(void**)&aInst);
|
|
if (NS_SUCCEEDED(rv) && aInst)
|
|
aImapUrl->SetImapMailFolderSink((nsIImapMailFolderSink*) aInst);
|
|
NS_IF_RELEASE (aInst);
|
|
aInst = nsnull;
|
|
|
|
rv = aMsgFolder->QueryInterface(NS_GET_IID(nsIImapMessageSink),
|
|
(void**)&aInst);
|
|
if (NS_SUCCEEDED(rv) && aInst)
|
|
aImapUrl->SetImapMessageSink((nsIImapMessageSink*) aInst);
|
|
NS_IF_RELEASE (aInst);
|
|
aInst = nsnull;
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl);
|
|
mailnewsUrl->SetFolder(aMsgFolder);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DiscoverAllFolders(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener* aUrlListener,
|
|
nsIMsgWindow * aMsgWindow,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null aClientEventQueue or aImapMailFolder");
|
|
if (!aImapMailFolder || ! aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED (rv))
|
|
{
|
|
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(imapUrl);
|
|
if (mailnewsurl)
|
|
mailnewsurl->SetMsgWindow(aMsgWindow);
|
|
urlSpec.Append("/discoverallboxes");
|
|
nsCOMPtr <nsIURI> url = do_QueryInterface(imapUrl, &rv);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DiscoverAllAndSubscribedFolders(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener* aUrlListener,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null aClientEventQueue or aImapMailFolder");
|
|
if (!aImapMailFolder || ! aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> aImapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(aImapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED (rv) && aImapUrl)
|
|
{
|
|
rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(aImapUrl);
|
|
|
|
urlSpec.Append("/discoverallandsubscribedboxes");
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, aImapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DiscoverChildren(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener* aUrlListener,
|
|
const char *folderPath,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
|
"Oops ... null aClientEventQueue or aImapMailFolder");
|
|
if (!aImapMailFolder || ! aClientEventQueue)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> aImapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
|
nsresult rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(aImapUrl),
|
|
aImapMailFolder,
|
|
aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED (rv))
|
|
{
|
|
rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
if (folderPath && *folderPath)
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(aImapUrl);
|
|
|
|
urlSpec.Append("/discoverchildren>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append(folderPath);
|
|
// mscott - this cast to a char * is okay...there's a bug in the XPIDL
|
|
// compiler that is preventing in string parameters from showing up as
|
|
// const char *. hopefully they will fix it soon.
|
|
rv = uri->SetSpec(urlSpec);
|
|
|
|
// Make sure the uri has the same hierarchy separator as the one in msg folder
|
|
// obj if it's not kOnlineHierarchySeparatorUnknown (ie, '^').
|
|
char uriDelimiter;
|
|
nsresult rv1 = aImapUrl->GetOnlineSubDirSeparator(&uriDelimiter);
|
|
if (NS_SUCCEEDED (rv1) && hierarchySeparator != kOnlineHierarchySeparatorUnknown &&
|
|
uriDelimiter != hierarchySeparator)
|
|
aImapUrl->SetOnlineSubDirSeparator((char)hierarchySeparator);
|
|
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
aImapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
else
|
|
{
|
|
rv = NS_ERROR_NULL_POINTER;
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::OnlineMessageCopy(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aSrcFolder,
|
|
const char* messageIds,
|
|
nsIMsgFolder* aDstFolder,
|
|
PRBool idsAreUids,
|
|
PRBool isMove,
|
|
nsIUrlListener* aUrlListener,
|
|
nsIURI** aURL,
|
|
nsISupports* copyState,
|
|
nsIMsgWindow *aMsgWindow)
|
|
{
|
|
NS_ASSERTION(aSrcFolder && aDstFolder && messageIds && aClientEventQueue,
|
|
"Fatal ... missing key parameters");
|
|
if (!aClientEventQueue || !aSrcFolder || !aDstFolder || !messageIds ||
|
|
*messageIds == 0)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr <nsIMsgIncomingServer> srcServer;
|
|
nsCOMPtr <nsIMsgIncomingServer> dstServer;
|
|
|
|
rv = aSrcFolder->GetServer(getter_AddRefs(srcServer));
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
rv = aDstFolder->GetServer(getter_AddRefs(dstServer));
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
PRBool sameServer;
|
|
rv = dstServer->Equals(srcServer, &sameServer);
|
|
if(NS_FAILED(rv)) return rv;
|
|
|
|
if (!sameServer)
|
|
{
|
|
NS_ASSERTION(PR_FALSE, "can't use this method to copy across servers");
|
|
// *** can only take message from the same imap host and user accnt
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aSrcFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aSrcFolder, aUrlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
SetImapUrlSink(aSrcFolder, imapUrl);
|
|
imapUrl->SetCopyState(copyState);
|
|
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
|
|
|
|
msgurl->SetMsgWindow(aMsgWindow);
|
|
imapUrl->AddChannelToLoadGroup(); //we get the loadGroup from msgWindow
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
if (isMove)
|
|
urlSpec.Append("/onlinemove>");
|
|
else
|
|
urlSpec.Append("/onlinecopy>");
|
|
if (idsAreUids)
|
|
urlSpec.Append(uidString);
|
|
else
|
|
urlSpec.Append(sequenceString);
|
|
urlSpec.Append('>');
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aSrcFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append('>');
|
|
urlSpec.Append(messageIds);
|
|
urlSpec.Append('>');
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
folderName.Adopt(strdup(""));
|
|
GetFolderName(aDstFolder, getter_Copies(folderName));
|
|
urlSpec.Append((const char *) folderName);
|
|
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsImapService::OfflineAppendFromFile(nsIFileSpec* aFileSpec,
|
|
nsIURI *aUrl,
|
|
nsIMsgFolder* aDstFolder,
|
|
const char* messageId, // te be replaced
|
|
PRBool inSelectedState, // needs to be in
|
|
nsIUrlListener* aListener,
|
|
nsIURI** aURL,
|
|
nsISupports* aCopyState)
|
|
{
|
|
nsCOMPtr <nsIMsgDatabase> destDB;
|
|
nsresult rv = aDstFolder->GetMsgDatabase(nsnull, getter_AddRefs(destDB));
|
|
// ### might need to send some notifications instead of just returning
|
|
|
|
if (NS_SUCCEEDED(rv) && destDB)
|
|
{
|
|
nsMsgKey fakeKey;
|
|
destDB->GetNextFakeOfflineMsgKey(&fakeKey);
|
|
|
|
nsCOMPtr <nsIMsgOfflineImapOperation> op;
|
|
rv = destDB->GetOfflineOpForKey(fakeKey, PR_TRUE, getter_AddRefs(op));
|
|
if (NS_SUCCEEDED(rv) && op)
|
|
{
|
|
nsXPIDLCString destFolderUri;
|
|
|
|
aDstFolder->GetURI(getter_Copies(destFolderUri));
|
|
op->SetOperation(nsIMsgOfflineImapOperation::kAppendDraft); // ### do we care if it's a template?
|
|
op->SetDestinationFolderURI(destFolderUri);
|
|
nsCOMPtr <nsIOutputStream> offlineStore;
|
|
rv = aDstFolder->GetOfflineStoreOutputStream(getter_AddRefs(offlineStore));
|
|
|
|
if (NS_SUCCEEDED(rv) && offlineStore)
|
|
{
|
|
PRInt64 curOfflineStorePos = 0;
|
|
nsCOMPtr <nsISeekableStream> seekable = do_QueryInterface(offlineStore);
|
|
if (seekable)
|
|
seekable->Tell(&curOfflineStorePos);
|
|
else
|
|
{
|
|
NS_ASSERTION(PR_FALSE, "needs to be a random store!");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
|
|
nsCOMPtr <nsIInputStream> inputStream;
|
|
nsCOMPtr <nsIMsgParseMailMsgState> msgParser = do_CreateInstance(NS_PARSEMAILMSGSTATE_CONTRACTID, &rv);
|
|
msgParser->SetMailDB(destDB);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = aFileSpec->GetInputStream(getter_AddRefs(inputStream));
|
|
if (NS_SUCCEEDED(rv) && inputStream)
|
|
{
|
|
// now, copy the temp file to the offline store for the dest folder.
|
|
PRInt32 inputBufferSize = 10240;
|
|
nsMsgLineStreamBuffer *inputStreamBuffer = new nsMsgLineStreamBuffer(inputBufferSize, PR_TRUE /* allocate new lines */, PR_FALSE /* leave CRLFs on the returned string */);
|
|
PRUint32 fileSize;
|
|
aFileSpec->GetFileSize(&fileSize);
|
|
PRUint32 bytesWritten;
|
|
rv = NS_OK;
|
|
// rv = inputStream->Read(inputBuffer, inputBufferSize, &bytesRead);
|
|
// if (NS_SUCCEEDED(rv) && bytesRead > 0)
|
|
msgParser->SetState(nsIMsgParseMailMsgState::ParseHeadersState);
|
|
// set the env pos to fake key so the msg hdr will have that for a key
|
|
msgParser->SetEnvelopePos(fakeKey);
|
|
PRBool needMoreData = PR_FALSE;
|
|
char * newLine = nsnull;
|
|
PRUint32 numBytesInLine = 0;
|
|
do
|
|
{
|
|
newLine = inputStreamBuffer->ReadNextLine(inputStream, numBytesInLine, needMoreData);
|
|
if (newLine)
|
|
{
|
|
msgParser->ParseAFolderLine(newLine, numBytesInLine);
|
|
rv = offlineStore->Write(newLine, numBytesInLine, &bytesWritten);
|
|
nsCRT::free(newLine);
|
|
}
|
|
}
|
|
while (newLine);
|
|
nsCOMPtr <nsIMsgDBHdr> fakeHdr;
|
|
|
|
msgParser->FinishHeader();
|
|
msgParser->GetNewMsgHdr(getter_AddRefs(fakeHdr));
|
|
if (fakeHdr)
|
|
{
|
|
if (NS_SUCCEEDED(rv) && fakeHdr)
|
|
{
|
|
PRUint32 resultFlags;
|
|
nsInt64 tellPos = curOfflineStorePos;
|
|
fakeHdr->SetMessageOffset((PRUint32) tellPos);
|
|
fakeHdr->OrFlags(MSG_FLAG_OFFLINE | MSG_FLAG_READ, &resultFlags);
|
|
fakeHdr->SetOfflineMessageSize(fileSize);
|
|
destDB->AddNewHdrToDB(fakeHdr, PR_TRUE /* notify */);
|
|
aDstFolder->SetFlag(MSG_FOLDER_FLAG_OFFLINEEVENTS);
|
|
}
|
|
}
|
|
// tell the listener we're done.
|
|
inputStream = nsnull;
|
|
aFileSpec->CloseStream();
|
|
aListener->OnStopRunningUrl(aUrl, NS_OK);
|
|
delete inputStreamBuffer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (destDB)
|
|
destDB->Close(PR_TRUE);
|
|
return rv;
|
|
}
|
|
|
|
/* append message from file url */
|
|
/* imap://HOST>appendmsgfromfile>DESTINATIONMAILBOXPATH */
|
|
/* imap://HOST>appenddraftfromfile>DESTINATIONMAILBOXPATH>UID>messageId */
|
|
NS_IMETHODIMP
|
|
nsImapService::AppendMessageFromFile(nsIEventQueue* aClientEventQueue,
|
|
nsIFileSpec* aFileSpec,
|
|
nsIMsgFolder* aDstFolder,
|
|
const char* messageId, // te be replaced
|
|
PRBool idsAreUids,
|
|
PRBool inSelectedState, // needs to be in
|
|
nsIUrlListener* aListener,
|
|
nsIURI** aURL,
|
|
nsISupports* aCopyState,
|
|
nsIMsgWindow *aMsgWindow)
|
|
{
|
|
nsresult rv = NS_ERROR_NULL_POINTER;
|
|
if (!aClientEventQueue || !aFileSpec || !aDstFolder)
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aDstFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aDstFolder, aListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr <nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(imapUrl);
|
|
if (msgUrl && aMsgWindow)
|
|
{
|
|
//we get the loadGroup from msgWindow
|
|
msgUrl->SetMsgWindow(aMsgWindow);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
}
|
|
|
|
SetImapUrlSink(aDstFolder, imapUrl);
|
|
imapUrl->SetMsgFileSpec(aFileSpec);
|
|
imapUrl->SetCopyState(aCopyState);
|
|
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
if (inSelectedState)
|
|
urlSpec.Append("/appenddraftfromfile>");
|
|
else
|
|
urlSpec.Append("/appendmsgfromfile>");
|
|
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(aDstFolder, getter_Copies(folderName));
|
|
urlSpec.Append(folderName);
|
|
|
|
if (inSelectedState)
|
|
{
|
|
urlSpec.Append('>');
|
|
if (idsAreUids)
|
|
urlSpec.Append(uidString);
|
|
else
|
|
urlSpec.Append(sequenceString);
|
|
urlSpec.Append('>');
|
|
if (messageId)
|
|
urlSpec.Append(messageId);
|
|
}
|
|
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (WeAreOffline())
|
|
{
|
|
return OfflineAppendFromFile(aFileSpec, uri, aDstFolder, messageId, inSelectedState, aListener, aURL, aCopyState);
|
|
// handle offline append to drafts or templates folder here.
|
|
}
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl,
|
|
nsnull, aURL);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue,
|
|
nsIImapUrl* aImapUrl,
|
|
nsISupports* aConsumer,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ENSURE_ARG(aImapUrl);
|
|
|
|
if (WeAreOffline())
|
|
{
|
|
nsImapAction imapAction;
|
|
|
|
// the only thing we can do offline is fetch messages.
|
|
// ### TODO - need to look at msg copy, save attachment, etc. when we
|
|
// have offline message bodies.
|
|
aImapUrl->GetImapAction(&imapAction);
|
|
if (imapAction != nsIImapUrl::nsImapMsgFetch && imapAction != nsIImapUrl::nsImapSaveMessageToDisk)
|
|
return NS_MSG_ERROR_OFFLINE;
|
|
}
|
|
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(aImapUrl);
|
|
rv = msgUrl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
|
|
|
if (aURL)
|
|
NS_IF_ADDREF(*aURL = msgUrl);
|
|
|
|
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
|
{
|
|
nsCOMPtr<nsIImapIncomingServer> aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
|
if (NS_SUCCEEDED(rv) && aImapServer)
|
|
rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
aImapUrl, aConsumer);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::MoveFolder(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder,
|
|
nsIMsgFolder* dstFolder, nsIUrlListener* urlListener,
|
|
nsIMsgWindow *msgWindow, nsIURI** url)
|
|
{
|
|
NS_ASSERTION(eventQueue && srcFolder && dstFolder,
|
|
"Oops ... null pointer");
|
|
if (!eventQueue || !srcFolder || !dstFolder)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
|
|
PRUnichar default_hierarchySeparator = GetHierarchyDelimiter(dstFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), dstFolder, urlListener, urlSpec, default_hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = SetImapUrlSink(dstFolder, imapUrl);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
if (mailNewsUrl)
|
|
mailNewsUrl->SetMsgWindow(msgWindow);
|
|
char hierarchySeparator = kOnlineHierarchySeparatorUnknown;
|
|
nsXPIDLCString folderName;
|
|
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
GetFolderName(srcFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/movefolderhierarchy>");
|
|
urlSpec.Append(hierarchySeparator);
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append('>');
|
|
folderName.Adopt(strdup(""));
|
|
GetFolderName(dstFolder, getter_Copies(folderName));
|
|
if ( folderName && folderName[0])
|
|
{
|
|
urlSpec.Append(hierarchySeparator);
|
|
urlSpec.Append((const char *) folderName);
|
|
}
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
GetFolderName(srcFolder, getter_Copies(folderName));
|
|
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
|
|
nsnull,
|
|
url);
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::RenameLeaf(nsIEventQueue* eventQueue, nsIMsgFolder* srcFolder,
|
|
const PRUnichar* newLeafName, nsIUrlListener* urlListener,
|
|
nsIMsgWindow *msgWindow, nsIURI** url)
|
|
{
|
|
NS_ASSERTION(eventQueue && srcFolder && newLeafName && *newLeafName,
|
|
"Oops ... [RenameLeaf] null pointers");
|
|
if (!eventQueue || !srcFolder || !newLeafName || !*newLeafName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(srcFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), srcFolder, urlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
rv = SetImapUrlSink(srcFolder, imapUrl);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
if (mailNewsUrl)
|
|
mailNewsUrl->SetMsgWindow(msgWindow);
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(srcFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/rename>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append('>');
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
|
|
|
|
nsCAutoString cStrFolderName(NS_STATIC_CAST(const char *, folderName));
|
|
// Unescape the name before looking for parent path
|
|
nsUnescape(cStrFolderName.BeginWriting());
|
|
PRInt32 leafNameStart =
|
|
cStrFolderName.RFindChar(hierarchySeparator);
|
|
if (leafNameStart != -1)
|
|
{
|
|
cStrFolderName.SetLength(leafNameStart+1);
|
|
urlSpec.Append(cStrFolderName);
|
|
}
|
|
|
|
nsCAutoString utfNewName;
|
|
CopyUTF16toMUTF7(nsDependentString(newLeafName), utfNewName);
|
|
char* escapedNewName = nsEscape(utfNewName.get(), url_Path);
|
|
if (!escapedNewName) return NS_ERROR_OUT_OF_MEMORY;
|
|
nsXPIDLCString escapedSlashName;
|
|
rv = nsImapUrl::EscapeSlashes(escapedNewName, getter_Copies(escapedSlashName));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCRT::free(escapedNewName);
|
|
urlSpec.Append(escapedSlashName.get());
|
|
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
|
|
nsnull, url);
|
|
}
|
|
} // if (NS_SUCCEEDED(rv))
|
|
} // if (NS_SUCCEEDED(rv) && imapUrl)
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::CreateFolder(nsIEventQueue* eventQueue, nsIMsgFolder* parent,
|
|
const PRUnichar* newFolderName,
|
|
nsIUrlListener* urlListener, nsIURI** url)
|
|
{
|
|
NS_ASSERTION(eventQueue && parent && newFolderName && *newFolderName,
|
|
"Oops ... [CreateFolder] null pointers");
|
|
if (!eventQueue || !parent || !newFolderName || !*newFolderName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(parent);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), parent, urlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = SetImapUrlSink(parent, imapUrl);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(parent, getter_Copies(folderName));
|
|
urlSpec.Append("/create>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
if (!folderName.IsEmpty())
|
|
{
|
|
nsXPIDLCString canonicalName;
|
|
|
|
nsImapUrl::ConvertToCanonicalFormat(folderName, (char) hierarchySeparator, getter_Copies(canonicalName));
|
|
urlSpec.Append((const char *) canonicalName);
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
}
|
|
|
|
nsCAutoString utfNewName;
|
|
rv = CopyUTF16toMUTF7(nsDependentString(newFolderName), utfNewName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
char* escapedFolderName = nsEscape(utfNewName.get(), url_Path);
|
|
urlSpec.Append(escapedFolderName);
|
|
nsCRT::free(escapedFolderName);
|
|
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
|
|
nsnull,
|
|
url);
|
|
} // if (NS_SUCCEEDED(rv))
|
|
} // if (NS_SUCCEEDED(rv) && imapUrl)
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::EnsureFolderExists(nsIEventQueue* eventQueue, nsIMsgFolder* parent,
|
|
const PRUnichar* newFolderName,
|
|
nsIUrlListener* urlListener, nsIURI** url)
|
|
{
|
|
NS_ASSERTION(eventQueue && parent && newFolderName && *newFolderName,
|
|
"Oops ... [EnsureExists] null pointers");
|
|
if (!eventQueue || !parent || !newFolderName || !*newFolderName)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(parent);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), parent, urlListener, urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = SetImapUrlSink(parent, imapUrl);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(parent, getter_Copies(folderName));
|
|
urlSpec.Append("/ensureExists>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
if (!folderName.IsEmpty())
|
|
{
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
}
|
|
nsCAutoString utfNewName;
|
|
CopyUTF16toMUTF7(nsDependentString(newFolderName), utfNewName);
|
|
char* escapedFolderName = nsEscape(utfNewName.get(), url_Path);
|
|
urlSpec.Append(escapedFolderName);
|
|
nsCRT::free(escapedFolderName);
|
|
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
|
|
nsnull,
|
|
url);
|
|
} // if (NS_SUCCEEDED(rv))
|
|
} // if (NS_SUCCEEDED(rv) && imapUrl)
|
|
return rv;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::ListFolder(nsIEventQueue* aClientEventQueue,
|
|
nsIMsgFolder* aImapMailFolder,
|
|
nsIUrlListener* aUrlListener,
|
|
nsIURI** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/listfolder>", nsIImapUrl::nsImapListFolder, aURL);
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsImapService::GetScheme(nsACString &aScheme)
|
|
{
|
|
aScheme = "imap";
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::GetDefaultPort(PRInt32 *aDefaultPort)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aDefaultPort);
|
|
*aDefaultPort = IMAP_PORT;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::GetProtocolFlags(PRUint32 *result)
|
|
{
|
|
*result = URI_STD | ALLOWS_PROXY;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
|
|
{
|
|
// allow imap to run on any port
|
|
*_retval = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::GetDefaultDoBiff(PRBool *aDoBiff)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aDoBiff);
|
|
// by default, do biff for IMAP servers
|
|
*aDoBiff = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetDefaultServerPort(PRBool isSecure, PRInt32 *aDefaultPort)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// Return Secure IMAP Port if secure option chosen i.e., if isSecure is TRUE
|
|
if (isSecure)
|
|
*aDefaultPort = SECURE_IMAP_PORT;
|
|
else
|
|
rv = GetDefaultPort(aDefaultPort);
|
|
|
|
return rv;
|
|
}
|
|
|
|
// this method first tries to find an exact username and hostname match with the given url
|
|
// then, tries to find any account on the passed in imap host in case this is a url to
|
|
// a shared imap folder.
|
|
nsresult nsImapService::GetServerFromUrl(nsIImapUrl *aImapUrl, nsIMsgIncomingServer **aServer)
|
|
{
|
|
nsCAutoString userPass;
|
|
nsCAutoString hostName;
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl);
|
|
nsresult rv;
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
// if we can't get a folder name out of the url then I think this is an error
|
|
aImapUrl->CreateCanonicalSourceFolderPathString(getter_Copies(folderName));
|
|
if (folderName.IsEmpty())
|
|
{
|
|
rv = mailnewsUrl->GetFileName(folderName);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIMsgAccountManager> accountManager =
|
|
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
rv = accountManager->FindServerByURI(mailnewsUrl, PR_FALSE, aServer);
|
|
|
|
// look for server with any user name, in case we're trying to subscribe
|
|
// to a folder with some one else's user name like the following
|
|
// "IMAP://userSharingFolder@server1/SharedFolderName"
|
|
|
|
if (NS_FAILED(rv) || !aServer)
|
|
{
|
|
nsCAutoString turl;
|
|
nsCOMPtr<nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
mailnewsUrl->GetSpec(turl);
|
|
rv = url->SetSpec(turl);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
url->SetUserPass(EmptyCString());
|
|
rv = accountManager->FindServerByURI(url, PR_FALSE, aServer);
|
|
if (*aServer)
|
|
aImapUrl->SetExternalLinkUrl(PR_TRUE);
|
|
}
|
|
// if we can't extract the imap server from this url then give up!!!
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
NS_ENSURE_TRUE(*aServer, NS_ERROR_FAILURE);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::NewURI(const nsACString &aSpec,
|
|
const char *aOriginCharset, // ignored
|
|
nsIURI *aBaseURI,
|
|
nsIURI **_retval)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIImapUrl> aImapUrl = do_CreateInstance(kImapUrlCID, &rv);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
// now extract lots of fun information...
|
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl);
|
|
//nsCAutoString unescapedSpec(aSpec);
|
|
// nsUnescape(unescapedSpec.BeginWriting());
|
|
|
|
// set the spec
|
|
if (aBaseURI)
|
|
{
|
|
nsCAutoString newSpec;
|
|
aBaseURI->Resolve(aSpec, newSpec);
|
|
mailnewsUrl->SetSpec(newSpec);
|
|
}
|
|
else
|
|
{
|
|
mailnewsUrl->SetSpec(aSpec);
|
|
}
|
|
|
|
nsXPIDLCString folderName;
|
|
|
|
// if we can't get a folder name out of the url then I think this is an error
|
|
aImapUrl->CreateCanonicalSourceFolderPathString(getter_Copies(folderName));
|
|
if (folderName.IsEmpty())
|
|
{
|
|
rv = mailnewsUrl->GetFileName(folderName);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr <nsIMsgIncomingServer> server;
|
|
rv = GetServerFromUrl(aImapUrl, getter_AddRefs(server));
|
|
// if we can't extract the imap server from this url then give up!!!
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
NS_ENSURE_TRUE(server, NS_ERROR_FAILURE);
|
|
|
|
// now try to get the folder in question...
|
|
nsCOMPtr<nsIMsgFolder> rootFolder;
|
|
server->GetRootFolder(getter_AddRefs(rootFolder));
|
|
|
|
if (rootFolder && !folderName.IsEmpty())
|
|
{
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsCOMPtr <nsIMsgImapMailFolder> imapRoot = do_QueryInterface(rootFolder, &rv);
|
|
nsCOMPtr <nsIMsgImapMailFolder> subFolder;
|
|
if (imapRoot)
|
|
{
|
|
imapRoot->FindOnlineSubFolder(folderName, getter_AddRefs(subFolder));
|
|
folder = do_QueryInterface(subFolder, &rv);
|
|
}
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIImapMessageSink> msgSink = do_QueryInterface(folder);
|
|
rv = aImapUrl->SetImapMessageSink(msgSink);
|
|
|
|
nsCOMPtr<nsIMsgFolder> msgFolder = do_QueryInterface(folder);
|
|
rv = SetImapUrlSink(msgFolder, aImapUrl);
|
|
nsXPIDLCString msgKey;
|
|
|
|
nsXPIDLCString messageIdString;
|
|
aImapUrl->CreateListOfMessageIdsString(getter_Copies(messageIdString));
|
|
if (messageIdString.get())
|
|
{
|
|
PRBool useLocalCache = PR_FALSE;
|
|
msgFolder->HasMsgOffline(atoi(messageIdString), &useLocalCache);
|
|
mailnewsUrl->SetMsgIsInLocalCache(useLocalCache);
|
|
}
|
|
}
|
|
}
|
|
|
|
// if we are fetching a part, be sure to enable fetch parts on demand
|
|
PRBool mimePartSelectorDetected = PR_FALSE;
|
|
aImapUrl->GetMimePartSelectorDetected(&mimePartSelectorDetected);
|
|
if (mimePartSelectorDetected)
|
|
aImapUrl->SetFetchPartsOnDemand(PR_TRUE);
|
|
|
|
// we got an imap url, so be sure to return it...
|
|
aImapUrl->QueryInterface(NS_GET_IID(nsIURI), (void **) _retval);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsImapService::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
|
{
|
|
// imap can't open and return a channel right away...the url needs to go in the imap url queue
|
|
// until we find a connection which can run the url..in order to satisfy necko, we're going to return
|
|
// a mock imap channel....
|
|
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIImapMockChannel> mockChannel;
|
|
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(aURI, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(imapUrl);
|
|
|
|
// XXX this mock channel stuff is wrong -- the channel really should be owning the URL
|
|
// and the originalURL, not the other way around
|
|
rv = imapUrl->InitializeURIforMockChannel();
|
|
rv = imapUrl->GetMockChannel(getter_AddRefs(mockChannel));
|
|
if (NS_FAILED(rv) || !mockChannel)
|
|
{
|
|
// this is a funky condition...it means we've already run the url once
|
|
// and someone is trying to get us to run it again...
|
|
imapUrl->Initialize(); // force a new mock channel to get created.
|
|
rv = imapUrl->InitializeURIforMockChannel();
|
|
rv = imapUrl->GetMockChannel(getter_AddRefs(mockChannel));
|
|
if (!mockChannel) return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
PRBool externalLinkUrl;
|
|
imapUrl->GetExternalLinkUrl(&externalLinkUrl);
|
|
if (externalLinkUrl)
|
|
{
|
|
// everything after here is to handle clicking on an external link. We only want
|
|
// to do this if we didn't run the url through the various nsImapService methods,
|
|
// which we can tell by seeing if the sinks have been setup on the url or not.
|
|
nsCOMPtr <nsIMsgIncomingServer> server;
|
|
rv = GetServerFromUrl(imapUrl, getter_AddRefs(server));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsXPIDLCString folderName;
|
|
imapUrl->CreateCanonicalSourceFolderPathString(getter_Copies(folderName));
|
|
if (folderName.IsEmpty())
|
|
{
|
|
rv = mailnewsUrl->GetFileName(folderName);
|
|
if (!folderName.IsEmpty())
|
|
NS_UnescapeURL(folderName);
|
|
}
|
|
// if the parent is null, then the folder doesn't really exist, so see if the user
|
|
// wants to subscribe to it./
|
|
nsCOMPtr<nsIMsgFolder> aFolder;
|
|
// now try to get the folder in question...
|
|
nsCOMPtr<nsIMsgFolder> rootFolder;
|
|
server->GetRootFolder(getter_AddRefs(rootFolder));
|
|
nsCOMPtr <nsIMsgImapMailFolder> imapRoot = do_QueryInterface(rootFolder);
|
|
nsCOMPtr <nsIMsgImapMailFolder> subFolder;
|
|
if (imapRoot)
|
|
{
|
|
imapRoot->FindOnlineSubFolder(folderName, getter_AddRefs(subFolder));
|
|
aFolder = do_QueryInterface(subFolder);
|
|
}
|
|
nsCOMPtr <nsIMsgFolder> parent;
|
|
if (aFolder)
|
|
aFolder->GetParent(getter_AddRefs(parent));
|
|
nsXPIDLCString serverKey;
|
|
nsCAutoString userPass;
|
|
rv = mailnewsUrl->GetUserPass(userPass);
|
|
server->GetKey(getter_Copies(serverKey));
|
|
char *fullFolderName = nsnull;
|
|
if (parent)
|
|
fullFolderName = ToNewCString(folderName);
|
|
if (!parent && !folderName.IsEmpty())// check if this folder is another user's folder
|
|
{
|
|
fullFolderName = nsIMAPNamespaceList::GenerateFullFolderNameWithDefaultNamespace(serverKey.get(), folderName.get(), userPass.get(), kOtherUsersNamespace, nsnull);
|
|
// if this is another user's folder, let's see if we're already subscribed to it.
|
|
rv = imapRoot->FindOnlineSubFolder(fullFolderName, getter_AddRefs(subFolder));
|
|
aFolder = do_QueryInterface(subFolder);
|
|
if (aFolder)
|
|
aFolder->GetParent(getter_AddRefs(parent));
|
|
}
|
|
// if we couldn't get the fullFolderName, then we probably couldn't find
|
|
// the other user's namespace, in which case, we shouldn't try to subscribe to it.
|
|
if (!parent && !folderName.IsEmpty() && fullFolderName)
|
|
{
|
|
// this folder doesn't exist - check if the user wants to subscribe to this folder.
|
|
nsCOMPtr<nsIPrompt> dialog;
|
|
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
wwatch->GetNewPrompter(nsnull, getter_AddRefs(dialog));
|
|
|
|
nsXPIDLString statusString, confirmText;
|
|
nsCOMPtr<nsIStringBundle> bundle;
|
|
rv = IMAPGetStringBundle(getter_AddRefs(bundle));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
// need to convert folder name from mod-utf7 to unicode
|
|
nsAutoString unescapedName;
|
|
if (NS_FAILED(CopyMUTF7toUTF16(nsDependentCString(fullFolderName), unescapedName)))
|
|
CopyASCIItoUTF16(nsDependentCString(fullFolderName), unescapedName);
|
|
const PRUnichar *formatStrings[1] = { unescapedName.get() };
|
|
|
|
rv = bundle->FormatStringFromID(IMAP_SUBSCRIBE_PROMPT,
|
|
formatStrings, 1,
|
|
getter_Copies(confirmText));
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
PRBool confirmResult = PR_FALSE;
|
|
rv = dialog->Confirm(nsnull, confirmText, &confirmResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (confirmResult)
|
|
{
|
|
nsCOMPtr <nsIImapIncomingServer> imapServer = do_QueryInterface(server);
|
|
if (imapServer)
|
|
{
|
|
nsCOMPtr <nsIURI> subscribeURI;
|
|
// now we have the real folder name to try to subscribe to. Let's try running
|
|
// a subscribe url and returning that as the uri we've created.
|
|
// We need to convert this to unicode because that's what subscribe wants :-(
|
|
// It's already in mod-utf7.
|
|
nsAutoString unicodeName;
|
|
unicodeName.AssignWithConversion(fullFolderName);
|
|
rv = imapServer->SubscribeToFolder(unicodeName.get(), PR_TRUE, getter_AddRefs(subscribeURI));
|
|
if (NS_SUCCEEDED(rv) && subscribeURI)
|
|
{
|
|
nsCOMPtr <nsIImapUrl> imapSubscribeUrl = do_QueryInterface(subscribeURI);
|
|
if (imapSubscribeUrl)
|
|
imapSubscribeUrl->SetExternalLinkUrl(PR_TRUE);
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(subscribeURI);
|
|
if (mailnewsUrl)
|
|
{
|
|
nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCOMPtr <nsIMsgWindow> msgWindow;
|
|
rv = mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
|
|
if (NS_SUCCEEDED(rv) && msgWindow)
|
|
{
|
|
mailnewsUrl->SetMsgWindow(msgWindow);
|
|
nsCOMPtr <nsIUrlListener> listener = do_QueryInterface(rootFolder);
|
|
if (listener)
|
|
mailnewsUrl->RegisterListener(listener);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// error out this channel, so it'll stop trying to run the url.
|
|
rv = NS_ERROR_FAILURE;
|
|
*_retval = nsnull;
|
|
PR_Free(fullFolderName);
|
|
}
|
|
else if (fullFolderName)// this folder exists - check if this is a click on a link to the folder
|
|
{ // in which case, we'll select it.
|
|
nsCOMPtr <nsIMsgFolder> imapFolder;
|
|
nsCOMPtr <nsIImapServerSink> serverSink;
|
|
|
|
mailnewsUrl->GetFolder(getter_AddRefs(imapFolder));
|
|
imapUrl->GetImapServerSink(getter_AddRefs(serverSink));
|
|
// need to see if this is a link click - one way is to check if the url is set up correctly
|
|
// if not, it's probably a url click. We need a better way of doing this.
|
|
if (!imapFolder)
|
|
{
|
|
nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCOMPtr <nsIMsgWindow> msgWindow;
|
|
rv = mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
|
|
if (NS_SUCCEEDED(rv) && msgWindow)
|
|
{
|
|
nsXPIDLCString uri;
|
|
rootFolder->GetURI(getter_Copies(uri));
|
|
uri.Append('/');
|
|
uri.Append(fullFolderName);
|
|
msgWindow->SelectFolder(uri.get());
|
|
// error out this channel, so it'll stop trying to run the url.
|
|
*_retval = nsnull;
|
|
rv = NS_ERROR_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
// make sure the imap action is selectFolder, so the content type
|
|
// will be x-application-imapfolder, so ::HandleContent will
|
|
// know to open a new 3 pane window.
|
|
imapUrl->SetImapAction(nsIImapUrl::nsImapSelectFolder);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (NS_SUCCEEDED(rv))
|
|
NS_IF_ADDREF(*_retval = mockChannel);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::SetDefaultLocalPath(nsIFileSpec *aPath)
|
|
{
|
|
NS_ENSURE_ARG(aPath);
|
|
|
|
nsFileSpec spec;
|
|
nsresult rv = aPath->GetFileSpec(&spec);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCOMPtr<nsILocalFile> localFile;
|
|
NS_FileSpecToIFile(&spec, getter_AddRefs(localFile));
|
|
if (!localFile) return NS_ERROR_FAILURE;
|
|
|
|
return NS_SetPersistentFile(PREF_MAIL_ROOT_IMAP_REL, PREF_MAIL_ROOT_IMAP, localFile);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetDefaultLocalPath(nsIFileSpec ** aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
*aResult = nsnull;
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRBool havePref;
|
|
nsCOMPtr<nsILocalFile> localFile;
|
|
rv = NS_GetPersistentFile(PREF_MAIL_ROOT_IMAP_REL,
|
|
PREF_MAIL_ROOT_IMAP,
|
|
NS_APP_IMAP_MAIL_50_DIR,
|
|
havePref,
|
|
getter_AddRefs(localFile));
|
|
|
|
PRBool exists;
|
|
rv = localFile->Exists(&exists);
|
|
if (NS_SUCCEEDED(rv) && !exists)
|
|
rv = localFile->Create(nsIFile::DIRECTORY_TYPE, 0775);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Make the resulting nsIFileSpec
|
|
// TODO: Convert arg to nsILocalFile and avoid this
|
|
nsCOMPtr<nsIFileSpec> outSpec;
|
|
rv = NS_NewFileSpecFromIFile(localFile, getter_AddRefs(outSpec));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!havePref || !exists)
|
|
{
|
|
rv = NS_SetPersistentFile(PREF_MAIL_ROOT_IMAP_REL, PREF_MAIL_ROOT_IMAP, localFile);
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to set root dir pref.");
|
|
}
|
|
|
|
NS_IF_ADDREF(*aResult = outSpec);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetServerIID(nsIID* *aServerIID)
|
|
{
|
|
*aServerIID = new nsIID(NS_GET_IID(nsIImapIncomingServer));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetRequiresUsername(PRBool *aRequiresUsername)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aRequiresUsername);
|
|
*aRequiresUsername = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetPreflightPrettyNameWithEmailAddress(PRBool *aPreflightPrettyNameWithEmailAddress)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aPreflightPrettyNameWithEmailAddress);
|
|
*aPreflightPrettyNameWithEmailAddress = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetCanLoginAtStartUp(PRBool *aCanLoginAtStartUp)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCanLoginAtStartUp);
|
|
*aCanLoginAtStartUp = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetCanDelete(PRBool *aCanDelete)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCanDelete);
|
|
*aCanDelete = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetCanDuplicate(PRBool *aCanDuplicate)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCanDuplicate);
|
|
*aCanDuplicate = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetCanGetMessages(PRBool *aCanGetMessages)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCanGetMessages);
|
|
*aCanGetMessages = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetCanGetIncomingMessages(PRBool *aCanGetIncomingMessages)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aCanGetIncomingMessages);
|
|
*aCanGetIncomingMessages = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetShowComposeMsgLink(PRBool *showComposeMsgLink)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(showComposeMsgLink);
|
|
*showComposeMsgLink = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetNeedToBuildSpecialFolderURIs(PRBool *needToBuildSpecialFolderURIs)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(needToBuildSpecialFolderURIs);
|
|
*needToBuildSpecialFolderURIs = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetSpecialFoldersDeletionAllowed(PRBool *specialFoldersDeletionAllowed)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(specialFoldersDeletionAllowed);
|
|
*specialFoldersDeletionAllowed = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetListOfFoldersWithPath(nsIImapIncomingServer *aServer, nsIMsgWindow *aMsgWindow, const char *folderPath)
|
|
{
|
|
nsresult rv;
|
|
|
|
#ifdef DEBUG_sspitzer
|
|
printf("GetListOfFoldersWithPath(%s)\n",folderPath);
|
|
#endif
|
|
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(aServer);
|
|
if (!server) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMsgFolder> rootMsgFolder;
|
|
rv = server->GetRootMsgFolder(getter_AddRefs(rootMsgFolder));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!rootMsgFolder) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIUrlListener> listener = do_QueryInterface(aServer, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!listener) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIEventQueue> queue;
|
|
// get the Event Queue for this thread...
|
|
nsCOMPtr<nsIEventQueueService> pEventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Locate the folder so that the correct hierarchical delimiter is used in the folder
|
|
// pathnames, otherwise root's (ie, '^') is used and this is wrong.
|
|
nsCOMPtr<nsIMsgFolder> msgFolder;
|
|
if (rootMsgFolder && folderPath && (*folderPath))
|
|
{
|
|
// If the folder path contains 'INBOX' of any forms, we need to convert it to uppercase
|
|
// before finding it under the root folder. We do the same in PossibleImapMailbox().
|
|
nsCAutoString tempFolderName(folderPath);
|
|
nsCAutoString tokenStr, remStr, changedStr;
|
|
PRInt32 slashPos = tempFolderName.FindChar('/');
|
|
if (slashPos > 0)
|
|
{
|
|
tempFolderName.Left(tokenStr,slashPos);
|
|
tempFolderName.Right(remStr, tempFolderName.Length()-slashPos);
|
|
}
|
|
else
|
|
tokenStr.Assign(tempFolderName);
|
|
|
|
if ((nsCRT::strcasecmp(tokenStr.get(), "INBOX")==0) && (nsCRT::strcmp(tokenStr.get(), "INBOX") != 0))
|
|
changedStr.Append("INBOX");
|
|
else
|
|
changedStr.Append(tokenStr);
|
|
|
|
if (slashPos > 0 )
|
|
changedStr.Append(remStr);
|
|
|
|
|
|
rv = rootMsgFolder->FindSubFolder(changedStr, getter_AddRefs(msgFolder));
|
|
}
|
|
|
|
rv = DiscoverChildren(queue, msgFolder, listener, folderPath, nsnull);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetListOfFoldersOnServer(nsIImapIncomingServer *aServer, nsIMsgWindow *aMsgWindow)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(aServer);
|
|
if (!server) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIMsgFolder> rootMsgFolder;
|
|
rv = server->GetRootMsgFolder(getter_AddRefs(rootMsgFolder));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!rootMsgFolder) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIUrlListener> listener = do_QueryInterface(aServer, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!listener) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIEventQueue> queue;
|
|
// get the Event Queue for this thread...
|
|
nsCOMPtr<nsIEventQueueService> pEventQService =
|
|
do_GetService(kEventQueueServiceCID, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = DiscoverAllAndSubscribedFolders(queue, rootMsgFolder, listener, nsnull);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::SubscribeFolder(nsIEventQueue* eventQueue,
|
|
nsIMsgFolder* aFolder,
|
|
const PRUnichar* aFolderName,
|
|
nsIUrlListener* urlListener, nsIURI** url)
|
|
{
|
|
return ChangeFolderSubscription(eventQueue, aFolder, aFolderName,
|
|
"/subscribe>", urlListener, url);
|
|
}
|
|
|
|
nsresult nsImapService::ChangeFolderSubscription(nsIEventQueue* eventQueue,
|
|
nsIMsgFolder* folder,
|
|
const PRUnichar* folderName,
|
|
const char *command,
|
|
nsIUrlListener* urlListener, nsIURI** url)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(eventQueue);
|
|
NS_ENSURE_ARG_POINTER(folder);
|
|
NS_ENSURE_ARG_POINTER(folderName);
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), folder, urlListener,
|
|
urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
rv = SetImapUrlSink(folder, imapUrl);
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
|
|
urlSpec.Append(command);
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
nsCAutoString utfFolderName;
|
|
rv = CopyUTF16toMUTF7(nsDependentString(folderName), utfFolderName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
char* escapedFolderName = nsEscape(utfFolderName.get(), url_Path);
|
|
urlSpec.Append(escapedFolderName);
|
|
nsCRT::free(escapedFolderName);
|
|
rv = uri->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
|
|
nsnull, url);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::UnsubscribeFolder(nsIEventQueue* aEventQueue,
|
|
nsIMsgFolder* aFolder,
|
|
const PRUnichar* aFolderName,
|
|
nsIUrlListener* aUrlListener, nsIURI** aUrl)
|
|
{
|
|
return ChangeFolderSubscription(aEventQueue, aFolder, aFolderName,
|
|
"/unsubscribe>", aUrlListener, aUrl);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::GetFolderAdminUrl(nsIEventQueue *aClientEventQueue,
|
|
nsIMsgFolder *aImapMailFolder,
|
|
nsIMsgWindow *aMsgWindow,
|
|
nsIUrlListener *aUrlListener,
|
|
nsIURI** aURL)
|
|
{
|
|
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
|
|
"/refreshfolderurls>", nsIImapUrl::nsImapRefreshFolderUrls, aURL);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::IssueCommandOnMsgs(nsIEventQueue *aClientEventQueue,
|
|
nsIMsgFolder *anImapFolder,
|
|
nsIMsgWindow *aMsgWindow,
|
|
const char *aCommand,
|
|
const char *uids,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aClientEventQueue);
|
|
NS_ENSURE_ARG_POINTER(anImapFolder);
|
|
NS_ENSURE_ARG_POINTER(aMsgWindow);
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(anImapFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), anImapFolder, nsnull, urlSpec, hierarchySeparator);
|
|
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
// nsImapUrl::SetSpec() will set the imap action properly
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapUserDefinedMsgCommand);
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
mailNewsUrl->SetMsgWindow(aMsgWindow);
|
|
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
rv = SetImapUrlSink(anImapFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(anImapFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/");
|
|
urlSpec.Append(aCommand);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(uidString);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(uids);
|
|
rv = mailNewsUrl->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
imapUrl,
|
|
nsnull,
|
|
aURL);
|
|
}
|
|
} // if we have a url to run....
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::FetchCustomMsgAttribute(nsIEventQueue *aClientEventQueue,
|
|
nsIMsgFolder *anImapFolder,
|
|
nsIMsgWindow *aMsgWindow,
|
|
const char *aAttribute,
|
|
const char *uids,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aClientEventQueue);
|
|
NS_ENSURE_ARG_POINTER(anImapFolder);
|
|
NS_ENSURE_ARG_POINTER(aMsgWindow);
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(anImapFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), anImapFolder, nsnull, urlSpec, hierarchySeparator);
|
|
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
// nsImapUrl::SetSpec() will set the imap action properly
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapUserDefinedFetchAttribute);
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
mailNewsUrl->SetMsgWindow(aMsgWindow);
|
|
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
rv = SetImapUrlSink(anImapFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(anImapFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/customFetch>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(uids);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(aAttribute);
|
|
rv = mailNewsUrl->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
imapUrl,
|
|
nsnull,
|
|
aURL);
|
|
}
|
|
} // if we have a url to run....
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::StoreCustomKeywords(nsIEventQueue *aClientEventQueue,
|
|
nsIMsgFolder *anImapFolder,
|
|
nsIMsgWindow *aMsgWindow,
|
|
const char *flagsToAdd,
|
|
const char *flagsToSubtract,
|
|
const char *uids,
|
|
nsIURI** aURL)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aClientEventQueue);
|
|
NS_ENSURE_ARG_POINTER(anImapFolder);
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(anImapFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), anImapFolder, nsnull, urlSpec, hierarchySeparator);
|
|
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
// nsImapUrl::SetSpec() will set the imap action properly
|
|
rv = imapUrl->SetImapAction(nsIImapUrl::nsImapMsgStoreCustomKeywords);
|
|
|
|
nsCOMPtr <nsIMsgMailNewsUrl> mailNewsUrl = do_QueryInterface(imapUrl);
|
|
mailNewsUrl->SetMsgWindow(aMsgWindow);
|
|
mailNewsUrl->SetUpdatingFolder(PR_TRUE);
|
|
imapUrl->AddChannelToLoadGroup();
|
|
rv = SetImapUrlSink(anImapFolder, imapUrl);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
nsXPIDLCString folderName;
|
|
GetFolderName(anImapFolder, getter_Copies(folderName));
|
|
urlSpec.Append("/customKeywords>UID>");
|
|
urlSpec.Append(char(hierarchySeparator));
|
|
urlSpec.Append((const char *) folderName);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(uids);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(flagsToAdd);
|
|
urlSpec.Append(">");
|
|
urlSpec.Append(flagsToSubtract);
|
|
rv = mailNewsUrl->SetSpec(urlSpec);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = GetImapConnectionAndLoadUrl(aClientEventQueue,
|
|
imapUrl,
|
|
nsnull,
|
|
aURL);
|
|
}
|
|
} // if we have a url to run....
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DownloadMessagesForOffline(const char *messageIds, nsIMsgFolder *aFolder, nsIUrlListener *aUrlListener, nsIMsgWindow *aMsgWindow)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aFolder);
|
|
NS_ENSURE_ARG_POINTER(messageIds);
|
|
|
|
nsCOMPtr<nsIImapUrl> imapUrl;
|
|
nsCAutoString urlSpec;
|
|
nsresult rv;
|
|
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aFolder);
|
|
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aFolder, nsnull,
|
|
urlSpec, hierarchySeparator);
|
|
if (NS_SUCCEEDED(rv) && imapUrl)
|
|
{
|
|
nsCOMPtr <nsIURI> runningURI;
|
|
// need to pass in stream listener in order to get the channel created correctly
|
|
nsCOMPtr<nsIImapMessageSink> imapMessageSink(do_QueryInterface(aFolder, &rv));
|
|
rv = FetchMessage(imapUrl, nsImapUrl::nsImapMsgDownloadForOffline,aFolder, imapMessageSink,
|
|
aMsgWindow, nsnull, messageIds, PR_FALSE, nsnull, getter_AddRefs(runningURI));
|
|
if (runningURI && aUrlListener)
|
|
{
|
|
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(runningURI));
|
|
if (msgurl)
|
|
msgurl->RegisterListener(aUrlListener);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::MessageURIToMsgHdr(const char *uri, nsIMsgDBHdr **_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(uri);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsIMsgFolder> folder;
|
|
nsMsgKey msgKey;
|
|
|
|
rv = DecomposeImapURI(uri, getter_AddRefs(folder), &msgKey);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
rv = folder->GetMessageHeader(msgKey, _retval);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::PlaybackAllOfflineOperations(nsIMsgWindow *aMsgWindow, nsIUrlListener *aListener, nsISupports **aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
nsresult rv;
|
|
nsImapOfflineSync *goOnline = new nsImapOfflineSync(aMsgWindow, aListener, nsnull);
|
|
if (goOnline)
|
|
{
|
|
rv = goOnline->QueryInterface(NS_GET_IID(nsISupports), (void **) aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (NS_SUCCEEDED(rv) && *aResult)
|
|
return goOnline->ProcessNextOperation();
|
|
}
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::DownloadAllOffineImapFolders(nsIMsgWindow *aMsgWindow, nsIUrlListener *aListener)
|
|
{
|
|
nsImapOfflineDownloader *downloadForOffline = new nsImapOfflineDownloader(aMsgWindow, aListener);
|
|
if (downloadForOffline)
|
|
{
|
|
// hold reference to this so it won't get deleted out from under itself.
|
|
NS_ADDREF(downloadForOffline);
|
|
nsresult rv = downloadForOffline->ProcessNextOperation();
|
|
NS_RELEASE(downloadForOffline);
|
|
return rv;
|
|
}
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsImapService::GetCacheSession(nsICacheSession **result)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (!mCacheSession)
|
|
{
|
|
nsCOMPtr<nsICacheService> serv = do_GetService(kCacheServiceCID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = serv->CreateSession("IMAP-memory-only", nsICache::STORE_IN_MEMORY, nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = mCacheSession->SetDoomEntriesIfExpired(PR_FALSE);
|
|
}
|
|
|
|
*result = mCacheSession;
|
|
NS_IF_ADDREF(*result);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsImapService::HandleContent(const char * aContentType, nsIInterfaceRequestor* aWindowContext, nsIRequest *request)
|
|
{
|
|
nsresult rv;
|
|
NS_ENSURE_ARG_POINTER(request);
|
|
|
|
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (nsCRT::strcasecmp(aContentType, "x-application-imapfolder") == 0)
|
|
{
|
|
nsCOMPtr<nsIURI> uri;
|
|
rv = aChannel->GetURI(getter_AddRefs(uri));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (uri)
|
|
{
|
|
request->Cancel(NS_BINDING_ABORTED);
|
|
nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCAutoString uriStr;
|
|
|
|
uri->GetSpec(uriStr);
|
|
|
|
// imap uri's are unescaped, so unescape the url.
|
|
NS_UnescapeURL(uriStr);
|
|
nsCOMPtr <nsIMessengerWindowService> messengerWindowService = do_GetService(NS_MESSENGERWINDOWSERVICE_CONTRACTID,&rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = messengerWindowService->OpenMessengerWindowWithUri("mail:3pane", uriStr.get(), nsMsgKey_None);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
} else {
|
|
// The content-type was not x-application-imapfolder
|
|
return NS_ERROR_WONT_HANDLE_CONTENT;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|