summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/imap/src/nsImapUrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/imap/src/nsImapUrl.cpp')
-rw-r--r--comm/mailnews/imap/src/nsImapUrl.cpp1276
1 files changed, 1276 insertions, 0 deletions
diff --git a/comm/mailnews/imap/src/nsImapUrl.cpp b/comm/mailnews/imap/src/nsImapUrl.cpp
new file mode 100644
index 0000000000..4460b5ab05
--- /dev/null
+++ b/comm/mailnews/imap/src/nsImapUrl.cpp
@@ -0,0 +1,1276 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "msgCore.h" // precompiled header...
+
+#include "nsImapUrl.h"
+#include "../public/nsIImapHostSessionList.h"
+#include "nsThreadUtils.h"
+#include "nsString.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "nsMemory.h"
+#include "nsCOMPtr.h"
+#include "nsImapUtils.h"
+#include "nsIImapMockChannel.h"
+#include "nsIImapMailFolderSink.h"
+#include "nsIImapMessageSink.h"
+#include "nsIImapServerSink.h"
+#include "nsImapNamespace.h"
+#include "nsICacheEntry.h"
+#include "nsIMsgFolder.h"
+#include "nsMsgUtils.h"
+#include "nsIMsgHdr.h"
+#include "nsServiceManagerUtils.h"
+#include "mozilla/Logging.h"
+
+using namespace mozilla;
+extern LazyLogModule IMAPCache; // defined in nsImapProtocol.cpp
+
+#define NS_IIMAPHOSTSESSIONLIST_CID \
+ { \
+ 0x479ce8fc, 0xe725, 0x11d2, { \
+ 0xa5, 0x05, 0x00, 0x60, 0xb0, 0xfc, 0x04, 0xb7 \
+ } \
+ }
+static NS_DEFINE_CID(kCImapHostSessionListCID, NS_IIMAPHOSTSESSIONLIST_CID);
+
+nsImapUrl::nsImapUrl() : mLock("nsImapUrl.mLock") {
+ m_listOfMessageIds = nullptr;
+ m_sourceCanonicalFolderPathSubString = nullptr;
+ m_destinationCanonicalFolderPathSubString = nullptr;
+ m_listOfMessageIds = nullptr;
+ m_tokenPlaceHolder = nullptr;
+ m_urlidSubString = nullptr;
+ m_searchCriteriaString = nullptr;
+ m_idsAreUids = false;
+ m_mimePartSelectorDetected = false;
+ m_msgLoadingFromCache = false;
+ m_storeResultsOffline = false;
+ m_storeOfflineOnFallback = false;
+ m_localFetchOnly = false;
+ m_rerunningUrl = false;
+ m_moreHeadersToDownload = false;
+ m_externalLinkUrl = true; // we'll start this at true, and set it false in
+ // nsImapService::CreateStartOfImapUrl
+ m_numBytesToFetch = 0;
+ m_validUrl = true; // assume the best.
+ m_runningUrl = false;
+ m_flags = 0;
+ m_extraStatus = ImapStatusNone;
+ m_onlineSubDirSeparator = '/';
+ m_imapAction = 0;
+ mAutodetectCharset = false;
+
+ // ** jt - the following are not ref counted
+ m_copyState = nullptr;
+ m_file = nullptr;
+ m_imapMailFolderSink = nullptr;
+ m_imapMessageSink = nullptr;
+ m_addDummyEnvelope = false;
+ m_canonicalLineEnding = false;
+}
+
+nsImapUrl::~nsImapUrl() {
+ PR_FREEIF(m_listOfMessageIds);
+ PR_FREEIF(m_destinationCanonicalFolderPathSubString);
+ PR_FREEIF(m_sourceCanonicalFolderPathSubString);
+ PR_FREEIF(m_searchCriteriaString);
+}
+
+NS_IMPL_ADDREF_INHERITED(nsImapUrl, nsMsgMailNewsUrl)
+
+NS_IMPL_RELEASE_INHERITED(nsImapUrl, nsMsgMailNewsUrl)
+
+NS_INTERFACE_MAP_BEGIN(nsImapUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIImapUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIMsgMessageUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIMsgI18NUrl)
+NS_INTERFACE_MAP_END_INHERITING(nsMsgMailNewsUrl)
+
+////////////////////////////////////////////////////////////////////////////////////
+// Begin nsIImapUrl specific support
+////////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP nsImapUrl::GetRequiredImapState(nsImapState* aImapUrlState) {
+ if (aImapUrlState) {
+ // the imap action determines the state we must be in...check the
+ // the imap action.
+
+ if (m_imapAction & 0x10000000)
+ *aImapUrlState = nsImapSelectedState;
+ else
+ *aImapUrlState = nsImapAuthenticatedState;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetImapAction(nsImapAction* aImapAction) {
+ *aImapAction = m_imapAction;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetImapAction(nsImapAction aImapAction) {
+ m_imapAction = aImapAction;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetFolder(nsIMsgFolder** aMsgFolder) {
+ NS_ENSURE_ARG_POINTER(aMsgFolder);
+ NS_ENSURE_ARG_POINTER(m_imapFolder);
+
+ nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(m_imapFolder);
+ folder.forget(aMsgFolder);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetFolder(nsIMsgFolder* aMsgFolder) {
+ nsresult rv;
+ m_imapFolder = do_GetWeakReference(aMsgFolder, &rv);
+ if (aMsgFolder) {
+ nsCOMPtr<nsIMsgIncomingServer> incomingServer;
+ aMsgFolder->GetServer(getter_AddRefs(incomingServer));
+ if (incomingServer) incomingServer->GetKey(m_serverKey);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsImapUrl::GetImapMailFolderSink(
+ nsIImapMailFolderSink** aImapMailFolderSink) {
+ NS_ENSURE_ARG_POINTER(aImapMailFolderSink);
+ if (!m_imapMailFolderSink)
+ return NS_ERROR_NULL_POINTER; // no assert, so don't use NS_ENSURE_POINTER.
+
+ nsCOMPtr<nsIImapMailFolderSink> folderSink =
+ do_QueryReferent(m_imapMailFolderSink);
+ folderSink.forget(aImapMailFolderSink);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetImapMailFolderSink(
+ nsIImapMailFolderSink* aImapMailFolderSink) {
+ nsresult rv;
+ m_imapMailFolderSink = do_GetWeakReference(aImapMailFolderSink, &rv);
+ return rv;
+}
+
+NS_IMETHODIMP nsImapUrl::GetImapMessageSink(
+ nsIImapMessageSink** aImapMessageSink) {
+ NS_ENSURE_ARG_POINTER(aImapMessageSink);
+ NS_ENSURE_ARG_POINTER(m_imapMessageSink);
+
+ nsCOMPtr<nsIImapMessageSink> messageSink =
+ do_QueryReferent(m_imapMessageSink);
+ messageSink.forget(aImapMessageSink);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetImapMessageSink(
+ nsIImapMessageSink* aImapMessageSink) {
+ nsresult rv;
+ m_imapMessageSink = do_GetWeakReference(aImapMessageSink, &rv);
+ return rv;
+}
+
+NS_IMETHODIMP nsImapUrl::GetImapServerSink(
+ nsIImapServerSink** aImapServerSink) {
+ NS_ENSURE_ARG_POINTER(aImapServerSink);
+ NS_ENSURE_ARG_POINTER(m_imapServerSink);
+
+ nsCOMPtr<nsIImapServerSink> serverSink = do_QueryReferent(m_imapServerSink);
+ serverSink.forget(aImapServerSink);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetImapServerSink(nsIImapServerSink* aImapServerSink) {
+ nsresult rv;
+ m_imapServerSink = do_GetWeakReference(aImapServerSink, &rv);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// End nsIImapUrl specific support
+////////////////////////////////////////////////////////////////////////////////////
+
+nsresult nsImapUrl::SetSpecInternal(const nsACString& aSpec) {
+ nsresult rv = nsMsgMailNewsUrl::SetSpecInternal(aSpec);
+ if (NS_SUCCEEDED(rv)) {
+ m_validUrl = true; // assume the best.
+ rv = ParseUrl();
+ }
+ return rv;
+}
+
+nsresult nsImapUrl::SetQuery(const nsACString& aQuery) {
+ nsresult rv = nsMsgMailNewsUrl::SetQuery(aQuery);
+ if (NS_SUCCEEDED(rv)) rv = ParseUrl();
+ return rv;
+}
+
+nsresult nsImapUrl::ParseUrl() {
+ nsresult rv = NS_OK;
+ // extract the user name
+ GetUserPass(m_userName);
+
+ nsAutoCString imapPartOfUrl;
+ rv = GetPathQueryRef(imapPartOfUrl);
+ nsAutoCString unescapedImapPartOfUrl;
+ MsgUnescapeString(imapPartOfUrl, 0, unescapedImapPartOfUrl);
+ if (NS_SUCCEEDED(rv) && !unescapedImapPartOfUrl.IsEmpty()) {
+ ParseImapPart(unescapedImapPartOfUrl.BeginWriting() +
+ 1); // GetPath leaves leading '/' in the path!!!
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::CreateSearchCriteriaString(char** aResult) {
+ // this method should only be called from the imap thread...
+ // o.t. add lock protection..
+ if (nullptr == aResult || !m_searchCriteriaString)
+ return NS_ERROR_NULL_POINTER;
+ *aResult = strdup(m_searchCriteriaString);
+ return NS_OK;
+}
+
+// this method gets called from the UI thread and the imap thread
+NS_IMETHODIMP nsImapUrl::GetListOfMessageIds(nsACString& aResult) {
+ MutexAutoLock mon(mLock);
+ if (!m_listOfMessageIds) return NS_ERROR_NULL_POINTER;
+
+ int32_t bytesToCopy = strlen(m_listOfMessageIds);
+
+ // mime may have glommed a "&part=" for a part download
+ // we return the entire message and let mime extract
+ // the part. Pop and news work this way also.
+ // this algorithm truncates the "&part" string.
+ char* currentChar = m_listOfMessageIds;
+ while (*currentChar && (*currentChar != '?')) currentChar++;
+ if (*currentChar == '?') bytesToCopy = currentChar - m_listOfMessageIds;
+
+ // we should also strip off anything after "/;section="
+ // since that can specify an IMAP MIME part
+ char* wherePart = PL_strstr(m_listOfMessageIds, "/;section=");
+ if (wherePart)
+ bytesToCopy =
+ std::min(bytesToCopy, int32_t(wherePart - m_listOfMessageIds));
+
+ aResult.Assign(m_listOfMessageIds, bytesToCopy);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCommand(nsACString& result) {
+ result = m_command;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCustomAttributeToFetch(nsACString& result) {
+ result = m_msgFetchAttribute;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCustomAttributeResult(nsACString& result) {
+ result = m_customAttributeResult;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetCustomAttributeResult(const nsACString& result) {
+ m_customAttributeResult = result;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCustomCommandResult(nsACString& result) {
+ result = m_customCommandResult;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetCustomCommandResult(const nsACString& result) {
+ m_customCommandResult = result;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCustomAddFlags(nsACString& aResult) {
+ aResult = m_customAddFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetCustomSubtractFlags(nsACString& aResult) {
+ aResult = m_customSubtractFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetImapPartToFetch(char** result) {
+ // here's the old code....
+
+ // unfortunately an imap part can have the form: /;section= OR
+ // it can have the form ?section=. We need to look for both.
+ if (m_listOfMessageIds) {
+ char* wherepart = PL_strstr(m_listOfMessageIds, ";section=");
+ if (!wherepart) // look for ?section too....
+ wherepart = PL_strstr(m_listOfMessageIds, "?section=");
+ if (wherepart) {
+ wherepart += 9; // strlen("/;section=")
+ char* wherelibmimepart = PL_strstr(wherepart, "&part=");
+ if (!wherelibmimepart) wherelibmimepart = PL_strstr(wherepart, "?part=");
+ int numCharsToCopy = (wherelibmimepart)
+ ? wherelibmimepart - wherepart
+ : PL_strlen(m_listOfMessageIds) -
+ (wherepart - m_listOfMessageIds);
+ if (numCharsToCopy) {
+ *result = (char*)PR_Malloc(sizeof(char) * (numCharsToCopy + 1));
+ if (*result) {
+ PL_strncpy(*result, wherepart, numCharsToCopy + 1); // appends a \0
+ (*result)[numCharsToCopy] = '\0';
+ }
+ }
+ } // if we got a wherepart
+ } // if we got a m_listOfMessageIds
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetOnlineSubDirSeparator(char* separator) {
+ if (separator) {
+ *separator = m_onlineSubDirSeparator;
+ return NS_OK;
+ }
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP nsImapUrl::GetNumBytesToFetch(int32_t* aNumBytesToFetch) {
+ NS_ENSURE_ARG_POINTER(aNumBytesToFetch);
+ *aNumBytesToFetch = m_numBytesToFetch;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsImapUrl::SetOnlineSubDirSeparator(char onlineDirSeparator) {
+ m_onlineSubDirSeparator = onlineDirSeparator;
+ return NS_OK;
+}
+
+// this method is only called from the imap thread
+NS_IMETHODIMP nsImapUrl::MessageIdsAreUids(bool* result) {
+ *result = m_idsAreUids;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsImapUrl::SetExtraStatus(int32_t aExtraStatus) {
+ m_extraStatus = aExtraStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetExtraStatus(int32_t* aResult) {
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = m_extraStatus;
+ return NS_OK;
+}
+
+// this method is only called from the imap thread
+NS_IMETHODIMP nsImapUrl::GetMsgFlags(
+ imapMessageFlagsType* result) // kAddMsgFlags or kSubtractMsgFlags only
+{
+ *result = m_flags;
+ return NS_OK;
+}
+
+void nsImapUrl::ParseImapPart(char* imapPartOfUrl) {
+ m_tokenPlaceHolder = imapPartOfUrl;
+ m_urlidSubString = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)NULL;
+
+ if (!m_urlidSubString) {
+ m_validUrl = false;
+ return;
+ }
+
+ if (!PL_strcasecmp(m_urlidSubString, "fetch")) {
+ m_imapAction = nsImapMsgFetch;
+ ParseUidChoice();
+ PR_FREEIF(m_sourceCanonicalFolderPathSubString);
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ // if fetched by spam filter, the action will be changed to
+ // nsImapMsgFetchPeek
+ } else {
+ if (!PL_strcasecmp(m_urlidSubString, "header")) {
+ m_imapAction = nsImapMsgHeader;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ } else if (!PL_strcasecmp(m_urlidSubString, "customFetch")) {
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseCustomMsgFetchAttribute();
+ } else if (!PL_strcasecmp(m_urlidSubString, "previewBody")) {
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseNumBytes();
+ } else if (!PL_strcasecmp(m_urlidSubString, "deletemsg")) {
+ m_imapAction = nsImapDeleteMsg;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ } else if (!PL_strcasecmp(m_urlidSubString, "uidexpunge")) {
+ m_imapAction = nsImapUidExpunge;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ } else if (!PL_strcasecmp(m_urlidSubString, "deleteallmsgs")) {
+ m_imapAction = nsImapDeleteAllMsgs;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "addmsgflags")) {
+ m_imapAction = nsImapAddMsgFlags;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseMsgFlags();
+ } else if (!PL_strcasecmp(m_urlidSubString, "subtractmsgflags")) {
+ m_imapAction = nsImapSubtractMsgFlags;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseMsgFlags();
+ } else if (!PL_strcasecmp(m_urlidSubString, "setmsgflags")) {
+ m_imapAction = nsImapSetMsgFlags;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseMsgFlags();
+ } else if (!PL_strcasecmp(m_urlidSubString, "onlinecopy")) {
+ m_imapAction = nsImapOnlineCopy;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "onlinemove")) {
+ m_imapAction = nsImapOnlineMove;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "onlinetoofflinecopy")) {
+ m_imapAction = nsImapOnlineToOfflineCopy;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "onlinetoofflinemove")) {
+ m_imapAction = nsImapOnlineToOfflineMove;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "offlinetoonlinecopy")) {
+ m_imapAction = nsImapOfflineToOnlineMove;
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "search")) {
+ m_imapAction = nsImapSearch;
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseSearchCriteriaString();
+ } else if (!PL_strcasecmp(m_urlidSubString, "test")) {
+ m_imapAction = nsImapTest;
+ } else if (!PL_strcasecmp(m_urlidSubString, "select")) {
+ m_imapAction = nsImapSelectFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ if (m_tokenPlaceHolder && *m_tokenPlaceHolder)
+ ParseListOfMessageIds();
+ else
+ m_listOfMessageIds = PL_strdup("");
+ } else if (!PL_strcasecmp(m_urlidSubString, "liteselect")) {
+ m_imapAction = nsImapLiteSelectFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "selectnoop")) {
+ m_imapAction = nsImapSelectNoopFolder;
+ m_listOfMessageIds = PL_strdup("");
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "expunge")) {
+ m_imapAction = nsImapExpungeFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ m_listOfMessageIds = PL_strdup(""); // no ids to UNDO
+ } else if (!PL_strcasecmp(m_urlidSubString, "create")) {
+ m_imapAction = nsImapCreateFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "ensureExists")) {
+ m_imapAction = nsImapEnsureExistsFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "discoverchildren")) {
+ m_imapAction = nsImapDiscoverChildrenUrl;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "discoverallboxes")) {
+ m_imapAction = nsImapDiscoverAllBoxesUrl;
+ } else if (!PL_strcasecmp(m_urlidSubString,
+ "discoverallandsubscribedboxes")) {
+ m_imapAction = nsImapDiscoverAllAndSubscribedBoxesUrl;
+ } else if (!PL_strcasecmp(m_urlidSubString, "delete")) {
+ m_imapAction = nsImapDeleteFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "deletefolder")) {
+ m_imapAction = nsImapDeleteFolderAndMsgs;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "rename")) {
+ m_imapAction = nsImapRenameFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "movefolderhierarchy")) {
+ m_imapAction = nsImapMoveFolderHierarchy;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ if (m_tokenPlaceHolder && *m_tokenPlaceHolder) // handle promote to root
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "list")) {
+ m_imapAction = nsImapLsubFolders;
+ ParseFolderPath(&m_destinationCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "biff")) {
+ m_imapAction = nsImapBiff;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ } else if (!PL_strcasecmp(m_urlidSubString, "netscape")) {
+ m_imapAction = nsImapGetMailAccountUrl;
+ } else if (!PL_strcasecmp(m_urlidSubString, "appendmsgfromfile")) {
+ m_imapAction = nsImapAppendMsgFromFile;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "appenddraftfromfile")) {
+ m_imapAction = nsImapAppendDraftFromFile;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseUidChoice();
+ if (m_tokenPlaceHolder && *m_tokenPlaceHolder)
+ ParseListOfMessageIds();
+ else
+ m_listOfMessageIds = strdup("");
+ } else if (!PL_strcasecmp(m_urlidSubString, "subscribe")) {
+ m_imapAction = nsImapSubscribe;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "unsubscribe")) {
+ m_imapAction = nsImapUnsubscribe;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "refreshacl")) {
+ m_imapAction = nsImapRefreshACL;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "refreshfolderurls")) {
+ m_imapAction = nsImapRefreshFolderUrls;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "refreshallacls")) {
+ m_imapAction = nsImapRefreshAllACLs;
+ } else if (!PL_strcasecmp(m_urlidSubString, "listfolder")) {
+ m_imapAction = nsImapListFolder;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "upgradetosubscription")) {
+ m_imapAction = nsImapUpgradeToSubscription;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "folderstatus")) {
+ m_imapAction = nsImapFolderStatus;
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ } else if (!PL_strcasecmp(m_urlidSubString, "verifyLogon")) {
+ m_imapAction = nsImapVerifylogon;
+ } else if (m_imapAction == nsIImapUrl::nsImapUserDefinedMsgCommand) {
+ m_command = m_urlidSubString; // save this
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ } else if (m_imapAction == nsIImapUrl::nsImapMsgStoreCustomKeywords) {
+ ParseUidChoice();
+ ParseFolderPath(&m_sourceCanonicalFolderPathSubString);
+ ParseListOfMessageIds();
+ bool addKeyword = (m_tokenPlaceHolder && *m_tokenPlaceHolder != '>');
+ // if we're not adding a keyword, m_tokenPlaceHolder will now look like
+ // >keywordToSubtract> and strtok will leave flagsPtr pointing to
+ // keywordToSubtract. So detect this case and only set the
+ // customSubtractFlags.
+ char* flagsPtr = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)nullptr;
+ if (addKeyword) {
+ m_customAddFlags.Assign(flagsPtr);
+ flagsPtr = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)nullptr;
+ }
+ m_customSubtractFlags.Assign(flagsPtr);
+ } else {
+ m_validUrl = false;
+ }
+ }
+}
+
+// Returns NULL if nothing was done.
+// Otherwise, returns a newly allocated name.
+NS_IMETHODIMP nsImapUrl::AddOnlineDirectoryIfNecessary(
+ const char* onlineMailboxName, char** directory) {
+ nsresult rv;
+ nsString onlineDirString;
+ char* newOnlineName = nullptr;
+
+ nsCOMPtr<nsIImapHostSessionList> hostSessionList =
+ do_GetService(kCImapHostSessionListCID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = hostSessionList->GetOnlineDirForHost(m_serverKey.get(), onlineDirString);
+ nsAutoCString onlineDir;
+ LossyCopyUTF16toASCII(onlineDirString, onlineDir);
+
+ nsImapNamespace* ns = nullptr;
+ rv = hostSessionList->GetNamespaceForMailboxForHost(m_serverKey.get(),
+ onlineMailboxName, ns);
+ if (!ns)
+ hostSessionList->GetDefaultNamespaceOfTypeForHost(m_serverKey.get(),
+ kPersonalNamespace, ns);
+
+ if (onlineDir.IsEmpty() && ns) onlineDir = ns->GetPrefix();
+
+ // If this host has an online server directory configured
+ if (onlineMailboxName && !onlineDir.IsEmpty()) {
+ if (PL_strcasecmp(onlineMailboxName, "INBOX")) {
+ NS_ASSERTION(ns, "couldn't find namespace for host");
+ nsAutoCString onlineDirWithDelimiter(onlineDir);
+ // make sure the onlineDir ends with the hierarchy delimiter
+ if (ns) {
+ char delimiter = ns->GetDelimiter();
+ if (delimiter && delimiter != kOnlineHierarchySeparatorUnknown) {
+ // try to change the canonical online dir name to real dir name first
+ onlineDirWithDelimiter.ReplaceChar('/', delimiter);
+ // make sure the last character is the delimiter
+ if (onlineDirWithDelimiter.Last() != delimiter)
+ onlineDirWithDelimiter += delimiter;
+ if (!*onlineMailboxName)
+ onlineDirWithDelimiter.SetLength(onlineDirWithDelimiter.Length() -
+ 1);
+ }
+ }
+ if (ns && (PL_strlen(ns->GetPrefix()) != 0) &&
+ !onlineDirWithDelimiter.Equals(ns->GetPrefix())) {
+ // check that onlineMailboxName doesn't start with the namespace. If
+ // that's the case, we don't want to prepend the online dir.
+ if (PL_strncmp(onlineMailboxName, ns->GetPrefix(),
+ PL_strlen(ns->GetPrefix()))) {
+ // The namespace for this mailbox is the root ("").
+ // Prepend the online server directory
+ int finalLen =
+ onlineDirWithDelimiter.Length() + strlen(onlineMailboxName) + 1;
+ newOnlineName = (char*)PR_Malloc(finalLen);
+ if (newOnlineName) {
+ PL_strcpy(newOnlineName, onlineDirWithDelimiter.get());
+ PL_strcat(newOnlineName, onlineMailboxName);
+ }
+ }
+ }
+ // just prepend the online server directory if it doesn't start with it
+ // already
+ else if (strncmp(onlineMailboxName, onlineDirWithDelimiter.get(),
+ onlineDirWithDelimiter.Length())) {
+ newOnlineName = (char*)PR_Malloc(strlen(onlineMailboxName) +
+ onlineDirWithDelimiter.Length() + 1);
+ if (newOnlineName) {
+ PL_strcpy(newOnlineName, onlineDirWithDelimiter.get());
+ PL_strcat(newOnlineName, onlineMailboxName);
+ }
+ }
+ }
+ }
+ if (directory)
+ *directory = newOnlineName;
+ else if (newOnlineName)
+ free(newOnlineName);
+ return rv;
+}
+
+// Converts from canonical format (hierarchy is indicated by '/' and all real
+// slashes ('/') are escaped) to the real online name on the server.
+NS_IMETHODIMP nsImapUrl::AllocateServerPath(const char* canonicalPath,
+ char onlineDelimiter,
+ char** aAllocatedPath) {
+ nsresult retVal = NS_OK;
+ char* rv = NULL;
+ char delimiterToUse = onlineDelimiter;
+ if (onlineDelimiter == kOnlineHierarchySeparatorUnknown)
+ GetOnlineSubDirSeparator(&delimiterToUse);
+ NS_ASSERTION(delimiterToUse != kOnlineHierarchySeparatorUnknown,
+ "hierarchy separator unknown");
+ if (canonicalPath)
+ rv = ReplaceCharsInCopiedString(canonicalPath, '/', delimiterToUse);
+ else
+ rv = strdup("");
+
+ if (delimiterToUse != '/') UnescapeSlashes(rv);
+ char* onlineNameAdded = nullptr;
+ AddOnlineDirectoryIfNecessary(rv, &onlineNameAdded);
+ if (onlineNameAdded) {
+ free(rv);
+ rv = onlineNameAdded;
+ }
+
+ if (aAllocatedPath)
+ *aAllocatedPath = rv;
+ else
+ free(rv);
+
+ return retVal;
+}
+
+// escape '/' as ^, ^ -> ^^ - use UnescapeSlashes to revert
+/* static */ nsresult nsImapUrl::EscapeSlashes(const char* sourcePath,
+ char** resultPath) {
+ NS_ENSURE_ARG(sourcePath);
+ NS_ENSURE_ARG(resultPath);
+ int32_t extra = 0;
+ int32_t len = strlen(sourcePath);
+ const char* src = sourcePath;
+ int32_t i;
+ for (i = 0; i < len; i++) {
+ if (*src == '^') extra += 1; /* ^ -> ^^ */
+ src++;
+ }
+ char* result = (char*)moz_xmalloc(len + extra + 1);
+ if (!result) return NS_ERROR_OUT_OF_MEMORY;
+
+ unsigned char* dst = (unsigned char*)result;
+ src = sourcePath;
+ for (i = 0; i < len; i++) {
+ unsigned char c = *src++;
+ if (c == '/')
+ *dst++ = '^';
+ else if (c == '^') {
+ *dst++ = '^';
+ *dst++ = '^';
+ } else
+ *dst++ = c;
+ }
+ *dst = '\0'; /* tack on eos */
+ *resultPath = result;
+ return NS_OK;
+}
+
+static void unescapeSlashes(char* path, size_t* newLength) {
+ char* src = path;
+ char* start = src;
+ char* dst = path;
+
+ while (*src) {
+ if (*src == '^') {
+ if (*(src + 1) == '^') {
+ *dst++ = '^';
+ src++; // skip over second '^'
+ } else
+ *dst++ = '/';
+ src++;
+ } else
+ *dst++ = *src++;
+ }
+
+ *newLength = dst - start;
+}
+
+/* static */ nsresult nsImapUrl::UnescapeSlashes(char* path) {
+ size_t newLength;
+ unescapeSlashes(path, &newLength);
+ path[newLength] = 0;
+ return NS_OK;
+}
+
+/* static */ nsresult nsImapUrl::UnescapeSlashes(nsACString& path) {
+ size_t newLength;
+ unescapeSlashes(path.BeginWriting(), &newLength);
+ path.SetLength(newLength);
+ return NS_OK;
+}
+
+/* static */ nsresult nsImapUrl::ConvertToCanonicalFormat(
+ const char* folderName, char onlineDelimiter,
+ char** resultingCanonicalPath) {
+ // Now, start the conversion to canonical form.
+
+ char* canonicalPath;
+ if (onlineDelimiter != '/') {
+ nsCString escapedPath;
+
+ EscapeSlashes(folderName, getter_Copies(escapedPath));
+ canonicalPath =
+ ReplaceCharsInCopiedString(escapedPath.get(), onlineDelimiter, '/');
+ } else {
+ canonicalPath = strdup(folderName);
+ }
+ if (canonicalPath) *resultingCanonicalPath = canonicalPath;
+
+ return (canonicalPath) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+// Converts the real online name on the server to canonical format:
+// result is hierarchy is indicated by '/' and all real slashes ('/') are
+// escaped. This method is only called from the IMAP thread.
+NS_IMETHODIMP nsImapUrl::AllocateCanonicalPath(const char* serverPath,
+ char onlineDelimiter,
+ char** allocatedPath) {
+ NS_ENSURE_ARG_POINTER(serverPath);
+
+ char delimiterToUse = onlineDelimiter;
+ *allocatedPath = nullptr;
+
+ char* currentPath = (char*)serverPath;
+
+ nsresult rv;
+ nsCOMPtr<nsIImapHostSessionList> hostSessionList =
+ do_GetService(kCImapHostSessionListCID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (onlineDelimiter == kOnlineHierarchySeparatorUnknown ||
+ onlineDelimiter == 0)
+ GetOnlineSubDirSeparator(&delimiterToUse);
+
+ nsString dir;
+ hostSessionList->GetOnlineDirForHost(m_serverKey.get(), dir);
+ // First we have to check to see if we should strip off an online server
+ // subdirectory
+ // If this host has an online server directory configured
+ nsAutoCString onlineDir;
+ LossyCopyUTF16toASCII(dir, onlineDir);
+
+ if (!onlineDir.IsEmpty()) {
+ // By definition, the online dir must be at the root.
+ if (delimiterToUse && delimiterToUse != kOnlineHierarchySeparatorUnknown) {
+ // try to change the canonical online dir name to real dir name first
+ onlineDir.ReplaceChar('/', delimiterToUse);
+ // Add the delimiter
+ if (onlineDir.Last() != delimiterToUse) onlineDir += delimiterToUse;
+ }
+ int len = onlineDir.Length();
+ if (!PL_strncmp(onlineDir.get(), currentPath, len)) {
+ // This online path begins with the server sub directory
+ currentPath += len;
+
+ // This might occur, but it's most likely something not good.
+ // Basically, it means we're doing something on the online sub directory
+ // itself.
+ NS_ASSERTION(*currentPath, "Oops ... null currentPath");
+ // Also make sure that the first character in the mailbox name is not '/'.
+ NS_ASSERTION(*currentPath != '/',
+ "Oops ... currentPath starts with a slash");
+ }
+ }
+
+ return ConvertToCanonicalFormat(currentPath, delimiterToUse, allocatedPath);
+}
+
+// this method is only called from the imap thread
+NS_IMETHODIMP nsImapUrl::CreateServerSourceFolderPathString(char** result) {
+ NS_ENSURE_ARG_POINTER(result);
+ AllocateServerPath(m_sourceCanonicalFolderPathSubString,
+ kOnlineHierarchySeparatorUnknown, result);
+ return NS_OK;
+}
+
+// this method is called from the imap thread AND the UI thread...
+NS_IMETHODIMP nsImapUrl::CreateCanonicalSourceFolderPathString(char** result) {
+ NS_ENSURE_ARG_POINTER(result);
+ MutexAutoLock mon(mLock);
+ *result = strdup(m_sourceCanonicalFolderPathSubString
+ ? m_sourceCanonicalFolderPathSubString
+ : "");
+ return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+// this method is called from the imap thread AND the UI thread...
+NS_IMETHODIMP nsImapUrl::CreateServerDestinationFolderPathString(
+ char** result) {
+ NS_ENSURE_ARG_POINTER(result);
+ MutexAutoLock mon(mLock);
+ nsresult rv = AllocateServerPath(m_destinationCanonicalFolderPathSubString,
+ kOnlineHierarchySeparatorUnknown, result);
+ return (*result) ? rv : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMETHODIMP nsImapUrl::SetMimePartSelectorDetected(
+ bool mimePartSelectorDetected) {
+ m_mimePartSelectorDetected = mimePartSelectorDetected;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetMimePartSelectorDetected(
+ bool* mimePartSelectorDetected) {
+ if (!mimePartSelectorDetected) return NS_ERROR_NULL_POINTER;
+
+ *mimePartSelectorDetected = m_mimePartSelectorDetected;
+ return NS_OK;
+}
+
+// this method is only called from the UI thread.
+NS_IMETHODIMP nsImapUrl::SetCopyState(nsISupports* copyState) {
+ MutexAutoLock mon(mLock);
+ m_copyState = copyState;
+ return NS_OK;
+}
+
+// this method is only called from the imap thread..but we still
+// need a monitor 'cause the setter is called from the UI thread.
+NS_IMETHODIMP nsImapUrl::GetCopyState(nsISupports** copyState) {
+ NS_ENSURE_ARG_POINTER(copyState);
+ MutexAutoLock mon(mLock);
+ NS_IF_ADDREF(*copyState = m_copyState);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsImapUrl::SetMsgFile(nsIFile* aFile) {
+ nsresult rv = NS_OK;
+ MutexAutoLock mon(mLock);
+ m_file = aFile;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsImapUrl::GetMsgFile(nsIFile** aFile) {
+ NS_ENSURE_ARG_POINTER(aFile);
+
+ MutexAutoLock mon(mLock);
+ NS_IF_ADDREF(*aFile = m_file);
+ return NS_OK;
+}
+
+// this method is called from the UI thread..
+NS_IMETHODIMP nsImapUrl::GetMockChannel(nsIImapMockChannel** aChannel) {
+ NS_ENSURE_ARG_POINTER(aChannel);
+ MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
+ "should only access mock channel on ui thread");
+ *aChannel = nullptr;
+ nsCOMPtr<nsIImapMockChannel> channel(do_QueryReferent(m_channelWeakPtr));
+ channel.forget(aChannel);
+ return *aChannel ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsImapUrl::SetMockChannel(nsIImapMockChannel* aChannel) {
+ MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
+ "should only access mock channel on ui thread");
+ m_channelWeakPtr = do_GetWeakReference(aChannel);
+ return NS_OK;
+}
+
+nsresult nsImapUrl::Clone(nsIURI** _retval) {
+ nsresult rv = nsMsgMailNewsUrl::Clone(_retval);
+ NS_ENSURE_SUCCESS(rv, rv);
+ // also clone the mURI member, because GetUri below won't work if
+ // mURI isn't set due to escaping issues.
+ nsCOMPtr<nsIMsgMessageUrl> clonedUrl = do_QueryInterface(*_retval);
+ if (clonedUrl) clonedUrl->SetUri(mURI);
+ return rv;
+}
+
+NS_IMETHODIMP nsImapUrl::GetNormalizedSpec(nsACString& aPrincipalSpec) {
+ // URLs look like this:
+ // imap://user@domain@server:port/fetch>UID>folder>nn
+ // We simply strip any query part beginning with ? & or /;
+ // Normalized spec: imap://user@domain@server:port/fetch>UID>folder>nn
+ nsCOMPtr<nsIMsgMailNewsUrl> mailnewsURL;
+ QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(mailnewsURL));
+
+ nsAutoCString spec;
+ mailnewsURL->GetSpecIgnoringRef(spec);
+
+ // Strip any query part beginning with ? or /;
+ MsgRemoveQueryPart(spec);
+
+ aPrincipalSpec.Assign(spec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetUri(const nsACString& aURI) {
+ mURI = aURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetUri(nsACString& aURI) {
+ nsresult rv = NS_OK;
+ if (!mURI.IsEmpty())
+ aURI = mURI;
+ else {
+ uint32_t key =
+ m_listOfMessageIds ? strtoul(m_listOfMessageIds, nullptr, 10) : 0;
+ nsCString canonicalPath;
+ AllocateCanonicalPath(m_sourceCanonicalFolderPathSubString,
+ m_onlineSubDirSeparator,
+ (getter_Copies(canonicalPath)));
+ nsCString fullFolderPath("/");
+ fullFolderPath.Append(m_userName);
+ nsAutoCString hostName;
+ rv = GetHost(hostName);
+ fullFolderPath.Append('@');
+ fullFolderPath.Append(hostName);
+ fullFolderPath.Append('/');
+ fullFolderPath.Append(canonicalPath);
+
+ nsCString baseMessageURI;
+ nsCreateImapBaseMessageURI(fullFolderPath, baseMessageURI);
+ rv = nsBuildImapMessageURI(baseMessageURI.get(), key, aURI);
+ }
+ return rv;
+}
+
+NS_IMPL_GETSET(nsImapUrl, AddDummyEnvelope, bool, m_addDummyEnvelope)
+NS_IMPL_GETSET(nsImapUrl, CanonicalLineEnding, bool, m_canonicalLineEnding)
+NS_IMETHODIMP nsImapUrl::GetMsgLoadingFromCache(bool* result) {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = m_msgLoadingFromCache;
+ return NS_OK;
+}
+NS_IMPL_GETSET(nsImapUrl, LocalFetchOnly, bool, m_localFetchOnly)
+NS_IMPL_GETSET(nsImapUrl, ExternalLinkUrl, bool, m_externalLinkUrl)
+NS_IMPL_GETSET(nsImapUrl, RerunningUrl, bool, m_rerunningUrl)
+NS_IMPL_GETSET(nsImapUrl, ValidUrl, bool, m_validUrl)
+NS_IMPL_GETSET(nsImapUrl, MoreHeadersToDownload, bool, m_moreHeadersToDownload)
+
+NS_IMETHODIMP nsImapUrl::SetMsgLoadingFromCache(bool loadingFromCache) {
+ nsresult rv = NS_OK;
+ m_msgLoadingFromCache = loadingFromCache;
+ return rv;
+}
+
+NS_IMETHODIMP nsImapUrl::SetMessageFile(nsIFile* aFile) {
+ m_messageFile = aFile;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetMessageFile(nsIFile** aFile) {
+ if (aFile) NS_IF_ADDREF(*aFile = m_messageFile);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::IsUrlType(uint32_t type, bool* isType) {
+ NS_ENSURE_ARG(isType);
+
+ switch (type) {
+ case nsIMsgMailNewsUrl::eCopy:
+ *isType = ((m_imapAction == nsIImapUrl::nsImapOnlineCopy) ||
+ (m_imapAction == nsIImapUrl::nsImapOnlineToOfflineCopy) ||
+ (m_imapAction == nsIImapUrl::nsImapOfflineToOnlineCopy));
+ break;
+ case nsIMsgMailNewsUrl::eMove:
+ *isType = ((m_imapAction == nsIImapUrl::nsImapOnlineMove) ||
+ (m_imapAction == nsIImapUrl::nsImapOnlineToOfflineMove) ||
+ (m_imapAction == nsIImapUrl::nsImapOfflineToOnlineMove));
+ break;
+ case nsIMsgMailNewsUrl::eDisplay:
+ *isType = (m_imapAction == nsIImapUrl::nsImapMsgFetch ||
+ m_imapAction == nsIImapUrl::nsImapMsgFetchPeek);
+ break;
+ default:
+ *isType = false;
+ };
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsImapUrl::GetOriginalSpec(nsACString& aSpec) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsImapUrl::SetOriginalSpec(const nsACString& aSpec) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+char* nsImapUrl::ReplaceCharsInCopiedString(const char* stringToCopy,
+ char oldChar, char newChar) {
+ char oldCharString[2];
+ *oldCharString = oldChar;
+ *(oldCharString + 1) = 0;
+
+ char* translatedString = PL_strdup(stringToCopy);
+ char* currentSeparator = PL_strstr(translatedString, oldCharString);
+
+ while (currentSeparator) {
+ *currentSeparator = newChar;
+ currentSeparator = PL_strstr(currentSeparator + 1, oldCharString);
+ }
+
+ return translatedString;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// End of functions which should be made obsolete after modifying nsIURI
+////////////////////////////////////////////////////////////////////////////////////
+
+void nsImapUrl::ParseFolderPath(char** resultingCanonicalPath) {
+ char* resultPath = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)NULL;
+
+ if (!resultPath) {
+ m_validUrl = false;
+ return;
+ }
+ NS_ASSERTION(*resultingCanonicalPath == nullptr, "whoops, mem leak");
+
+ char dirSeparator = *resultPath;
+
+ nsCString unescapedResultingCanonicalPath;
+ MsgUnescapeString(nsDependentCString(resultPath + 1), 0,
+ unescapedResultingCanonicalPath);
+ *resultingCanonicalPath = ToNewCString(unescapedResultingCanonicalPath);
+ // The delimiter will be set for a given URL, but will not be statically
+ // available from an arbitrary URL. It is the creator's responsibility to
+ // fill in the correct delimiter from the folder's namespace when creating the
+ // URL.
+ if (dirSeparator != kOnlineHierarchySeparatorUnknown)
+ SetOnlineSubDirSeparator(dirSeparator);
+
+ // if dirSeparator == kOnlineHierarchySeparatorUnknown, then this must be a
+ // create of a top level imap box. If there is an online subdir, we will
+ // automatically use its separator. If there is not an online subdir, we
+ // don't need a separator.
+}
+
+void nsImapUrl::ParseSearchCriteriaString() {
+ if (m_tokenPlaceHolder) {
+ int quotedFlag = false;
+
+ // skip initial separator
+ while (*m_tokenPlaceHolder == *IMAP_URL_TOKEN_SEPARATOR)
+ m_tokenPlaceHolder++;
+
+ char* saveTokenPlaceHolder = m_tokenPlaceHolder;
+
+ // m_searchCriteriaString = m_tokenPlaceHolder;
+
+ // looking for another separator outside quoted string
+ while (*m_tokenPlaceHolder) {
+ if (*m_tokenPlaceHolder == '\\' && *(m_tokenPlaceHolder + 1) == '"')
+ m_tokenPlaceHolder++;
+ else if (*m_tokenPlaceHolder == '"')
+ quotedFlag = !quotedFlag;
+ else if (!quotedFlag &&
+ *m_tokenPlaceHolder == *IMAP_URL_TOKEN_SEPARATOR) {
+ *m_tokenPlaceHolder = '\0';
+ m_tokenPlaceHolder++;
+ break;
+ }
+ m_tokenPlaceHolder++;
+ }
+ m_searchCriteriaString = PL_strdup(saveTokenPlaceHolder);
+ if (*m_tokenPlaceHolder == '\0') m_tokenPlaceHolder = NULL;
+
+ if (*m_searchCriteriaString == '\0') m_searchCriteriaString = (char*)NULL;
+ } else
+ m_searchCriteriaString = (char*)NULL;
+ if (!m_searchCriteriaString) m_validUrl = false;
+}
+
+void nsImapUrl::ParseUidChoice() {
+ char* uidChoiceString =
+ m_tokenPlaceHolder
+ ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR, &m_tokenPlaceHolder)
+ : (char*)NULL;
+ if (!uidChoiceString)
+ m_validUrl = false;
+ else
+ m_idsAreUids = strcmp(uidChoiceString, "UID") == 0;
+}
+
+void nsImapUrl::ParseMsgFlags() {
+ char* flagsPtr = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)NULL;
+ if (flagsPtr) {
+ // the url is encodes the flags byte as ascii
+ int intFlags = atoi(flagsPtr);
+ m_flags = (imapMessageFlagsType)intFlags; // cast here
+ } else
+ m_flags = 0;
+}
+
+void nsImapUrl::ParseListOfMessageIds() {
+ m_listOfMessageIds = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)NULL;
+ if (!m_listOfMessageIds)
+ m_validUrl = false;
+ else {
+ m_listOfMessageIds = strdup(m_listOfMessageIds);
+ m_mimePartSelectorDetected = PL_strstr(m_listOfMessageIds, "&part=") != 0 ||
+ PL_strstr(m_listOfMessageIds, "?part=") != 0;
+
+ // if it's a spam filter trying to fetch the msg, don't let it get marked
+ // read.
+ if (PL_strstr(m_listOfMessageIds, "?header=filter") != 0)
+ m_imapAction = nsImapMsgFetchPeek;
+ }
+}
+
+void nsImapUrl::ParseCustomMsgFetchAttribute() {
+ m_msgFetchAttribute = m_tokenPlaceHolder ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR,
+ &m_tokenPlaceHolder)
+ : (char*)nullptr;
+}
+
+void nsImapUrl::ParseNumBytes() {
+ const char* numBytes =
+ (m_tokenPlaceHolder)
+ ? NS_strtok(IMAP_URL_TOKEN_SEPARATOR, &m_tokenPlaceHolder)
+ : 0;
+ m_numBytesToFetch = numBytes ? atoi(numBytes) : 0;
+}
+
+// nsIMsgI18NUrl support
+
+nsresult nsImapUrl::GetMsgFolder(nsIMsgFolder** msgFolder) {
+ // if we have a RDF URI, then try to get the folder for that URI and then ask
+ // the folder for it's charset....
+
+ nsCString uri;
+ GetUri(uri);
+ NS_ENSURE_TRUE(!uri.IsEmpty(), NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsIMsgDBHdr> msg;
+ GetMsgDBHdrFromURI(uri, getter_AddRefs(msg));
+ NS_ENSURE_TRUE(msg, NS_ERROR_FAILURE);
+ nsresult rv = msg->GetFolder(msgFolder);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ENSURE_TRUE(msgFolder, NS_ERROR_FAILURE);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetAutodetectCharset(bool* aAutodetectCharset) {
+ *aAutodetectCharset = mAutodetectCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetAutodetectCharset(bool aAutodetectCharset) {
+ mAutodetectCharset = aAutodetectCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetStoreResultsOffline(bool* aStoreResultsOffline) {
+ NS_ENSURE_ARG_POINTER(aStoreResultsOffline);
+ *aStoreResultsOffline = m_storeResultsOffline;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetStoreResultsOffline(bool aStoreResultsOffline) {
+ m_storeResultsOffline = aStoreResultsOffline;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetStoreOfflineOnFallback(
+ bool* aStoreOfflineOnFallback) {
+ NS_ENSURE_ARG_POINTER(aStoreOfflineOnFallback);
+ *aStoreOfflineOnFallback = m_storeOfflineOnFallback;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::SetStoreOfflineOnFallback(
+ bool aStoreOfflineOnFallback) {
+ m_storeOfflineOnFallback = aStoreOfflineOnFallback;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsImapUrl::GetMessageHeader(nsIMsgDBHdr** aMsgHdr) {
+ nsCString uri;
+ nsresult rv = GetUri(uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return GetMsgDBHdrFromURI(uri, aMsgHdr);
+}