summaryrefslogtreecommitdiffstats
path: root/mailnews/local/src/nsMailboxUrl.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /mailnews/local/src/nsMailboxUrl.cpp
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/local/src/nsMailboxUrl.cpp')
-rw-r--r--mailnews/local/src/nsMailboxUrl.cpp556
1 files changed, 556 insertions, 0 deletions
diff --git a/mailnews/local/src/nsMailboxUrl.cpp b/mailnews/local/src/nsMailboxUrl.cpp
new file mode 100644
index 000000000..25fe4f35f
--- /dev/null
+++ b/mailnews/local/src/nsMailboxUrl.cpp
@@ -0,0 +1,556 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "nsIURI.h"
+#include "nsIMailboxUrl.h"
+#include "nsMailboxUrl.h"
+
+#include "nsStringGlue.h"
+#include "nsLocalUtils.h"
+#include "nsIMsgDatabase.h"
+#include "nsMsgDBCID.h"
+#include "nsMsgBaseCID.h"
+#include "nsIMsgHdr.h"
+
+#include "nsIMsgFolder.h"
+#include "prprf.h"
+#include "prmem.h"
+#include "nsIMsgMailSession.h"
+#include "nsNetUtil.h"
+#include "nsIFileURL.h"
+
+// this is totally lame and MUST be removed by M6
+// the real fix is to attach the URI to the URL as it runs through netlib
+// then grab it and use it on the other side
+#include "nsCOMPtr.h"
+#include "nsMsgBaseCID.h"
+#include "nsIMsgAccountManager.h"
+#include "nsMsgUtils.h"
+#include "mozilla/Services.h"
+
+// helper function for parsing the search field of a url
+char * extractAttributeValue(const char * searchString, const char * attributeName);
+
+nsMailboxUrl::nsMailboxUrl()
+{
+ m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
+ m_filePath = nullptr;
+ m_messageID = nullptr;
+ m_messageKey = nsMsgKey_None;
+ m_messageSize = 0;
+ m_messageFile = nullptr;
+ m_addDummyEnvelope = false;
+ m_canonicalLineEnding = false;
+ m_curMsgIndex = 0;
+}
+
+nsMailboxUrl::~nsMailboxUrl()
+{
+ PR_Free(m_messageID);
+}
+
+NS_IMPL_ADDREF_INHERITED(nsMailboxUrl, nsMsgMailNewsUrl)
+NS_IMPL_RELEASE_INHERITED(nsMailboxUrl, nsMsgMailNewsUrl)
+
+NS_INTERFACE_MAP_BEGIN(nsMailboxUrl)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMailboxUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIMailboxUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIMsgMessageUrl)
+ NS_INTERFACE_MAP_ENTRY(nsIMsgI18NUrl)
+NS_INTERFACE_MAP_END_INHERITING(nsMsgMailNewsUrl)
+
+////////////////////////////////////////////////////////////////////////////////////
+// Begin nsIMailboxUrl specific support
+////////////////////////////////////////////////////////////////////////////////////
+nsresult nsMailboxUrl::SetMailboxParser(nsIStreamListener * aMailboxParser)
+{
+ if (aMailboxParser)
+ m_mailboxParser = aMailboxParser;
+ return NS_OK;
+}
+
+nsresult nsMailboxUrl::GetMailboxParser(nsIStreamListener ** aConsumer)
+{
+ NS_ENSURE_ARG_POINTER(aConsumer);
+
+ NS_IF_ADDREF(*aConsumer = m_mailboxParser);
+ return NS_OK;
+}
+
+nsresult nsMailboxUrl::SetMailboxCopyHandler(nsIStreamListener * aMailboxCopyHandler)
+{
+ if (aMailboxCopyHandler)
+ m_mailboxCopyHandler = aMailboxCopyHandler;
+ return NS_OK;
+}
+
+nsresult nsMailboxUrl::GetMailboxCopyHandler(nsIStreamListener ** aMailboxCopyHandler)
+{
+ NS_ENSURE_ARG_POINTER(aMailboxCopyHandler);
+
+ if (aMailboxCopyHandler)
+ {
+ *aMailboxCopyHandler = m_mailboxCopyHandler;
+ NS_IF_ADDREF(*aMailboxCopyHandler);
+ }
+
+ return NS_OK;
+}
+
+nsresult nsMailboxUrl::GetMessageKey(nsMsgKey* aMessageKey)
+{
+ *aMessageKey = m_messageKey;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetMessageSize(uint32_t * aMessageSize)
+{
+ if (aMessageSize)
+ {
+ *aMessageSize = m_messageSize;
+ return NS_OK;
+ }
+ else
+ return NS_ERROR_NULL_POINTER;
+}
+
+nsresult nsMailboxUrl::SetMessageSize(uint32_t aMessageSize)
+{
+ m_messageSize = aMessageSize;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetPrincipalSpec(nsACString& aPrincipalSpec)
+{
+ nsCOMPtr<nsIMsgMailNewsUrl> mailnewsURL;
+ QueryInterface(NS_GET_IID(nsIMsgMailNewsUrl), getter_AddRefs(mailnewsURL));
+
+ nsAutoCString spec;
+ mailnewsURL->GetSpecIgnoringRef(spec);
+
+ // mailbox: URLs contain a lot of query parts. We want need a normalised form:
+ // mailbox:///path/to/folder?number=nn.
+ // We also need to translate the second form mailbox://user@domain@server/folder?number=nn.
+
+ char* messageKey = extractAttributeValue(spec.get(), "number=");
+
+ // Strip any query part beginning with ? or /;
+ int32_t ind = spec.Find("/;");
+ if (ind != kNotFound)
+ spec.SetLength(ind);
+
+ ind = spec.FindChar('?');
+ if (ind != kNotFound)
+ spec.SetLength(ind);
+
+ // Check for format lacking absolute path.
+ if (spec.Find("///") == kNotFound) {
+ nsCString folderPath;
+ nsresult rv = nsLocalURI2Path(kMailboxRootURI, spec.get(), folderPath);
+ if (NS_SUCCEEDED (rv)) {
+ nsAutoCString buf;
+ MsgEscapeURL(folderPath,
+ nsINetUtil::ESCAPE_URL_DIRECTORY | nsINetUtil::ESCAPE_URL_FORCED, buf);
+ spec = NS_LITERAL_CSTRING("mailbox://") + buf;
+ }
+ }
+
+ spec += NS_LITERAL_CSTRING("?number=");
+ spec.Append(messageKey);
+ PR_Free(messageKey);
+
+ aPrincipalSpec.Assign(spec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetUri(const char * aURI)
+{
+ mURI= aURI;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::CloneInternal(uint32_t aRefHandlingMode,
+ const nsACString& newRef,
+ nsIURI **_retval)
+{
+ nsresult rv = nsMsgMailNewsUrl::CloneInternal(aRefHandlingMode,
+ newRef, _retval);
+ NS_ENSURE_SUCCESS(rv, rv);
+ // also clone the mURI member, because GetUri below won't work if
+ // mURI isn't set due to nsIFile fun.
+ nsCOMPtr <nsIMsgMessageUrl> clonedUrl = do_QueryInterface(*_retval);
+ if (clonedUrl)
+ clonedUrl->SetUri(mURI.get());
+ return rv;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetUri(char ** aURI)
+{
+ // if we have been given a uri to associate with this url, then use it
+ // otherwise try to reconstruct a URI on the fly....
+
+ if (!mURI.IsEmpty())
+ *aURI = ToNewCString(mURI);
+ else
+ {
+ if (m_filePath)
+ {
+ nsAutoCString baseUri;
+ nsresult rv;
+ nsCOMPtr<nsIMsgAccountManager> accountManager =
+ do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // we blow off errors here so that we can open attachments
+ // in .eml files.
+ (void) accountManager->FolderUriForPath(m_filePath, baseUri);
+ if (baseUri.IsEmpty()) {
+ rv = m_baseURL->GetSpec(baseUri);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ nsCString baseMessageURI;
+ nsCreateLocalBaseMessageURI(baseUri, baseMessageURI);
+ nsAutoCString uriStr;
+ nsBuildLocalMessageURI(baseMessageURI.get(), m_messageKey, uriStr);
+ *aURI = ToNewCString(uriStr);
+ }
+ else
+ *aURI = nullptr;
+ }
+
+ return NS_OK;
+}
+
+nsresult nsMailboxUrl::GetMsgHdrForKey(nsMsgKey msgKey, nsIMsgDBHdr ** aMsgHdr)
+{
+ nsresult rv = NS_OK;
+ if (aMsgHdr && m_filePath)
+ {
+ nsCOMPtr<nsIMsgDatabase> mailDBFactory;
+ nsCOMPtr<nsIMsgDatabase> mailDB;
+ nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
+
+ if (msgDBService)
+ rv = msgDBService->OpenMailDBFromFile(m_filePath, nullptr, false,
+ false, getter_AddRefs(mailDB));
+ if (NS_SUCCEEDED(rv) && mailDB) // did we get a db back?
+ rv = mailDB->GetMsgHdrForKey(msgKey, aMsgHdr);
+ else
+ {
+ nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindowWeak));
+ if (!msgWindow)
+ {
+ nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
+ }
+
+ // maybe this is .eml file we're trying to read. See if we can get a header from the header sink.
+ if (msgWindow)
+ {
+ nsCOMPtr<nsIMsgHeaderSink> headerSink;
+ msgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
+ if (headerSink)
+ {
+ rv = headerSink->GetDummyMsgHeader(aMsgHdr);
+ if (NS_SUCCEEDED(rv))
+ {
+ int64_t fileSize = 0;
+ m_filePath->GetFileSize(&fileSize);
+ (*aMsgHdr)->SetMessageSize(fileSize);
+ }
+ }
+ }
+ }
+ }
+ else
+ rv = NS_ERROR_NULL_POINTER;
+
+ return rv;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetMessageHeader(nsIMsgDBHdr ** aMsgHdr)
+{
+ if (m_dummyHdr)
+ {
+ NS_IF_ADDREF(*aMsgHdr = m_dummyHdr);
+ return NS_OK;
+ }
+ return GetMsgHdrForKey(m_messageKey, aMsgHdr);
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetMessageHeader(nsIMsgDBHdr *aMsgHdr)
+{
+ m_dummyHdr = aMsgHdr;
+ return NS_OK;
+}
+
+NS_IMPL_GETSET(nsMailboxUrl, AddDummyEnvelope, bool, m_addDummyEnvelope)
+NS_IMPL_GETSET(nsMailboxUrl, CanonicalLineEnding, bool, m_canonicalLineEnding)
+
+NS_IMETHODIMP
+nsMailboxUrl::GetOriginalSpec(char **aSpec)
+{
+ if (!aSpec || m_originalSpec.IsEmpty())
+ return NS_ERROR_NULL_POINTER;
+ *aSpec = ToNewCString(m_originalSpec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMailboxUrl::SetOriginalSpec(const char *aSpec)
+{
+ m_originalSpec = aSpec;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetMessageFile(nsIFile * aFile)
+{
+ m_messageFile = aFile;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetMessageFile(nsIFile ** aFile)
+{
+ // why don't we return an error for null aFile?
+ if (aFile)
+ NS_IF_ADDREF(*aFile = m_messageFile);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::IsUrlType(uint32_t type, bool *isType)
+{
+ NS_ENSURE_ARG(isType);
+
+ switch(type)
+ {
+ case nsIMsgMailNewsUrl::eCopy:
+ *isType = (m_mailboxAction == nsIMailboxUrl::ActionCopyMessage);
+ break;
+ case nsIMsgMailNewsUrl::eMove:
+ *isType = (m_mailboxAction == nsIMailboxUrl::ActionMoveMessage);
+ break;
+ case nsIMsgMailNewsUrl::eDisplay:
+ *isType = (m_mailboxAction == nsIMailboxUrl::ActionFetchMessage ||
+ m_mailboxAction == nsIMailboxUrl::ActionFetchPart);
+ break;
+ default:
+ *isType = false;
+ };
+
+ return NS_OK;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// End nsIMailboxUrl specific support
+////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// possible search part phrases include: MessageID=id&number=MessageKey
+
+nsresult nsMailboxUrl::ParseSearchPart()
+{
+ nsAutoCString searchPart;
+ nsresult rv = GetQuery(searchPart);
+ // add code to this function to decompose everything past the '?'.....
+ if (NS_SUCCEEDED(rv) && !searchPart.IsEmpty())
+ {
+ // the action for this mailbox must be a display message...
+ char * msgPart = extractAttributeValue(searchPart.get(), "part=");
+ if (msgPart) // if we have a part in the url then we must be fetching just the part.
+ m_mailboxAction = nsIMailboxUrl::ActionFetchPart;
+ else
+ m_mailboxAction = nsIMailboxUrl::ActionFetchMessage;
+
+ char * messageKey = extractAttributeValue(searchPart.get(), "number=");
+ m_messageID = extractAttributeValue(searchPart.get(),"messageid=");
+ if (messageKey)
+ m_messageKey = (nsMsgKey) ParseUint64Str(messageKey); // convert to a uint32_t...
+
+ PR_Free(msgPart);
+ PR_Free(messageKey);
+ }
+ else
+ m_mailboxAction = nsIMailboxUrl::ActionParseMailbox;
+
+ return rv;
+}
+
+// warning: don't assume when parsing the url that the protocol part is "news"...
+nsresult nsMailboxUrl::ParseUrl()
+{
+ GetFilePath(m_file);
+
+ ParseSearchPart();
+ // ### fix me.
+ // this hack is to avoid asserting on every local message loaded because the security manager
+ // is creating an empty "mailbox://" uri for every message.
+ if (m_file.Length() < 2)
+ m_filePath = nullptr;
+ else
+ {
+ nsCString fileUri("file://");
+ fileUri.Append(m_file);
+ nsresult rv;
+ nsCOMPtr<nsIIOService> ioService =
+ mozilla::services::GetIOService();
+ NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
+ nsCOMPtr <nsIURI> uri;
+ rv = ioService->NewURI(fileUri, nullptr, nullptr, getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr <nsIFileURL> fileURL = do_QueryInterface(uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr <nsIFile> fileURLFile;
+ fileURL->GetFile(getter_AddRefs(fileURLFile));
+ m_filePath = do_QueryInterface(fileURLFile, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ GetPath(m_file);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetSpec(const nsACString &aSpec)
+{
+ nsresult rv = nsMsgMailNewsUrl::SetSpec(aSpec);
+ if (NS_SUCCEEDED(rv))
+ rv = ParseUrl();
+ return rv;
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetQuery(const nsACString &aQuery)
+{
+ nsresult rv = nsMsgMailNewsUrl::SetQuery(aQuery);
+ if (NS_SUCCEEDED(rv))
+ rv = ParseUrl();
+ return rv;
+}
+
+// takes a string like ?messageID=fooo&number=MsgKey and returns a new string
+// containing just the attribute value. i.e you could pass in this string with
+// an attribute name of messageID and I'll return fooo. Use PR_Free to delete
+// this string...
+
+// Assumption: attribute pairs in the string are separated by '&'.
+char * extractAttributeValue(const char * searchString, const char * attributeName)
+{
+ char * attributeValue = nullptr;
+
+ if (searchString && attributeName)
+ {
+ // search the string for attributeName
+ uint32_t attributeNameSize = PL_strlen(attributeName);
+ char * startOfAttribute = PL_strcasestr(searchString, attributeName);
+ if (startOfAttribute)
+ {
+ startOfAttribute += attributeNameSize; // skip over the attributeName
+ if (startOfAttribute) // is there something after the attribute name
+ {
+ char * endOfAttribute = startOfAttribute ? PL_strchr(startOfAttribute, '&') : nullptr;
+ nsDependentCString attributeValueStr;
+ if (startOfAttribute && endOfAttribute) // is there text after attribute value
+ attributeValueStr.Assign(startOfAttribute, endOfAttribute - startOfAttribute);
+ else // there is nothing left so eat up rest of line.
+ attributeValueStr.Assign(startOfAttribute);
+
+ // now unescape the string...
+ nsCString unescapedValue;
+ MsgUnescapeString(attributeValueStr, 0, unescapedValue);
+ attributeValue = PL_strdup(unescapedValue.get());
+ } // if we have a attribute value
+
+ } // if we have a attribute name
+ } // if we got non-null search string and attribute name values
+
+ return attributeValue;
+}
+
+// nsIMsgI18NUrl support
+
+nsresult nsMailboxUrl::GetFolder(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(getter_Copies(uri));
+ NS_ENSURE_TRUE(!uri.IsEmpty(), NS_ERROR_FAILURE);
+ nsCOMPtr<nsIMsgDBHdr> msg;
+ GetMsgDBHdrFromURI(uri.get(), getter_AddRefs(msg));
+ if (!msg)
+ return NS_ERROR_FAILURE;
+ return msg->GetFolder(msgFolder);
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetFolderCharset(char ** aCharacterSet)
+{
+ NS_ENSURE_ARG_POINTER(aCharacterSet);
+ nsCOMPtr<nsIMsgFolder> folder;
+ nsresult rv = GetFolder(getter_AddRefs(folder));
+
+ // In cases where a file is not associated with a folder, for
+ // example standalone .eml files, failure is normal.
+ if (NS_FAILED(rv))
+ return rv;
+ nsCString tmpStr;
+ folder->GetCharset(tmpStr);
+ *aCharacterSet = ToNewCString(tmpStr);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetFolderCharsetOverride(bool * aCharacterSetOverride)
+{
+ nsCOMPtr<nsIMsgFolder> folder;
+ nsresult rv = GetFolder(getter_AddRefs(folder));
+ NS_ENSURE_SUCCESS(rv,rv);
+ NS_ENSURE_TRUE(folder, NS_ERROR_FAILURE);
+ folder->GetCharsetOverride(aCharacterSetOverride);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetCharsetOverRide(char ** aCharacterSet)
+{
+ if (!mCharsetOverride.IsEmpty())
+ *aCharacterSet = ToNewCString(mCharsetOverride);
+ else
+ *aCharacterSet = nullptr;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::SetCharsetOverRide(const char * aCharacterSet)
+{
+ mCharsetOverride = aCharacterSet;
+ return NS_OK;
+}
+
+/* void setMoveCopyMsgKeys (out nsMsgKey keysToFlag, in long numKeys); */
+NS_IMETHODIMP nsMailboxUrl::SetMoveCopyMsgKeys(nsMsgKey *keysToFlag, int32_t numKeys)
+{
+ m_keys.ReplaceElementsAt(0, m_keys.Length(), keysToFlag, numKeys);
+ if (!m_keys.IsEmpty() && m_messageKey == nsMsgKey_None)
+ m_messageKey = m_keys[0];
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetMoveCopyMsgHdrForIndex(uint32_t msgIndex, nsIMsgDBHdr **msgHdr)
+{
+ NS_ENSURE_ARG(msgHdr);
+ if (msgIndex < m_keys.Length())
+ {
+ nsMsgKey nextKey = m_keys[msgIndex];
+ return GetMsgHdrForKey(nextKey, msgHdr);
+ }
+ return NS_MSG_MESSAGE_NOT_FOUND;
+}
+
+NS_IMETHODIMP nsMailboxUrl::GetNumMoveCopyMsgs(uint32_t *numMsgs)
+{
+ NS_ENSURE_ARG(numMsgs);
+ *numMsgs = m_keys.Length();
+ return NS_OK;
+}