Source code

Revision control

Copy as Markdown

Other Tools

/* 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"
#include "nsMsgMailNewsUrl.h"
#include "nsIMsgAccountManager.h"
#include "nsIFeedbackService.h"
#include "nsIMsgWindow.h"
#include "nsString.h"
#include "nsILoadGroup.h"
#include "nsIDocShell.h"
#include "nsIWebProgressListener.h"
#include "nsIIOService.h"
#include "nsNetCID.h"
#include "nsIStreamListener.h"
#include "nsNetUtil.h"
#include "nsIFile.h"
#include <time.h>
#include "nsMsgUtils.h"
#include "mozilla/Components.h"
#include "nsProxyRelease.h"
#include "mozilla/Encoding.h"
#include "nsDocShellLoadState.h"
#include "nsContentUtils.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIChannel.h"
#include "SaveAsListener.h"
nsMsgMailNewsUrl::nsMsgMailNewsUrl() {
// nsIURI specific state
m_runningUrl = false;
m_updatingFolder = false;
m_msgIsInLocalCache = false;
m_suppressErrorMsgs = false;
m_hasNormalizedOrigin = false; // SetSpecInternal() will set this correctly.
mMaxProgress = -1;
}
#define NOTIFY_URL_LISTENERS(propertyfunc_, params_) \
PR_BEGIN_MACRO \
nsTObserverArray<nsCOMPtr<nsIUrlListener>>::ForwardIterator iter( \
mUrlListeners); \
while (iter.HasMore()) { \
nsCOMPtr<nsIUrlListener> listener = iter.GetNext(); \
listener->propertyfunc_ params_; \
} \
PR_END_MACRO
nsMsgMailNewsUrl::~nsMsgMailNewsUrl() {
// In IMAP this URL is created and destroyed on the imap thread,
// so we must ensure that releases of XPCOM objects (which might be
// implemented by non-threadsafe JS components) are released on the
// main thread.
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::m_baseURL", m_baseURL.forget());
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::mMimeHeaders",
mMimeHeaders.forget());
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::m_searchSession",
m_searchSession.forget());
// Weak references hold a non-threadsafe nsWeakReference proxy that is created
// on and belongs to the main thread, so it must be released there too.
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::m_msgWindowWeak",
m_msgWindowWeak.forget());
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::m_loadGroupWeak",
m_loadGroupWeak.forget());
nsTObserverArray<nsCOMPtr<nsIUrlListener>>::ForwardIterator iter(
mUrlListeners);
while (iter.HasMore()) {
nsCOMPtr<nsIUrlListener> listener = iter.GetNext();
if (listener)
NS_ReleaseOnMainThread("nsMsgMailNewsUrl::mUrlListeners",
listener.forget());
}
}
NS_IMPL_ADDREF(nsMsgMailNewsUrl)
NS_IMPL_RELEASE(nsMsgMailNewsUrl)
// We want part URLs to QI to nsIURIWithSpecialOrigin so we can give
// them a "normalized" origin. URLs that already have a "normalized"
// origin should not QI to nsIURIWithSpecialOrigin.
NS_INTERFACE_MAP_BEGIN(nsMsgMailNewsUrl)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMsgMailNewsUrl)
NS_INTERFACE_MAP_ENTRY(nsIMsgMailNewsUrl)
NS_INTERFACE_MAP_ENTRY(nsIURL)
NS_INTERFACE_MAP_ENTRY(nsIURI)
NS_INTERFACE_MAP_ENTRY(nsISerializable)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
NS_INTERFACE_MAP_ENTRY(nsIURIWithSizeOf)
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIURIWithSpecialOrigin,
m_hasNormalizedOrigin)
NS_INTERFACE_MAP_END
//--------------------------
// Support for serialization
//--------------------------
// nsMsgMailNewsUrl is only partly serialized by serializing the "base URL"
// which is an nsStandardURL, or by only serializing the Spec. This may
// cause problems in the future. See bug 1512356 and bug 1515337 for details,
// follow-up in bug 1512698.
void nsMsgMailNewsUrl::Serialize(mozilla::ipc::URIParams& aParams) {
nsCOMPtr<nsIIPCSerializableURI> serializable = do_QueryInterface(m_baseURL);
serializable->Serialize(aParams);
}
//----------------------------
// Support for nsISerializable
//----------------------------
NS_IMETHODIMP nsMsgMailNewsUrl::Read(nsIObjectInputStream* stream) {
nsAutoCString urlstr;
nsresult rv = NS_ReadOptionalCString(stream, urlstr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIIOService> ioService = mozilla::components::IO::Service();
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> url;
rv = ioService->NewURI(urlstr, nullptr, nullptr, getter_AddRefs(url));
NS_ENSURE_SUCCESS(rv, rv);
m_baseURL = do_QueryInterface(url);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::Write(nsIObjectOutputStream* stream) {
nsAutoCString urlstr;
nsresult rv = m_baseURL->GetSpec(urlstr);
NS_ENSURE_SUCCESS(rv, rv);
return NS_WriteOptionalStringZ(stream, urlstr.get());
}
//-------------------------
// Support for nsIClassInfo
//-------------------------
NS_IMETHODIMP nsMsgMailNewsUrl::GetInterfaces(nsTArray<nsIID>& array) {
array.Clear();
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetScriptableHelper(
nsIXPCScriptable** _retval) {
*_retval = nullptr;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetContractID(nsACString& aContractID) {
aContractID.SetIsVoid(true);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetClassDescription(
nsACString& aClassDescription) {
aClassDescription.SetIsVoid(true);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetClassID(nsCID** aClassID) {
*aClassID = (nsCID*)moz_xmalloc(sizeof(nsCID));
return GetClassIDNoAlloc(*aClassID);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFlags(uint32_t* aFlags) {
*aFlags = 0;
return NS_OK;
}
#define NS_MSGMAILNEWSURL_CID \
{0x3fdae3ab, 0x4ac1, 0x4ad4, {0xb2, 0x8a, 0x28, 0xd0, 0xfa, 0x36, 0x39, 0x29}}
static NS_DEFINE_CID(kNS_MSGMAILNEWSURL_CID, NS_MSGMAILNEWSURL_CID);
NS_IMETHODIMP nsMsgMailNewsUrl::GetClassIDNoAlloc(nsCID* aClassIDNoAlloc) {
*aClassIDNoAlloc = kNS_MSGMAILNEWSURL_CID;
return NS_OK;
}
//------------------------------------
// Support for nsIURIWithSpecialOrigin
//------------------------------------
NS_IMETHODIMP nsMsgMailNewsUrl::GetOrigin(nsIURI** aOrigin) {
MOZ_ASSERT(m_hasNormalizedOrigin,
"nsMsgMailNewsUrl::GetOrigin() can only be called for URLs with "
"normalized spec");
if (!m_normalizedOrigin) {
nsCOMPtr<nsIMsgMessageUrl> msgUrl;
QueryInterface(NS_GET_IID(nsIMsgMessageUrl), getter_AddRefs(msgUrl));
nsAutoCString spec;
if (!msgUrl || NS_FAILED(msgUrl->GetNormalizedSpec(spec))) {
MOZ_ASSERT(false, "Can't get normalized spec");
// just use the normal spec.
GetSpec(spec);
}
nsresult rv = NS_NewURI(getter_AddRefs(m_normalizedOrigin), spec);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_IF_ADDREF(*aOrigin = m_normalizedOrigin);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////////
// Begin nsIMsgMailNewsUrl specific support
////////////////////////////////////////////////////////////////////////////////////
nsresult nsMsgMailNewsUrl::GetUrlState(bool* aRunningUrl) {
if (aRunningUrl) *aRunningUrl = m_runningUrl;
return NS_OK;
}
nsresult nsMsgMailNewsUrl::SetUrlState(bool aRunningUrl, nsresult aExitCode) {
// if we already knew this running state, return, unless the url was aborted
if (m_runningUrl == aRunningUrl && aExitCode != NS_MSG_ERROR_URL_ABORTED) {
return NS_OK;
}
m_runningUrl = aRunningUrl;
// We need it for urls that don't run through the doc loader.
nsCOMPtr<nsIFeedbackService> feedback =
mozilla::components::Feedback::Service();
if (feedback) {
if (m_runningUrl) {
feedback->ReportStatus(""_ns, "start-meteors"_ns);
} else {
feedback->ReportProgress(0);
feedback->ReportStatus(""_ns, "stop-meteors"_ns);
}
}
if (m_runningUrl) {
NOTIFY_URL_LISTENERS(OnStartRunningUrl, (this));
} else {
NOTIFY_URL_LISTENERS(OnStopRunningUrl, (this, aExitCode));
mUrlListeners.Clear();
}
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::RegisterListener(nsIUrlListener* aUrlListener) {
NS_ENSURE_ARG_POINTER(aUrlListener);
mUrlListeners.AppendElement(aUrlListener);
return NS_OK;
}
nsresult nsMsgMailNewsUrl::UnRegisterListener(nsIUrlListener* aUrlListener) {
NS_ENSURE_ARG_POINTER(aUrlListener);
// Due to the way mailnews is structured, some listeners attempt to remove
// themselves twice. This may in fact be an error in the coding, however
// if they didn't do it as they do currently, then they could fail to remove
// their listeners.
mUrlListeners.RemoveElement(aUrlListener);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetServer(
nsIMsgIncomingServer** aIncomingServer) {
// mscott --> we could cache a copy of the server here....but if we did, we
// run the risk of leaking the server if any single url gets leaked....of
// course that shouldn't happen...but it could. so i'm going to look it up
// every time and we can look at caching it later.
nsresult rv;
nsAutoCString urlstr;
rv = m_baseURL->GetSpec(urlstr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> url;
rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.SetSpec(urlstr)
.Finalize(url);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString scheme;
rv = GetScheme(scheme);
if (NS_SUCCEEDED(rv)) {
if (scheme.EqualsLiteral("pop")) {
scheme.AssignLiteral("pop3");
}
// we use "nntp" in the server list so translate news/snews here.
if (scheme.EqualsLiteral("news") || scheme.EqualsLiteral("snews")) {
scheme.AssignLiteral("nntp");
}
rv = NS_MutateURI(url).SetScheme(scheme).Finalize(url);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgAccountManager> accountManager =
mozilla::components::AccountManager::Service();
nsCOMPtr<nsIMsgIncomingServer> server;
rv = accountManager->FindServerByURI(url, aIncomingServer);
if (!*aIncomingServer && scheme.EqualsLiteral("imap")) {
// look for any imap server with this host name so clicking on
// other users folder urls will work. We could override this method
// for imap urls, or we could make caching of servers work and
// just set the server in the imap code for this case.
rv = NS_MutateURI(url).SetUserPass(EmptyCString()).Finalize(url);
NS_ENSURE_SUCCESS(rv, rv);
rv = accountManager->FindServerByURI(url, aIncomingServer);
}
// A null server is valid for news URLs — they can be opened without
// any configured news accounts.
if (!*aIncomingServer && scheme.EqualsLiteral("nntp")) {
*aIncomingServer = nullptr;
return NS_OK;
}
}
return rv;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgWindow(nsIMsgWindow** aMsgWindow) {
NS_ENSURE_ARG_POINTER(aMsgWindow);
*aMsgWindow = nullptr;
nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindowWeak));
msgWindow.forget(aMsgWindow);
return *aMsgWindow ? NS_OK : NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgWindow(nsIMsgWindow* aMsgWindow) {
m_msgWindowWeak = do_GetWeakReference(aMsgWindow);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetMaxProgress(int64_t* aMaxProgress) {
*aMaxProgress = mMaxProgress;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetMaxProgress(int64_t aMaxProgress) {
mMaxProgress = aMaxProgress;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetLoadGroup(nsILoadGroup** aLoadGroup) {
*aLoadGroup = nullptr;
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetUpdatingFolder(bool* aResult) {
NS_ENSURE_ARG(aResult);
*aResult = m_updatingFolder;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetUpdatingFolder(bool updatingFolder) {
m_updatingFolder = updatingFolder;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetMsgIsInLocalCache(bool* aMsgIsInLocalCache) {
NS_ENSURE_ARG(aMsgIsInLocalCache);
*aMsgIsInLocalCache = m_msgIsInLocalCache;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetMsgIsInLocalCache(bool aMsgIsInLocalCache) {
m_msgIsInLocalCache = aMsgIsInLocalCache;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetSuppressErrorMsgs(bool* aSuppressErrorMsgs) {
NS_ENSURE_ARG(aSuppressErrorMsgs);
*aSuppressErrorMsgs = m_suppressErrorMsgs;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetSuppressErrorMsgs(bool aSuppressErrorMsgs) {
m_suppressErrorMsgs = aSuppressErrorMsgs;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetErrorCode(nsACString& aErrorCode) {
aErrorCode = m_errorCode;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetErrorCode(const nsACString& aErrorCode) {
m_errorCode.Assign(aErrorCode);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetErrorMessage(nsAString& aErrorMessage) {
aErrorMessage = m_errorMessage;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetErrorMessage(
const nsAString& aErrorMessage) {
m_errorMessage.Assign(aErrorMessage);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetSeeOtherURI(const nsACString& aSeeOtherURI) {
m_seeOtherURI.Assign(aSeeOtherURI);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetSeeOtherURI(nsACString& aSeeOtherURI) {
aSeeOtherURI = m_seeOtherURI;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::IsUrlType(uint32_t type, bool* isType) {
// base class doesn't know about any specific types
NS_ENSURE_ARG(isType);
*isType = false;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetSearchSession(
nsIMsgSearchSession* aSearchSession) {
if (aSearchSession) m_searchSession = aSearchSession;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetSearchSession(
nsIMsgSearchSession** aSearchSession) {
NS_ENSURE_ARG(aSearchSession);
NS_IF_ADDREF(*aSearchSession = m_searchSession);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////////
// End nsIMsgMailNewsUrl specific support
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// Begin nsIURI support
////////////////////////////////////////////////////////////////////////////////////
// Authority-less [s]news: URIs get extra slashes inserted in
// SetSpecInternal() so nsStandardURL can parse them. Remove them here.
static void unmungeNewsURL(nsACString& aSpec) {
if (StringBeginsWith(aSpec, "news:///"_ns)) {
aSpec.Cut(5, 3);
} else if (StringBeginsWith(aSpec, "snews:///"_ns)) {
aSpec.Cut(6, 3);
}
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetSpec(nsACString& aSpec) {
nsresult rv = m_baseURL->GetSpec(aSpec);
NS_ENSURE_SUCCESS(rv, rv);
unmungeNewsURL(aSpec);
return NS_OK;
}
uint32_t nsMsgMailNewsUrl::SpecHash() {
nsAutoCString spec;
(void)GetSpec(spec);
return CachedSpecHash(spec);
}
nsresult nsMsgMailNewsUrl::CreateURL(const nsACString& aSpec, nsIURL** aURL) {
nsCOMPtr<nsIURL> url;
nsresult rv = NS_MutateURI(NS_STANDARDURLMUTATOR_CONTRACTID)
.SetSpec(aSpec)
.Finalize(url);
NS_ENSURE_SUCCESS(rv, rv);
url.forget(aURL);
return NS_OK;
}
nsresult nsMsgMailNewsUrl::SetSpecInternal(const nsACString& aSpec) {
nsAutoCString lowerSpec(aSpec);
ToLowerCase(lowerSpec);
// Parse out "filename" attribute if present.
int32_t filenamePos = lowerSpec.Find("?filename="_ns);
if (filenamePos == kNotFound) {
filenamePos = lowerSpec.Find("&filename="_ns);
}
if (filenamePos != kNotFound) {
int32_t valuePos = filenamePos + 10;
int32_t endPos = lowerSpec.FindChar('&', valuePos);
if (endPos != kNotFound) {
mAttachmentFileName = Substring(aSpec, valuePos, endPos - valuePos);
} else {
mAttachmentFileName = Substring(aSpec, valuePos);
}
}
// For authority-less [s]news: URIs, insert three slashes so that
// nsStandardURL can parse them with an empty authority component.
// The extra slashes are removed in GetSpec() / GetDisplaySpec().
// See RFC 5538 section 4.
nsAutoCString parseSpec(aSpec);
// Use the lowercased copy for case-insensitive scheme matching.
if (StringBeginsWith(lowerSpec, "news:"_ns) && lowerSpec.Length() > 5 &&
aSpec[5] != '/') {
parseSpec.Insert("///", 5);
} else if (StringBeginsWith(lowerSpec, "snews:"_ns) &&
lowerSpec.Length() > 6 && aSpec[6] != '/') {
parseSpec.Insert("///", 6);
}
nsresult rv = CreateURL(parseSpec, getter_AddRefs(m_baseURL));
NS_ENSURE_SUCCESS(rv, rv);
// Check whether the URL is in normalized form.
nsCOMPtr<nsIMsgMessageUrl> msgUrl;
QueryInterface(NS_GET_IID(nsIMsgMessageUrl), getter_AddRefs(msgUrl));
nsAutoCString normalizedSpec;
if (!msgUrl || NS_FAILED(msgUrl->GetNormalizedSpec(normalizedSpec))) {
m_hasNormalizedOrigin = false;
} else {
m_hasNormalizedOrigin = !aSpec.Equals(normalizedSpec);
}
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetPrePath(nsACString& aPrePath) {
return m_baseURL->GetPrePath(aPrePath);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetScheme(nsACString& aScheme) {
return m_baseURL->GetScheme(aScheme);
}
nsresult nsMsgMailNewsUrl::SetScheme(const nsACString& aScheme) {
return NS_MutateURI(m_baseURL).SetScheme(aScheme).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetUserPass(nsACString& aUserPass) {
return m_baseURL->GetUserPass(aUserPass);
}
nsresult nsMsgMailNewsUrl::SetUserPass(const nsACString& aUserPass) {
return NS_MutateURI(m_baseURL).SetUserPass(aUserPass).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetUsername(nsACString& aUsername) {
/* note: this will return an escaped string */
return m_baseURL->GetUsername(aUsername);
}
nsresult nsMsgMailNewsUrl::SetUsername(const nsACString& aUsername) {
return NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
}
nsresult nsMsgMailNewsUrl::SetUsernameInternal(const nsACString& aUsername) {
return NS_MutateURI(m_baseURL).SetUsername(aUsername).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetPassword(nsACString& aPassword) {
return m_baseURL->GetPassword(aPassword);
}
nsresult nsMsgMailNewsUrl::SetPassword(const nsACString& aPassword) {
return NS_MutateURI(m_baseURL).SetPassword(aPassword).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetHostPort(nsACString& aHostPort) {
return m_baseURL->GetHostPort(aHostPort);
}
nsresult nsMsgMailNewsUrl::SetHostPort(const nsACString& aHostPort) {
return NS_MutateURI(m_baseURL).SetHostPort(aHostPort).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(nsACString& aHost) {
return m_baseURL->GetHost(aHost);
}
nsresult nsMsgMailNewsUrl::SetHost(const nsACString& aHost) {
return NS_MutateURI(m_baseURL).SetHost(aHost).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetPort(int32_t* aPort) {
return m_baseURL->GetPort(aPort);
}
nsresult nsMsgMailNewsUrl::SetPort(int32_t aPort) {
return NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
}
nsresult nsMsgMailNewsUrl::SetPortInternal(int32_t aPort) {
return NS_MutateURI(m_baseURL).SetPort(aPort).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetPathQueryRef(nsACString& aPath) {
return m_baseURL->GetPathQueryRef(aPath);
}
nsresult nsMsgMailNewsUrl::SetPathQueryRef(const nsACString& aPath) {
return NS_MutateURI(m_baseURL).SetPathQueryRef(aPath).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiHost(nsACString& aHostA) {
return m_baseURL->GetAsciiHost(aHostA);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiHostPort(nsACString& aHostPortA) {
return m_baseURL->GetAsciiHostPort(aHostPortA);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetAsciiSpec(nsACString& aSpecA) {
return m_baseURL->GetAsciiSpec(aSpecA);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetBaseURI(nsIURI** aBaseURI) {
NS_ENSURE_ARG_POINTER(aBaseURI);
return m_baseURL->QueryInterface(NS_GET_IID(nsIURI), (void**)aBaseURI);
}
NS_IMETHODIMP nsMsgMailNewsUrl::Equals(nsIURI* other, bool* _retval) {
// The passed-in URI might be a mail news url. Pass our inner URL to its
// Equals method. The other mail news url will then pass its inner URL to
// to the Equals method of our inner URL. Other URIs will return false.
if (other) return other->Equals(m_baseURL, _retval);
return m_baseURL->Equals(other, _retval);
}
NS_IMETHODIMP nsMsgMailNewsUrl::EqualsExceptRef(nsIURI* other, bool* result) {
// The passed-in URI might be a mail news url. Pass our inner URL to its
// Equals method. The other mail news url will then pass its inner URL to
// to the Equals method of our inner URL. Other URIs will return false.
if (other) return other->EqualsExceptRef(m_baseURL, result);
return m_baseURL->EqualsExceptRef(other, result);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetSpecIgnoringRef(nsACString& result) {
return m_baseURL->GetSpecIgnoringRef(result);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetDisplaySpec(nsACString& aUnicodeSpec) {
nsresult rv = m_baseURL->GetDisplaySpec(aUnicodeSpec);
NS_ENSURE_SUCCESS(rv, rv);
unmungeNewsURL(aUnicodeSpec);
return NS_OK;
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetDisplayHostPort(nsACString& aHostPort) {
return m_baseURL->GetDisplayHostPort(aHostPort);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetDisplayHost(nsACString& aHost) {
return m_baseURL->GetDisplayHost(aHost);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetDisplayPrePath(nsACString& aPrePath) {
return m_baseURL->GetDisplayPrePath(aPrePath);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::GetHasRef(bool* result) {
return m_baseURL->GetHasRef(result);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetHasUserPass(bool* aHasUserPass) {
nsAutoCString username;
GetUsername(username);
nsAutoCString password;
GetPassword(password);
*aHasUserPass = !username.IsEmpty() || !password.IsEmpty();
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SchemeIs(const char* aScheme, bool* _retval) {
return m_baseURL->SchemeIs(aScheme, _retval);
}
nsresult nsMsgMailNewsUrl::Clone(nsIURI** _retval) {
nsresult rv;
nsAutoCString urlSpec;
nsCOMPtr<nsIIOService> ioService = mozilla::components::IO::Service();
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
rv = GetSpec(urlSpec);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> newUri;
rv = ioService->NewURI(urlSpec, nullptr, nullptr, getter_AddRefs(newUri));
NS_ENSURE_SUCCESS(rv, rv);
// add the msg window to the cloned url
nsCOMPtr<nsIMsgWindow> msgWindow(do_QueryReferent(m_msgWindowWeak));
if (msgWindow) {
nsCOMPtr<nsIMsgMailNewsUrl> msgMailNewsUrl = do_QueryInterface(newUri, &rv);
NS_ENSURE_SUCCESS(rv, rv);
msgMailNewsUrl->SetMsgWindow(msgWindow);
}
newUri.forget(_retval);
return rv;
}
NS_IMETHODIMP nsMsgMailNewsUrl::Resolve(const nsACString& relativePath,
nsACString& result) {
// only resolve anchor urls....i.e. urls which start with '#' against the
// mailnews url... everything else shouldn't be resolved against mailnews
// urls.
nsresult rv = NS_OK;
if (relativePath.IsEmpty()) {
// Return base URL.
rv = GetSpec(result);
} else if (!relativePath.IsEmpty() &&
relativePath.First() == '#') // an anchor
{
rv = m_baseURL->Resolve(relativePath, result);
} else {
// if relativePath is a complete url with it's own scheme then allow it...
nsCOMPtr<nsIIOService> ioService = mozilla::components::IO::Service();
NS_ENSURE_TRUE(ioService, NS_ERROR_UNEXPECTED);
nsAutoCString scheme;
rv = ioService->ExtractScheme(relativePath, scheme);
// if we have a fully qualified scheme then pass the relative path back as
// the result
if (NS_SUCCEEDED(rv) && !scheme.IsEmpty()) {
result = relativePath;
rv = NS_OK;
} else {
result.Truncate();
rv = NS_ERROR_FAILURE;
}
}
return rv;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetDirectory(nsACString& aDirectory) {
return m_baseURL->GetDirectory(aDirectory);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileName(nsACString& aFileName) {
if (!mAttachmentFileName.IsEmpty()) {
aFileName = mAttachmentFileName;
return NS_OK;
}
return m_baseURL->GetFileName(aFileName);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileBaseName(nsACString& aFileBaseName) {
return m_baseURL->GetFileBaseName(aFileBaseName);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileExtension(nsACString& aFileExtension) {
if (!mAttachmentFileName.IsEmpty()) {
int32_t pos = mAttachmentFileName.RFindChar(char16_t('.'));
if (pos > 0)
aFileExtension =
Substring(mAttachmentFileName, pos + 1 /* skip the '.' */);
return NS_OK;
}
return m_baseURL->GetFileExtension(aFileExtension);
}
nsresult nsMsgMailNewsUrl::SetFileNameInternal(const nsACString& aFileName) {
mAttachmentFileName = aFileName;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetQuery(nsACString& aQuery) {
return m_baseURL->GetQuery(aQuery);
}
nsresult nsMsgMailNewsUrl::SetQuery(const nsACString& aQuery) {
return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
}
nsresult nsMsgMailNewsUrl::SetQueryInternal(const nsACString& aQuery) {
return NS_MutateURI(m_baseURL).SetQuery(aQuery).Finalize(m_baseURL);
}
nsresult nsMsgMailNewsUrl::SetQueryWithEncoding(
const nsACString& aQuery, const mozilla::Encoding* aEncoding) {
return NS_MutateURI(m_baseURL)
.SetQueryWithEncoding(aQuery, aEncoding)
.Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetHasQuery(bool* aHasQuery) {
return m_baseURL->GetHasQuery(aHasQuery);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetRef(nsACString& aRef) {
return m_baseURL->GetRef(aRef);
}
nsresult nsMsgMailNewsUrl::SetRef(const nsACString& aRef) {
return NS_MutateURI(m_baseURL).SetRef(aRef).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFilePath(nsACString& o_DirFile) {
return m_baseURL->GetFilePath(o_DirFile);
}
nsresult nsMsgMailNewsUrl::SetFilePath(const nsACString& i_DirFile) {
return NS_MutateURI(m_baseURL).SetFilePath(i_DirFile).Finalize(m_baseURL);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetCommonBaseSpec(nsIURI* uri2,
nsACString& result) {
return m_baseURL->GetCommonBaseSpec(uri2, result);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetRelativeSpec(nsIURI* uri2,
nsACString& result) {
return m_baseURL->GetRelativeSpec(uri2, result);
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetMemCacheEntry(nsICacheEntry* memCacheEntry) {
m_memCacheEntry = memCacheEntry;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetMemCacheEntry(
nsICacheEntry** memCacheEntry) {
NS_ENSURE_ARG(memCacheEntry);
nsresult rv = NS_OK;
if (m_memCacheEntry) {
NS_ADDREF(*memCacheEntry = m_memCacheEntry);
} else {
*memCacheEntry = nullptr;
return NS_ERROR_NULL_POINTER;
}
return rv;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetMimeHeaders(nsIMimeHeaders** mimeHeaders) {
NS_ENSURE_ARG_POINTER(mimeHeaders);
NS_IF_ADDREF(*mimeHeaders = mMimeHeaders);
return (mMimeHeaders) ? NS_OK : NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetMimeHeaders(nsIMimeHeaders* mimeHeaders) {
mMimeHeaders = mimeHeaders;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::LoadURI(nsIDocShell* docShell,
uint32_t aLoadFlags) {
NS_ENSURE_ARG_POINTER(docShell);
RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(this);
loadState->SetLoadFlags(aLoadFlags);
loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags));
loadState->SetFirstParty(false);
loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
return docShell->LoadURI(loadState, false);
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetSaveAsListener(
bool addDummyEnvelope, nsIFile* aFile, nsIStreamListener** aSaveListener) {
NS_ENSURE_ARG_POINTER(aSaveListener);
// Figure out whether we should use canonical line ending (i.e. CRLF). If we
// can't figure this out from the current URI, then we'll default to using
// `MSG_LINEBREAK` to preserve the legacy behavior.
nsCOMPtr<nsIMsgMessageUrl> msgUrl;
nsresult rv = this->QueryInterface(NS_GET_IID(nsIMsgMessageUrl),
getter_AddRefs(msgUrl));
bool useCanonicalLineEnding = false;
if (NS_SUCCEEDED(rv)) {
MOZ_TRY(msgUrl->GetCanonicalLineEnding(&useCanonicalLineEnding));
}
RefPtr<SaveAsListener> saveAsListener = new SaveAsListener(
aFile, addDummyEnvelope, useCanonicalLineEnding, nullptr, nullptr);
return saveAsListener->QueryInterface(NS_GET_IID(nsIStreamListener),
(void**)aSaveListener);
}
NS_IMETHODIMP
nsMsgMailNewsUrl::SetFailedSecInfo(nsITransportSecurityInfo* secInfo) {
mFailedSecInfo = secInfo;
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFailedSecInfo(
nsITransportSecurityInfo** secInfo) {
NS_ENSURE_ARG_POINTER(secInfo);
NS_IF_ADDREF(*secInfo = mFailedSecInfo);
return NS_OK;
}
NS_IMETHODIMP nsMsgMailNewsUrl::SetFolder(nsIMsgFolder* /* aFolder */) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgMailNewsUrl::GetFolder(nsIMsgFolder** /* aFolder */) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMPL_ISUPPORTS(nsMsgMailNewsUrl::Mutator, nsIURISetters, nsIURIMutator)
NS_IMETHODIMP
nsMsgMailNewsUrl::Mutate(nsIURIMutator** aMutator) {
RefPtr<nsMsgMailNewsUrl::Mutator> mutator = new nsMsgMailNewsUrl::Mutator();
nsresult rv = mutator->InitFromURI(this);
if (NS_FAILED(rv)) {
return rv;
}
mutator.forget(aMutator);
return NS_OK;
}
size_t nsMsgMailNewsUrl::SizeOfIncludingThis(
mozilla::MallocSizeOf aMallocSizeOf) {
// We don't need to calcaulte this unless something requires it.
return 0;
};