mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-22 20:33:10 +09:00
2332 lines
70 KiB
C++
2332 lines
70 KiB
C++
/* -*- 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 "nsMsgIncomingServer.h"
|
|
#include "nscore.h"
|
|
#include "plstr.h"
|
|
#include "prmem.h"
|
|
#include "prprf.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsStringGlue.h"
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsIMsgBiffManager.h"
|
|
#include "nsMsgBaseCID.h"
|
|
#include "nsMsgDBCID.h"
|
|
#include "nsIMsgFolder.h"
|
|
#include "nsIMsgFolderCache.h"
|
|
#include "nsIMsgPluggableStore.h"
|
|
#include "nsIMsgFolderCacheElement.h"
|
|
#include "nsIMsgWindow.h"
|
|
#include "nsIMsgFilterService.h"
|
|
#include "nsIMsgProtocolInfo.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsIRelativeFilePref.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIAuthPrompt.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsIWindowWatcher.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsIMsgHdr.h"
|
|
#include "nsIRDFService.h"
|
|
#include "nsRDFCID.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsILoginInfo.h"
|
|
#include "nsILoginManager.h"
|
|
#include "nsIMsgAccountManager.h"
|
|
#include "nsIMsgMdnGenerator.h"
|
|
#include "nsMsgFolderFlags.h"
|
|
#include "nsMsgUtils.h"
|
|
#include "nsMsgMessageFlags.h"
|
|
#include "nsIMsgSearchTerm.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "mozilla/Services.h"
|
|
#include "nsIMsgFilter.h"
|
|
#include "nsIArray.h"
|
|
#include "nsArrayUtils.h"
|
|
#include "nsIObserverService.h"
|
|
|
|
#define PORT_NOT_SET -1
|
|
|
|
nsMsgIncomingServer::nsMsgIncomingServer():
|
|
m_rootFolder(nullptr),
|
|
m_downloadedHdrs(50),
|
|
m_numMsgsDownloaded(0),
|
|
m_biffState(nsIMsgFolder::nsMsgBiffState_Unknown),
|
|
m_serverBusy(false),
|
|
m_canHaveFilters(true),
|
|
m_displayStartupPage(true),
|
|
mPerformingBiff(false)
|
|
{
|
|
}
|
|
|
|
nsresult nsMsgIncomingServer::Init()
|
|
{
|
|
// We need to know when the password manager changes.
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
mozilla::services::GetObserverService();
|
|
NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
|
|
|
|
observerService->AddObserver(this, "passwordmgr-storage-changed", false);
|
|
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsMsgIncomingServer::~nsMsgIncomingServer()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(nsMsgIncomingServer, nsIMsgIncomingServer,
|
|
nsISupportsWeakReference, nsIObserver)
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::Observe(nsISupports *aSubject, const char* aTopic,
|
|
const char16_t *aData)
|
|
{
|
|
nsresult rv;
|
|
|
|
// When the state of the password manager changes we need to clear the
|
|
// password from the cache in case the user just removed it.
|
|
if (strcmp(aTopic, "passwordmgr-storage-changed") == 0)
|
|
{
|
|
rv = ForgetSessionPassword();
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
}
|
|
else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0)
|
|
{
|
|
// Now remove ourselves from the observer service as well.
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
mozilla::services::GetObserverService();
|
|
NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
|
|
|
|
observerService->RemoveObserver(this, "passwordmgr-storage-changed");
|
|
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetServerBusy(bool aServerBusy)
|
|
{
|
|
m_serverBusy = aServerBusy;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetServerBusy(bool * aServerBusy)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aServerBusy);
|
|
*aServerBusy = m_serverBusy;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetKey(nsACString& serverKey)
|
|
{
|
|
serverKey = m_serverKey;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetKey(const nsACString& serverKey)
|
|
{
|
|
m_serverKey.Assign(serverKey);
|
|
|
|
// in order to actually make use of the key, we need the prefs
|
|
nsresult rv;
|
|
nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString branchName;
|
|
branchName.AssignLiteral("mail.server.");
|
|
branchName.Append(m_serverKey);
|
|
branchName.Append('.');
|
|
rv = prefs->GetBranch(branchName.get(), getter_AddRefs(mPrefBranch));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return prefs->GetBranch("mail.server.default.", getter_AddRefs(mDefPrefBranch));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetRootFolder(nsIMsgFolder * aRootFolder)
|
|
{
|
|
m_rootFolder = aRootFolder;
|
|
return NS_OK;
|
|
}
|
|
|
|
// this will return the root folder of this account,
|
|
// even if this server is deferred.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetRootFolder(nsIMsgFolder * *aRootFolder)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aRootFolder);
|
|
if (!m_rootFolder)
|
|
{
|
|
nsresult rv = CreateRootFolder();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
NS_IF_ADDREF(*aRootFolder = m_rootFolder);
|
|
return NS_OK;
|
|
}
|
|
|
|
// this will return the root folder of the deferred to account,
|
|
// if this server is deferred.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetRootMsgFolder(nsIMsgFolder **aRootMsgFolder)
|
|
{
|
|
return GetRootFolder(aRootMsgFolder);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::PerformExpand(nsIMsgWindow *aMsgWindow)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::VerifyLogon(nsIUrlListener *aUrlListener, nsIMsgWindow *aMsgWindow,
|
|
nsIURI **aURL)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::PerformBiff(nsIMsgWindow* aMsgWindow)
|
|
{
|
|
//This has to be implemented in the derived class, but in case someone doesn't implement it
|
|
//just return not implemented.
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetNewMessages(nsIMsgFolder *aFolder, nsIMsgWindow *aMsgWindow,
|
|
nsIUrlListener *aUrlListener)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aFolder);
|
|
return aFolder->GetNewMessages(aMsgWindow, aUrlListener);
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetPerformingBiff(bool *aPerformingBiff)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aPerformingBiff);
|
|
*aPerformingBiff = mPerformingBiff;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::SetPerformingBiff(bool aPerformingBiff)
|
|
{
|
|
mPerformingBiff = aPerformingBiff;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_GETSET(nsMsgIncomingServer, BiffState, uint32_t, m_biffState)
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (m_rootFolder)
|
|
{
|
|
nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryInterface(m_rootFolder, &rv);
|
|
if (NS_SUCCEEDED(rv) && msgFolder)
|
|
rv = msgFolder->WriteToFolderCache(folderCache, true /* deep */);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::Shutdown()
|
|
{
|
|
nsresult rv = CloseCachedConnections();
|
|
mFilterPlugin = nullptr;
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
if (mFilterList)
|
|
{
|
|
// close the filter log stream
|
|
rv = mFilterList->SetLogStream(nullptr);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
mFilterList = nullptr;
|
|
}
|
|
|
|
if (mSpamSettings)
|
|
{
|
|
// close the spam log stream
|
|
rv = mSpamSettings->SetLogStream(nullptr);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
mSpamSettings = nullptr;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::CloseCachedConnections()
|
|
{
|
|
// derived class should override if they cache connections.
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetDownloadMessagesAtStartup(bool *getMessagesAtStartup)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
*getMessagesAtStartup = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanHaveFilters(bool *canHaveFilters)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(canHaveFilters);
|
|
*canHaveFilters = m_canHaveFilters;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetCanHaveFilters(bool aCanHaveFilters)
|
|
{
|
|
m_canHaveFilters = aCanHaveFilters;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanBeDefaultServer(bool *canBeDefaultServer)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
*canBeDefaultServer = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanSearchMessages(bool *canSearchMessages)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
NS_ENSURE_ARG_POINTER(canSearchMessages);
|
|
*canSearchMessages = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanCompactFoldersOnServer(bool *canCompactFoldersOnServer)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
NS_ENSURE_ARG_POINTER(canCompactFoldersOnServer);
|
|
*canCompactFoldersOnServer = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanUndoDeleteOnServer(bool *canUndoDeleteOnServer)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
NS_ENSURE_ARG_POINTER(canUndoDeleteOnServer);
|
|
*canUndoDeleteOnServer = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCanEmptyTrashOnExit(bool *canEmptyTrashOnExit)
|
|
{
|
|
// derived class should override if they need to do this.
|
|
NS_ENSURE_ARG_POINTER(canEmptyTrashOnExit);
|
|
*canEmptyTrashOnExit = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
// construct <localStoreType>://[<username>@]<hostname
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetServerURI(nsACString& aResult)
|
|
{
|
|
nsresult rv;
|
|
rv = GetLocalStoreType(aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
aResult.AppendLiteral("://");
|
|
|
|
nsCString username;
|
|
rv = GetUsername(username);
|
|
if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
|
|
nsCString escapedUsername;
|
|
MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
|
|
// not all servers have a username
|
|
aResult.Append(escapedUsername);
|
|
aResult.Append('@');
|
|
}
|
|
|
|
nsCString hostname;
|
|
rv = GetHostName(hostname);
|
|
if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
|
|
nsCString escapedHostname;
|
|
MsgEscapeString(hostname, nsINetUtil::ESCAPE_URL_PATH, escapedHostname);
|
|
// not all servers have a hostname
|
|
aResult.Append(escapedHostname);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// helper routine to create local folder on disk, if it doesn't exist.
|
|
nsresult
|
|
nsMsgIncomingServer::CreateLocalFolder(const nsAString& folderName)
|
|
{
|
|
nsCOMPtr<nsIMsgFolder> rootFolder;
|
|
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
nsCOMPtr<nsIMsgFolder> child;
|
|
rv = rootFolder->GetChildNamed(folderName, getter_AddRefs(child));
|
|
if (child)
|
|
return NS_OK;
|
|
nsCOMPtr<nsIMsgPluggableStore> msgStore;
|
|
rv = GetMsgStore(getter_AddRefs(msgStore));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return msgStore->CreateFolder(rootFolder, folderName, getter_AddRefs(child));
|
|
}
|
|
|
|
nsresult
|
|
nsMsgIncomingServer::CreateRootFolder()
|
|
{
|
|
nsresult rv;
|
|
// get the URI from the incoming server
|
|
nsCString serverUri;
|
|
rv = GetServerURI(serverUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// get the corresponding RDF resource
|
|
// RDF will create the server resource if it doesn't already exist
|
|
nsCOMPtr<nsIRDFResource> serverResource;
|
|
rv = rdf->GetResource(serverUri, getter_AddRefs(serverResource));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// make incoming server know about its root server folder so we
|
|
// can find sub-folders given an incoming server.
|
|
m_rootFolder = do_QueryInterface(serverResource, &rv);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetBoolValue(const char *prefname,
|
|
bool *val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
NS_ENSURE_ARG_POINTER(val);
|
|
*val = false;
|
|
|
|
if (NS_FAILED(mPrefBranch->GetBoolPref(prefname, val)))
|
|
mDefPrefBranch->GetBoolPref(prefname, val);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetBoolValue(const char *prefname,
|
|
bool val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
bool defaultValue;
|
|
nsresult rv = mDefPrefBranch->GetBoolPref(prefname, &defaultValue);
|
|
|
|
if (NS_SUCCEEDED(rv) && val == defaultValue)
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
else
|
|
rv = mPrefBranch->SetBoolPref(prefname, val);
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetIntValue(const char *prefname,
|
|
int32_t *val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
NS_ENSURE_ARG_POINTER(val);
|
|
*val = 0;
|
|
|
|
if (NS_FAILED(mPrefBranch->GetIntPref(prefname, val)))
|
|
mDefPrefBranch->GetIntPref(prefname, val);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetFileValue(const char* aRelPrefName,
|
|
const char* aAbsPrefName,
|
|
nsIFile** aLocalFile)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
// Get the relative first
|
|
nsCOMPtr<nsIRelativeFilePref> relFilePref;
|
|
nsresult rv = mPrefBranch->GetComplexValue(aRelPrefName,
|
|
NS_GET_IID(nsIRelativeFilePref),
|
|
getter_AddRefs(relFilePref));
|
|
if (relFilePref) {
|
|
rv = relFilePref->GetFile(aLocalFile);
|
|
NS_ASSERTION(*aLocalFile, "An nsIRelativeFilePref has no file.");
|
|
if (NS_SUCCEEDED(rv))
|
|
(*aLocalFile)->Normalize();
|
|
} else {
|
|
rv = mPrefBranch->GetComplexValue(aAbsPrefName,
|
|
NS_GET_IID(nsIFile),
|
|
reinterpret_cast<void**>(aLocalFile));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
rv = NS_NewRelativeFilePref(*aLocalFile,
|
|
NS_LITERAL_CSTRING(NS_APP_USER_PROFILE_50_DIR),
|
|
getter_AddRefs(relFilePref));
|
|
if (relFilePref)
|
|
rv = mPrefBranch->SetComplexValue(aRelPrefName,
|
|
NS_GET_IID(nsIRelativeFilePref),
|
|
relFilePref);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetFileValue(const char* aRelPrefName,
|
|
const char* aAbsPrefName,
|
|
nsIFile* aLocalFile)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
// Write the relative path.
|
|
nsCOMPtr<nsIRelativeFilePref> relFilePref;
|
|
NS_NewRelativeFilePref(aLocalFile,
|
|
NS_LITERAL_CSTRING(NS_APP_USER_PROFILE_50_DIR),
|
|
getter_AddRefs(relFilePref));
|
|
if (relFilePref) {
|
|
nsresult rv = mPrefBranch->SetComplexValue(aRelPrefName,
|
|
NS_GET_IID(nsIRelativeFilePref),
|
|
relFilePref);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
}
|
|
return mPrefBranch->SetComplexValue(aAbsPrefName, NS_GET_IID(nsIFile), aLocalFile);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetIntValue(const char *prefname,
|
|
int32_t val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
int32_t defaultVal;
|
|
nsresult rv = mDefPrefBranch->GetIntPref(prefname, &defaultVal);
|
|
|
|
if (NS_SUCCEEDED(rv) && defaultVal == val)
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
else
|
|
rv = mPrefBranch->SetIntPref(prefname, val);
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetCharValue(const char *prefname,
|
|
nsACString& val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCString tmpVal;
|
|
if (NS_FAILED(mPrefBranch->GetCharPref(prefname, getter_Copies(tmpVal))))
|
|
mDefPrefBranch->GetCharPref(prefname, getter_Copies(tmpVal));
|
|
val = tmpVal;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetUnicharValue(const char *prefname,
|
|
nsAString& val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsISupportsString> supportsString;
|
|
if (NS_FAILED(mPrefBranch->GetComplexValue(prefname,
|
|
NS_GET_IID(nsISupportsString),
|
|
getter_AddRefs(supportsString))))
|
|
mDefPrefBranch->GetComplexValue(prefname,
|
|
NS_GET_IID(nsISupportsString),
|
|
getter_AddRefs(supportsString));
|
|
|
|
if (supportsString)
|
|
return supportsString->GetData(val);
|
|
val.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetCharValue(const char *prefname,
|
|
const nsACString& val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
if (val.IsEmpty()) {
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCString defaultVal;
|
|
nsresult rv = mDefPrefBranch->GetCharPref(prefname, getter_Copies(defaultVal));
|
|
|
|
if (NS_SUCCEEDED(rv) && defaultVal.Equals(val))
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
else
|
|
rv = mPrefBranch->SetCharPref(prefname, nsCString(val).get());
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetUnicharValue(const char *prefname,
|
|
const nsAString& val)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
if (val.IsEmpty()) {
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsISupportsString> supportsString;
|
|
nsresult rv = mDefPrefBranch->GetComplexValue(prefname,
|
|
NS_GET_IID(nsISupportsString),
|
|
getter_AddRefs(supportsString));
|
|
nsString defaultVal;
|
|
if (NS_SUCCEEDED(rv) &&
|
|
NS_SUCCEEDED(supportsString->GetData(defaultVal)) &&
|
|
defaultVal.Equals(val))
|
|
mPrefBranch->ClearUserPref(prefname);
|
|
else {
|
|
supportsString = do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
|
if (supportsString) {
|
|
supportsString->SetData(val);
|
|
rv = mPrefBranch->SetComplexValue(prefname,
|
|
NS_GET_IID(nsISupportsString),
|
|
supportsString);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
// pretty name is the display name to show to the user
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetPrettyName(nsAString& retval)
|
|
{
|
|
nsresult rv = GetUnicharValue("name", retval);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// if there's no name, then just return the hostname
|
|
return retval.IsEmpty() ? GetConstructedPrettyName(retval) : rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetPrettyName(const nsAString& value)
|
|
{
|
|
SetUnicharValue("name", value);
|
|
nsCOMPtr<nsIMsgFolder> rootFolder;
|
|
GetRootFolder(getter_AddRefs(rootFolder));
|
|
if (rootFolder)
|
|
rootFolder->SetPrettyName(value);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// construct the pretty name to show to the user if they haven't
|
|
// specified one. This should be overridden for news and mail.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetConstructedPrettyName(nsAString& retval)
|
|
{
|
|
nsCString username;
|
|
nsresult rv = GetUsername(username);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (!username.IsEmpty()) {
|
|
CopyASCIItoUTF16(username, retval);
|
|
retval.AppendLiteral(" on ");
|
|
}
|
|
|
|
nsCString hostname;
|
|
rv = GetHostName(hostname);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
retval.Append(NS_ConvertASCIItoUTF16(hostname));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::ToString(nsAString& aResult)
|
|
{
|
|
aResult.AssignLiteral("[nsIMsgIncomingServer: ");
|
|
aResult.Append(NS_ConvertASCIItoUTF16(m_serverKey));
|
|
aResult.AppendLiteral("]");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::SetPassword(const nsACString& aPassword)
|
|
{
|
|
m_password = aPassword;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetPassword(nsACString& aPassword)
|
|
{
|
|
aPassword = m_password;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetServerRequiresPasswordForBiff(bool *aServerRequiresPasswordForBiff)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aServerRequiresPasswordForBiff);
|
|
*aServerRequiresPasswordForBiff = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
// This sets m_password if we find a password in the pw mgr.
|
|
nsresult nsMsgIncomingServer::GetPasswordWithoutUI()
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsILoginManager> loginMgr(do_GetService(NS_LOGINMANAGER_CONTRACTID,
|
|
&rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Get the current server URI
|
|
nsCString currServerUri;
|
|
rv = GetLocalStoreType(currServerUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
currServerUri.AppendLiteral("://");
|
|
|
|
nsCString temp;
|
|
rv = GetHostName(temp);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
currServerUri.Append(temp);
|
|
|
|
NS_ConvertUTF8toUTF16 currServer(currServerUri);
|
|
|
|
uint32_t numLogins = 0;
|
|
nsILoginInfo** logins = nullptr;
|
|
rv = loginMgr->FindLogins(&numLogins, currServer, EmptyString(),
|
|
currServer, &logins);
|
|
|
|
// Login manager can produce valid fails, e.g. NS_ERROR_ABORT when a user
|
|
// cancels the master password dialog. Therefore handle that here, but don't
|
|
// warn about it.
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
// Don't abort here, if we didn't find any or failed, then we'll just have
|
|
// to prompt.
|
|
if (numLogins > 0)
|
|
{
|
|
nsCString serverCUsername;
|
|
rv = GetUsername(serverCUsername);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
|
|
|
|
nsString username;
|
|
for (uint32_t i = 0; i < numLogins; ++i)
|
|
{
|
|
rv = logins[i]->GetUsername(username);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (username.Equals(serverUsername))
|
|
{
|
|
nsString password;
|
|
rv = logins[i]->GetPassword(password);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
m_password = NS_LossyConvertUTF16toASCII(password);
|
|
break;
|
|
}
|
|
}
|
|
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(numLogins, logins);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetPasswordWithUI(const nsAString& aPromptMessage, const
|
|
nsAString& aPromptTitle,
|
|
nsIMsgWindow* aMsgWindow,
|
|
nsACString& aPassword)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
if (m_password.IsEmpty())
|
|
{
|
|
// let's see if we have the password in the password manager and
|
|
// can avoid this prompting thing. This makes it easier to get embedders
|
|
// to get up and running w/o a password prompting UI.
|
|
rv = GetPasswordWithoutUI();
|
|
// If GetPasswordWithoutUI returns NS_ERROR_ABORT, the most likely case
|
|
// is the user canceled getting the master password, so just return
|
|
// straight away, as they won't want to get prompted again.
|
|
if (rv == NS_ERROR_ABORT)
|
|
return NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
|
}
|
|
if (m_password.IsEmpty())
|
|
{
|
|
nsCOMPtr<nsIAuthPrompt> dialog;
|
|
// aMsgWindow is required if we need to prompt
|
|
if (aMsgWindow)
|
|
{
|
|
rv = aMsgWindow->GetAuthPrompt(getter_AddRefs(dialog));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
if (dialog)
|
|
{
|
|
// prompt the user for the password
|
|
nsCString serverUri;
|
|
rv = GetLocalStoreType(serverUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
serverUri.AppendLiteral("://");
|
|
nsCString temp;
|
|
rv = GetUsername(temp);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!temp.IsEmpty())
|
|
{
|
|
nsCString escapedUsername;
|
|
MsgEscapeString(temp, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
|
|
serverUri.Append(escapedUsername);
|
|
serverUri.Append('@');
|
|
}
|
|
|
|
rv = GetHostName(temp);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
serverUri.Append(temp);
|
|
|
|
// we pass in the previously used password, if any, into PromptPassword
|
|
// so that it will appear as ******. This means we can't use an nsString
|
|
// and getter_Copies.
|
|
char16_t *uniPassword = nullptr;
|
|
if (!aPassword.IsEmpty())
|
|
uniPassword = ToNewUnicode(NS_ConvertASCIItoUTF16(aPassword));
|
|
|
|
bool okayValue = true;
|
|
rv = dialog->PromptPassword(PromiseFlatString(aPromptTitle).get(),
|
|
PromiseFlatString(aPromptMessage).get(),
|
|
NS_ConvertASCIItoUTF16(serverUri).get(),
|
|
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
|
&uniPassword, &okayValue);
|
|
nsAutoString uniPasswordAdopted;
|
|
uniPasswordAdopted.Adopt(uniPassword);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!okayValue) // if the user pressed cancel, just return an empty string;
|
|
{
|
|
aPassword.Truncate();
|
|
return NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
|
}
|
|
|
|
// we got a password back...so remember it
|
|
rv = SetPassword(NS_LossyConvertUTF16toASCII(uniPasswordAdopted));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
} // if we got a prompt dialog
|
|
else
|
|
return NS_ERROR_FAILURE;
|
|
} // if the password is empty
|
|
return GetPassword(aPassword);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::ForgetPassword()
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsILoginManager> loginMgr =
|
|
do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Get the current server URI
|
|
nsCString currServerUri;
|
|
rv = GetLocalStoreType(currServerUri);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
currServerUri.AppendLiteral("://");
|
|
|
|
nsCString temp;
|
|
rv = GetHostName(temp);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
currServerUri.Append(temp);
|
|
|
|
uint32_t count;
|
|
nsILoginInfo** logins;
|
|
|
|
NS_ConvertUTF8toUTF16 currServer(currServerUri);
|
|
|
|
nsCString serverCUsername;
|
|
rv = GetUsername(serverCUsername);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
|
|
|
|
rv = loginMgr->FindLogins(&count, currServer, EmptyString(),
|
|
currServer, &logins);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// There should only be one-login stored for this url, however just in case
|
|
// there isn't.
|
|
nsString username;
|
|
for (uint32_t i = 0; i < count; ++i)
|
|
{
|
|
if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
|
|
username.Equals(serverUsername))
|
|
{
|
|
// If this fails, just continue, we'll still want to remove the password
|
|
// from our local cache.
|
|
loginMgr->RemoveLogin(logins[i]);
|
|
}
|
|
}
|
|
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
|
|
|
|
return SetPassword(EmptyCString());
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::ForgetSessionPassword()
|
|
{
|
|
m_password.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetDefaultLocalPath(nsIFile *aDefaultLocalPath)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
|
rv = GetProtocolInfo(getter_AddRefs(protocolInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return protocolInfo->SetDefaultLocalPath(aDefaultLocalPath);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetLocalPath(nsIFile **aLocalPath)
|
|
{
|
|
nsresult rv;
|
|
|
|
// if the local path has already been set, use it
|
|
rv = GetFileValue("directory-rel", "directory", aLocalPath);
|
|
if (NS_SUCCEEDED(rv) && *aLocalPath)
|
|
return rv;
|
|
|
|
// otherwise, create the path using the protocol info.
|
|
// note we are using the
|
|
// hostname, unless that directory exists.
|
|
// this should prevent all collisions.
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
|
rv = GetProtocolInfo(getter_AddRefs(protocolInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIFile> localPath;
|
|
rv = protocolInfo->GetDefaultLocalPath(getter_AddRefs(localPath));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = localPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
|
if (rv == NS_ERROR_FILE_ALREADY_EXISTS)
|
|
rv = NS_OK;
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString hostname;
|
|
rv = GetHostName(hostname);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// set the leaf name to "dummy", and then call MakeUnique with a suggested leaf name
|
|
rv = localPath->AppendNative(hostname);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = localPath->CreateUnique(nsIFile::DIRECTORY_TYPE, 0755);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = SetLocalPath(localPath);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
localPath.swap(*aLocalPath);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetMsgStore(nsIMsgPluggableStore **aMsgStore)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aMsgStore);
|
|
if (!m_msgStore)
|
|
{
|
|
nsCString storeContractID;
|
|
nsresult rv;
|
|
// We don't want there to be a default pref, I think, since
|
|
// we can't change the default. We may want no pref to mean
|
|
// berkeley store, and then set the store pref off of some sort
|
|
// of default when creating a server. But we need to make sure
|
|
// that we do always write a store pref.
|
|
GetCharValue("storeContractID", storeContractID);
|
|
if (storeContractID.IsEmpty())
|
|
{
|
|
storeContractID.Assign("@mozilla.org/msgstore/berkeleystore;1");
|
|
SetCharValue("storeContractID", storeContractID);
|
|
}
|
|
|
|
// After someone starts using the pluggable store, we can no longer
|
|
// change the value.
|
|
SetBoolValue("canChangeStoreType", false);
|
|
|
|
// Right now, we just have one pluggable store per server. If we want
|
|
// to support multiple, this pref could be a list of pluggable store
|
|
// contract id's.
|
|
m_msgStore = do_CreateInstance(storeContractID.get(), &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
NS_IF_ADDREF(*aMsgStore = m_msgStore);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetLocalPath(nsIFile *aLocalPath)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aLocalPath);
|
|
nsresult rv = aLocalPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
|
if (rv == NS_ERROR_FILE_ALREADY_EXISTS)
|
|
rv = NS_OK;
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return SetFileValue("directory-rel", "directory", aLocalPath);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetLocalStoreType(nsACString& aResult)
|
|
{
|
|
NS_NOTYETIMPLEMENTED("nsMsgIncomingServer superclass not implementing GetLocalStoreType!");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetLocalDatabaseType(nsACString& aResult)
|
|
{
|
|
NS_NOTYETIMPLEMENTED("nsMsgIncomingServer superclass not implementing GetLocalDatabaseType!");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetAccountManagerChrome(nsAString& aResult)
|
|
{
|
|
aResult.AssignLiteral("am-main.xul");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::Equals(nsIMsgIncomingServer *server, bool *_retval)
|
|
{
|
|
nsresult rv;
|
|
|
|
NS_ENSURE_ARG_POINTER(server);
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
|
|
nsCString key1;
|
|
nsCString key2;
|
|
|
|
rv = GetKey(key1);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = server->GetKey(key2);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// compare the server keys
|
|
*_retval = key1.Equals(key2, nsCaseInsensitiveCStringComparator());
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::ClearAllValues()
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
return mPrefBranch->DeleteBranch("");
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::RemoveFiles()
|
|
{
|
|
// IMPORTANT, see bug #77652
|
|
// TODO: Decide what to do for deferred accounts.
|
|
nsCString deferredToAccount;
|
|
GetCharValue("deferred_to_account", deferredToAccount);
|
|
bool isDeferredTo = true;
|
|
GetIsDeferredTo(&isDeferredTo);
|
|
if (!deferredToAccount.IsEmpty() || isDeferredTo)
|
|
{
|
|
NS_ASSERTION(false, "shouldn't remove files for a deferred account");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
nsCOMPtr <nsIFile> localPath;
|
|
nsresult rv = GetLocalPath(getter_AddRefs(localPath));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return localPath->Remove(true);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetFilterList(nsIMsgFilterList *aFilterList)
|
|
{
|
|
mFilterList = aFilterList;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetFilterList(nsIMsgWindow *aMsgWindow, nsIMsgFilterList **aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
if (!mFilterList)
|
|
{
|
|
nsCOMPtr<nsIMsgFolder> msgFolder;
|
|
// use GetRootFolder so for deferred pop3 accounts, we'll get the filters
|
|
// file from the deferred account, not the deferred to account,
|
|
// so that filters will still be per-server.
|
|
nsresult rv = GetRootFolder(getter_AddRefs(msgFolder));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString filterType;
|
|
rv = GetCharValue("filter.type", filterType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (!filterType.IsEmpty() && !filterType.EqualsLiteral("default"))
|
|
{
|
|
nsAutoCString contractID("@mozilla.org/filterlist;1?type=");
|
|
contractID += filterType;
|
|
ToLowerCase(contractID);
|
|
mFilterList = do_CreateInstance(contractID.get(), &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mFilterList->SetFolder(msgFolder);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ADDREF(*aResult = mFilterList);
|
|
return NS_OK;
|
|
}
|
|
|
|
// The default case, a local folder, is a bit special. It requires
|
|
// more initialization.
|
|
|
|
nsCOMPtr<nsIFile> thisFolder;
|
|
rv = msgFolder->GetFilePath(getter_AddRefs(thisFolder));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
mFilterFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = mFilterFile->InitWithFile(thisFolder);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
mFilterFile->AppendNative(NS_LITERAL_CSTRING("msgFilterRules.dat"));
|
|
|
|
bool fileExists;
|
|
mFilterFile->Exists(&fileExists);
|
|
if (!fileExists)
|
|
{
|
|
nsCOMPtr<nsIFile> oldFilterFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = oldFilterFile->InitWithFile(thisFolder);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
oldFilterFile->AppendNative(NS_LITERAL_CSTRING("rules.dat"));
|
|
|
|
oldFilterFile->Exists(&fileExists);
|
|
if (fileExists) //copy rules.dat --> msgFilterRules.dat
|
|
{
|
|
rv = oldFilterFile->CopyToNative(thisFolder, NS_LITERAL_CSTRING("msgFilterRules.dat"));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
nsCOMPtr<nsIMsgFilterService> filterService =
|
|
do_GetService(NS_MSGFILTERSERVICE_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = filterService->OpenFilterList(mFilterFile, msgFolder, aMsgWindow, getter_AddRefs(mFilterList));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
NS_IF_ADDREF(*aResult = mFilterList);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetEditableFilterList(nsIMsgFilterList *aEditableFilterList)
|
|
{
|
|
mEditableFilterList = aEditableFilterList;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetEditableFilterList(nsIMsgWindow *aMsgWindow, nsIMsgFilterList **aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
if (!mEditableFilterList)
|
|
{
|
|
bool editSeparate;
|
|
nsresult rv = GetBoolValue("filter.editable.separate", &editSeparate);
|
|
if (NS_FAILED(rv) || !editSeparate)
|
|
return GetFilterList(aMsgWindow, aResult);
|
|
|
|
nsCString filterType;
|
|
rv = GetCharValue("filter.editable.type", filterType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString contractID("@mozilla.org/filterlist;1?type=");
|
|
contractID += filterType;
|
|
ToLowerCase(contractID);
|
|
mEditableFilterList = do_CreateInstance(contractID.get(), &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIMsgFolder> msgFolder;
|
|
// use GetRootFolder so for deferred pop3 accounts, we'll get the filters
|
|
// file from the deferred account, not the deferred to account,
|
|
// so that filters will still be per-server.
|
|
rv = GetRootFolder(getter_AddRefs(msgFolder));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mEditableFilterList->SetFolder(msgFolder);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ADDREF(*aResult = mEditableFilterList);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IF_ADDREF(*aResult = mEditableFilterList);
|
|
return NS_OK;
|
|
}
|
|
|
|
// If the hostname contains ':' (like hostname:1431)
|
|
// then parse and set the port number.
|
|
nsresult
|
|
nsMsgIncomingServer::InternalSetHostName(const nsACString& aHostname, const char * prefName)
|
|
{
|
|
nsCString hostname;
|
|
hostname = aHostname;
|
|
if (MsgCountChar(hostname, ':') == 1)
|
|
{
|
|
int32_t colonPos = hostname.FindChar(':');
|
|
nsAutoCString portString(Substring(hostname, colonPos));
|
|
hostname.SetLength(colonPos);
|
|
nsresult err;
|
|
int32_t port = portString.ToInteger(&err);
|
|
if (NS_SUCCEEDED(err))
|
|
SetPort(port);
|
|
}
|
|
return SetCharValue(prefName, hostname);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::OnUserOrHostNameChanged(const nsACString& oldName,
|
|
const nsACString& newName,
|
|
bool hostnameChanged)
|
|
{
|
|
nsresult rv;
|
|
|
|
// 1. Reset password so that users are prompted for new password for the new user/host.
|
|
ForgetPassword();
|
|
|
|
// 2. Let the derived class close all cached connection to the old host.
|
|
CloseCachedConnections();
|
|
|
|
// 3. Notify any listeners for account server changes.
|
|
nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = accountManager->NotifyServerChanged(this);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// 4. Lastly, replace all occurrences of old name in the acct name with the new one.
|
|
nsString acctName;
|
|
rv = GetPrettyName(acctName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_ENSURE_FALSE(acctName.IsEmpty(), NS_OK);
|
|
|
|
// exit if new name contains @ then better do not update the account name
|
|
if (!hostnameChanged && (newName.FindChar('@') != kNotFound))
|
|
return NS_OK;
|
|
|
|
int32_t atPos = acctName.FindChar('@');
|
|
|
|
// get previous username and hostname
|
|
nsCString userName, hostName;
|
|
if (hostnameChanged)
|
|
{
|
|
rv = GetRealUsername(userName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
hostName.Assign(oldName);
|
|
}
|
|
else
|
|
{
|
|
userName.Assign(oldName);
|
|
rv = GetRealHostName(hostName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
// switch corresponding part of the account name to the new name...
|
|
if (!hostnameChanged && (atPos != kNotFound))
|
|
{
|
|
// ...if username changed and the previous username was equal to the part
|
|
// of the account name before @
|
|
if (StringHead(acctName, atPos).Equals(NS_ConvertASCIItoUTF16(userName)))
|
|
acctName.Replace(0, userName.Length(), NS_ConvertASCIItoUTF16(newName));
|
|
}
|
|
if (hostnameChanged)
|
|
{
|
|
// ...if hostname changed and the previous hostname was equal to the part
|
|
// of the account name after @, or to the whole account name
|
|
if (atPos == kNotFound)
|
|
atPos = 0;
|
|
else
|
|
atPos += 1;
|
|
if (Substring(acctName, atPos).Equals(NS_ConvertASCIItoUTF16(hostName))) {
|
|
acctName.Replace(atPos, acctName.Length() - atPos,
|
|
NS_ConvertASCIItoUTF16(newName));
|
|
}
|
|
}
|
|
|
|
return SetPrettyName(acctName);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetHostName(const nsACString& aHostname)
|
|
{
|
|
return (InternalSetHostName(aHostname, "hostname"));
|
|
}
|
|
|
|
// SetRealHostName() is called only when the server name is changed from the
|
|
// UI (Account Settings page). No one should call it in any circumstances.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetRealHostName(const nsACString& aHostname)
|
|
{
|
|
nsCString oldName;
|
|
nsresult rv = GetRealHostName(oldName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = InternalSetHostName(aHostname, "realhostname");
|
|
|
|
// A few things to take care of if we're changing the hostname.
|
|
if (!aHostname.Equals(oldName, nsCaseInsensitiveCStringComparator()))
|
|
rv = OnUserOrHostNameChanged(oldName, aHostname, true);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetHostName(nsACString& aResult)
|
|
{
|
|
nsresult rv;
|
|
rv = GetCharValue("hostname", aResult);
|
|
if (MsgCountChar(aResult, ':') == 1)
|
|
{
|
|
// gack, we need to reformat the hostname - SetHostName will do that
|
|
SetHostName(aResult);
|
|
rv = GetCharValue("hostname", aResult);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetRealHostName(nsACString& aResult)
|
|
{
|
|
// If 'realhostname' is set (was changed) then use it, otherwise use 'hostname'
|
|
nsresult rv;
|
|
rv = GetCharValue("realhostname", aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (aResult.IsEmpty())
|
|
return GetHostName(aResult);
|
|
|
|
if (MsgCountChar(aResult, ':') == 1)
|
|
{
|
|
SetRealHostName(aResult);
|
|
rv = GetCharValue("realhostname", aResult);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetRealUsername(nsACString& aResult)
|
|
{
|
|
// If 'realuserName' is set (was changed) then use it, otherwise use 'userName'
|
|
nsresult rv;
|
|
rv = GetCharValue("realuserName", aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return aResult.IsEmpty() ? GetUsername(aResult) : rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetRealUsername(const nsACString& aUsername)
|
|
{
|
|
// Need to take care of few things if we're changing the username.
|
|
nsCString oldName;
|
|
nsresult rv = GetRealUsername(oldName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetCharValue("realuserName", aUsername);
|
|
if (!oldName.Equals(aUsername))
|
|
rv = OnUserOrHostNameChanged(oldName, aUsername, false);
|
|
return rv;
|
|
}
|
|
|
|
#define BIFF_PREF_NAME "check_new_mail"
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetDoBiff(bool *aDoBiff)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aDoBiff);
|
|
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsresult rv;
|
|
|
|
rv = mPrefBranch->GetBoolPref(BIFF_PREF_NAME, aDoBiff);
|
|
if (NS_SUCCEEDED(rv))
|
|
return rv;
|
|
|
|
// if the pref isn't set, use the default
|
|
// value based on the protocol
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
|
rv = GetProtocolInfo(getter_AddRefs(protocolInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = protocolInfo->GetDefaultDoBiff(aDoBiff);
|
|
// note, don't call SetDoBiff()
|
|
// since we keep changing our minds on
|
|
// if biff should be on or off, let's keep the ability
|
|
// to change the default in future builds.
|
|
// if we call SetDoBiff() here, it will be in the users prefs.
|
|
// and we can't do anything after that.
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetDoBiff(bool aDoBiff)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
// Update biffManager immediately, no restart required. Adding/removing
|
|
// existing/non-existing server is handled without error checking.
|
|
nsresult rv;
|
|
nsCOMPtr<nsIMsgBiffManager> biffService =
|
|
do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
|
|
if (NS_SUCCEEDED(rv) && biffService)
|
|
{
|
|
if (aDoBiff)
|
|
(void) biffService->AddServerBiff(this);
|
|
else
|
|
(void) biffService->RemoveServerBiff(this);
|
|
}
|
|
|
|
return mPrefBranch->SetBoolPref(BIFF_PREF_NAME, aDoBiff);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetPort(int32_t *aPort)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aPort);
|
|
|
|
nsresult rv;
|
|
rv = GetIntValue("port", aPort);
|
|
// We can't use a port of 0, because the URI parsing code fails.
|
|
if (*aPort != PORT_NOT_SET && *aPort)
|
|
return rv;
|
|
|
|
// if the port isn't set, use the default
|
|
// port based on the protocol
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
|
rv = GetProtocolInfo(getter_AddRefs(protocolInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
int32_t socketType;
|
|
rv = GetSocketType(&socketType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
bool useSSLPort = (socketType == nsMsgSocketType::SSL);
|
|
return protocolInfo->GetDefaultServerPort(useSSLPort, aPort);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetPort(int32_t aPort)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
|
|
rv = GetProtocolInfo(getter_AddRefs(protocolInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
int32_t socketType;
|
|
rv = GetSocketType(&socketType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
bool useSSLPort = (socketType == nsMsgSocketType::SSL);
|
|
|
|
int32_t defaultPort;
|
|
protocolInfo->GetDefaultServerPort(useSSLPort, &defaultPort);
|
|
return SetIntValue("port", aPort == defaultPort ? PORT_NOT_SET : aPort);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetProtocolInfo(nsIMsgProtocolInfo **aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
nsCString type;
|
|
nsresult rv = GetType(type);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString contractid(NS_MSGPROTOCOLINFO_CONTRACTID_PREFIX);
|
|
contractid.Append(type);
|
|
|
|
nsCOMPtr<nsIMsgProtocolInfo> protocolInfo = do_GetService(contractid.get(), &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
protocolInfo.forget(aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetRetentionSettings(nsIMsgRetentionSettings **settings)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(settings);
|
|
nsMsgRetainByPreference retainByPreference;
|
|
int32_t daysToKeepHdrs = 0;
|
|
int32_t numHeadersToKeep = 0;
|
|
int32_t daysToKeepBodies = 0;
|
|
bool cleanupBodiesByDays = false;
|
|
bool applyToFlaggedMessages = false;
|
|
nsresult rv = NS_OK;
|
|
// Create an empty retention settings object,
|
|
// get the settings from the server prefs, and init the object from the prefs.
|
|
nsCOMPtr <nsIMsgRetentionSettings> retentionSettings =
|
|
do_CreateInstance(NS_MSG_RETENTIONSETTINGS_CONTRACTID);
|
|
if (retentionSettings)
|
|
{
|
|
rv = GetIntValue("retainBy", (int32_t*) &retainByPreference);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = GetIntValue("numHdrsToKeep", &numHeadersToKeep);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = GetIntValue("daysToKeepHdrs", &daysToKeepHdrs);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = GetIntValue("daysToKeepBodies", &daysToKeepBodies);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = GetBoolValue("cleanupBodies", &cleanupBodiesByDays);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = GetBoolValue("applyToFlaggedMessages", &applyToFlaggedMessages);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
retentionSettings->SetRetainByPreference(retainByPreference);
|
|
retentionSettings->SetNumHeadersToKeep((uint32_t) numHeadersToKeep);
|
|
retentionSettings->SetDaysToKeepBodies(daysToKeepBodies);
|
|
retentionSettings->SetDaysToKeepHdrs(daysToKeepHdrs);
|
|
retentionSettings->SetCleanupBodiesByDays(cleanupBodiesByDays);
|
|
retentionSettings->SetApplyToFlaggedMessages(applyToFlaggedMessages);
|
|
}
|
|
else
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
NS_IF_ADDREF(*settings = retentionSettings);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::SetRetentionSettings(nsIMsgRetentionSettings *settings)
|
|
{
|
|
nsMsgRetainByPreference retainByPreference;
|
|
uint32_t daysToKeepHdrs = 0;
|
|
uint32_t numHeadersToKeep = 0;
|
|
uint32_t daysToKeepBodies = 0;
|
|
bool cleanupBodiesByDays = false;
|
|
bool applyToFlaggedMessages = false;
|
|
settings->GetRetainByPreference(&retainByPreference);
|
|
settings->GetNumHeadersToKeep(&numHeadersToKeep);
|
|
settings->GetDaysToKeepBodies(&daysToKeepBodies);
|
|
settings->GetDaysToKeepHdrs(&daysToKeepHdrs);
|
|
settings->GetCleanupBodiesByDays(&cleanupBodiesByDays);
|
|
settings->GetApplyToFlaggedMessages(&applyToFlaggedMessages);
|
|
nsresult rv = SetIntValue("retainBy", retainByPreference);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetIntValue("numHdrsToKeep", numHeadersToKeep);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetIntValue("daysToKeepHdrs", daysToKeepHdrs);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetIntValue("daysToKeepBodies", daysToKeepBodies);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetBoolValue("cleanupBodies", cleanupBodiesByDays);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
rv = SetBoolValue("applyToFlaggedMessages", applyToFlaggedMessages);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetDisplayStartupPage(bool *displayStartupPage)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(displayStartupPage);
|
|
*displayStartupPage = m_displayStartupPage;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetDisplayStartupPage(bool displayStartupPage)
|
|
{
|
|
m_displayStartupPage = displayStartupPage;
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetDownloadSettings(nsIMsgDownloadSettings **settings)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(settings);
|
|
bool downloadUnreadOnly = false;
|
|
bool downloadByDate = false;
|
|
uint32_t ageLimitOfMsgsToDownload = 0;
|
|
nsresult rv = NS_OK;
|
|
if (!m_downloadSettings)
|
|
{
|
|
m_downloadSettings = do_CreateInstance(NS_MSG_DOWNLOADSETTINGS_CONTRACTID);
|
|
if (m_downloadSettings)
|
|
{
|
|
rv = GetBoolValue("downloadUnreadOnly", &downloadUnreadOnly);
|
|
rv = GetBoolValue("downloadByDate", &downloadByDate);
|
|
rv = GetIntValue("ageLimit", (int32_t *) &ageLimitOfMsgsToDownload);
|
|
m_downloadSettings->SetDownloadUnreadOnly(downloadUnreadOnly);
|
|
m_downloadSettings->SetDownloadByDate(downloadByDate);
|
|
m_downloadSettings->SetAgeLimitOfMsgsToDownload(ageLimitOfMsgsToDownload);
|
|
}
|
|
else
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
// Create an empty download settings object,
|
|
// get the settings from the server prefs, and init the object from the prefs.
|
|
}
|
|
NS_IF_ADDREF(*settings = m_downloadSettings);
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::SetDownloadSettings(nsIMsgDownloadSettings *settings)
|
|
{
|
|
m_downloadSettings = settings;
|
|
bool downloadUnreadOnly = false;
|
|
bool downloadByDate = false;
|
|
uint32_t ageLimitOfMsgsToDownload = 0;
|
|
m_downloadSettings->GetDownloadUnreadOnly(&downloadUnreadOnly);
|
|
m_downloadSettings->GetDownloadByDate(&downloadByDate);
|
|
m_downloadSettings->GetAgeLimitOfMsgsToDownload(&ageLimitOfMsgsToDownload);
|
|
nsresult rv = SetBoolValue("downloadUnreadOnly", downloadUnreadOnly);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
SetBoolValue("downloadByDate", downloadByDate);
|
|
return SetIntValue("ageLimit", ageLimitOfMsgsToDownload);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetSupportsDiskSpace(bool *aSupportsDiskSpace)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSupportsDiskSpace);
|
|
*aSupportsDiskSpace = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetOfflineSupportLevel(int32_t *aSupportLevel)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSupportLevel);
|
|
|
|
nsresult rv = GetIntValue("offline_support_level", aSupportLevel);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (*aSupportLevel == OFFLINE_SUPPORT_LEVEL_UNDEFINED)
|
|
*aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetOfflineSupportLevel(int32_t aSupportLevel)
|
|
{
|
|
SetIntValue("offline_support_level", aSupportLevel);
|
|
return NS_OK;
|
|
}
|
|
#define BASE_MSGS_URL "chrome://messenger/locale/messenger.properties"
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::DisplayOfflineMsg(nsIMsgWindow *aMsgWindow)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aMsgWindow);
|
|
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
|
mozilla::services::GetStringBundleService();
|
|
NS_ENSURE_TRUE(bundleService, NS_ERROR_UNEXPECTED);
|
|
|
|
nsCOMPtr<nsIStringBundle> bundle;
|
|
nsresult rv = bundleService->CreateBundle(BASE_MSGS_URL, getter_AddRefs(bundle));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (bundle)
|
|
{
|
|
nsString errorMsgTitle;
|
|
nsString errorMsgBody;
|
|
bundle->GetStringFromName(u"nocachedbodybody2", getter_Copies(errorMsgBody));
|
|
bundle->GetStringFromName(u"nocachedbodytitle", getter_Copies(errorMsgTitle));
|
|
aMsgWindow->DisplayHTMLInMessagePane(errorMsgTitle, errorMsgBody, true);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// Called only during the migration process. A unique name is generated for the
|
|
// migrated account.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GeneratePrettyNameForMigration(nsAString& aPrettyName)
|
|
{
|
|
/**
|
|
* 4.x had provisions for multiple imap servers to be maintained under
|
|
* single identity. So, when migrated each of those server accounts need
|
|
* to be represented by unique account name. nsImapIncomingServer will
|
|
* override the implementation for this to do the right thing.
|
|
*/
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetFilterScope(nsMsgSearchScopeValue *filterScope)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(filterScope);
|
|
*filterScope = nsMsgSearchScope::offlineMailFilter;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetSearchScope(nsMsgSearchScopeValue *searchScope)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(searchScope);
|
|
*searchScope = nsMsgSearchScope::offlineMail;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetIsSecure(bool *aIsSecure)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aIsSecure);
|
|
int32_t socketType;
|
|
nsresult rv = GetSocketType(&socketType);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
*aIsSecure = (socketType == nsMsgSocketType::alwaysSTARTTLS ||
|
|
socketType == nsMsgSocketType::SSL);
|
|
return NS_OK;
|
|
}
|
|
|
|
// use the convenience macros to implement the accessors
|
|
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Username, "userName")
|
|
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, AuthMethod, "authMethod")
|
|
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, BiffMinutes, "check_time")
|
|
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Type, "type")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DownloadOnBiff, "download_on_biff")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, Valid, "valid")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, EmptyTrashOnExit,
|
|
"empty_trash_on_exit")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, CanDelete, "canDelete")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, LoginAtStartUp, "login_at_startup")
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer,
|
|
DefaultCopiesAndFoldersPrefsToServer,
|
|
"allows_specialfolders_usage")
|
|
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer,
|
|
CanCreateFoldersOnServer,
|
|
"canCreateFolders")
|
|
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer,
|
|
CanFileMessagesOnServer,
|
|
"canFileMessages")
|
|
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer,
|
|
LimitOfflineMessageSize,
|
|
"limit_offline_message_size")
|
|
|
|
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, MaxMessageSize, "max_size")
|
|
|
|
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, IncomingDuplicateAction, "dup_action")
|
|
|
|
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, Hidden, "hidden")
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetSocketType(int32_t *aSocketType)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsresult rv = mPrefBranch->GetIntPref("socketType", aSocketType);
|
|
|
|
// socketType is set to default value. Look at isSecure setting
|
|
if (NS_FAILED(rv))
|
|
{
|
|
bool isSecure;
|
|
rv = mPrefBranch->GetBoolPref("isSecure", &isSecure);
|
|
if (NS_SUCCEEDED(rv) && isSecure)
|
|
{
|
|
*aSocketType = nsMsgSocketType::SSL;
|
|
// don't call virtual method in case overrides call GetSocketType
|
|
nsMsgIncomingServer::SetSocketType(*aSocketType);
|
|
}
|
|
else
|
|
{
|
|
if (!mDefPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
rv = mDefPrefBranch->GetIntPref("socketType", aSocketType);
|
|
if (NS_FAILED(rv))
|
|
*aSocketType = nsMsgSocketType::plain;
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::SetSocketType(int32_t aSocketType)
|
|
{
|
|
if (!mPrefBranch)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
int32_t socketType = nsMsgSocketType::plain;
|
|
mPrefBranch->GetIntPref("socketType", &socketType);
|
|
|
|
nsresult rv = mPrefBranch->SetIntPref("socketType", aSocketType);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool isSecureOld = (socketType == nsMsgSocketType::alwaysSTARTTLS ||
|
|
socketType == nsMsgSocketType::SSL);
|
|
bool isSecureNew = (aSocketType == nsMsgSocketType::alwaysSTARTTLS ||
|
|
aSocketType == nsMsgSocketType::SSL);
|
|
if ((isSecureOld != isSecureNew) && m_rootFolder) {
|
|
nsCOMPtr <nsIAtom> isSecureAtom = MsgGetAtom("isSecure");
|
|
m_rootFolder->NotifyBoolPropertyChanged(isSecureAtom,
|
|
isSecureOld, isSecureNew);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// Check if the password is available and return a boolean indicating whether
|
|
// it is being authenticated or not.
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetPasswordPromptRequired(bool *aPasswordIsRequired)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aPasswordIsRequired);
|
|
*aPasswordIsRequired = true;
|
|
|
|
// If the password is not even required for biff we don't need to check any further
|
|
nsresult rv = GetServerRequiresPasswordForBiff(aPasswordIsRequired);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (!*aPasswordIsRequired)
|
|
return NS_OK;
|
|
|
|
// If the password is empty, check to see if it is stored and to be retrieved
|
|
if (m_password.IsEmpty())
|
|
(void)GetPasswordWithoutUI();
|
|
|
|
*aPasswordIsRequired = m_password.IsEmpty();
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::ConfigureTemporaryFilters(nsIMsgFilterList *aFilterList)
|
|
{
|
|
nsresult rv = ConfigureTemporaryReturnReceiptsFilter(aFilterList);
|
|
if (NS_FAILED(rv)) // shut up warnings...
|
|
return rv;
|
|
return ConfigureTemporaryServerSpamFilters(aFilterList);
|
|
}
|
|
|
|
nsresult
|
|
nsMsgIncomingServer::ConfigureTemporaryServerSpamFilters(nsIMsgFilterList *filterList)
|
|
{
|
|
nsCOMPtr<nsISpamSettings> spamSettings;
|
|
nsresult rv = GetSpamSettings(getter_AddRefs(spamSettings));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool useServerFilter;
|
|
rv = spamSettings->GetUseServerFilter(&useServerFilter);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// if we aren't configured to use server filters, then return early.
|
|
if (!useServerFilter)
|
|
return NS_OK;
|
|
|
|
// For performance reasons, we'll handle clearing of filters if the user turns
|
|
// off the server-side filters from the junk mail controls, in the junk mail controls.
|
|
nsAutoCString serverFilterName;
|
|
spamSettings->GetServerFilterName(serverFilterName);
|
|
if (serverFilterName.IsEmpty())
|
|
return NS_OK;
|
|
int32_t serverFilterTrustFlags = 0;
|
|
(void) spamSettings->GetServerFilterTrustFlags(&serverFilterTrustFlags);
|
|
if (!serverFilterTrustFlags)
|
|
return NS_OK;
|
|
// check if filters have been setup already.
|
|
nsAutoString yesFilterName, noFilterName;
|
|
CopyASCIItoUTF16(serverFilterName, yesFilterName);
|
|
yesFilterName.AppendLiteral("Yes");
|
|
|
|
CopyASCIItoUTF16(serverFilterName, noFilterName);
|
|
noFilterName.AppendLiteral("No");
|
|
|
|
nsCOMPtr<nsIMsgFilter> newFilter;
|
|
(void) filterList->GetFilterNamed(yesFilterName,
|
|
getter_AddRefs(newFilter));
|
|
|
|
if (!newFilter)
|
|
(void) filterList->GetFilterNamed(noFilterName,
|
|
getter_AddRefs(newFilter));
|
|
if (newFilter)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIFile> file;
|
|
spamSettings->GetServerFilterFile(getter_AddRefs(file));
|
|
|
|
// it's possible that we can no longer find the sfd file (i.e. the user disabled an extnsion that
|
|
// was supplying the .sfd file.
|
|
if (!file)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIMsgFilterService> filterService = do_GetService(NS_MSGFILTERSERVICE_CONTRACTID, &rv);
|
|
nsCOMPtr<nsIMsgFilterList> serverFilterList;
|
|
|
|
rv = filterService->OpenFilterList(file, NULL, NULL, getter_AddRefs(serverFilterList));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = serverFilterList->GetFilterNamed(yesFilterName,
|
|
getter_AddRefs(newFilter));
|
|
if (newFilter && serverFilterTrustFlags & nsISpamSettings::TRUST_POSITIVES)
|
|
{
|
|
newFilter->SetTemporary(true);
|
|
// check if we're supposed to move junk mail to junk folder; if so,
|
|
// add filter action to do so.
|
|
|
|
/*
|
|
* We don't want this filter to activate on messages that have
|
|
* been marked by the user as not spam. This occurs when messages that
|
|
* were marked as good are moved back into the inbox. But to
|
|
* do this with a filter, we have to add a boolean term. That requires
|
|
* that we rewrite the existing filter search terms to group them.
|
|
*/
|
|
|
|
// get the list of search terms from the filter
|
|
nsCOMPtr<nsISupportsArray> searchTerms;
|
|
rv = newFilter->GetSearchTerms(getter_AddRefs(searchTerms));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
uint32_t count = 0;
|
|
searchTerms->Count(&count);
|
|
if (count > 1) // don't need to group a single term
|
|
{
|
|
// beginGrouping the first term, and endGrouping the last term
|
|
nsCOMPtr<nsIMsgSearchTerm> firstTerm(do_QueryElementAt(searchTerms,
|
|
0, &rv));
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
firstTerm->SetBeginsGrouping(true);
|
|
|
|
nsCOMPtr<nsIMsgSearchTerm> lastTerm(do_QueryElementAt(searchTerms,
|
|
count - 1, &rv));
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
lastTerm->SetEndsGrouping(true);
|
|
}
|
|
|
|
// Create a new term, checking if the user set junk status. The term will
|
|
// search for junkscoreorigin != "user"
|
|
nsCOMPtr<nsIMsgSearchTerm> searchTerm;
|
|
rv = newFilter->CreateTerm(getter_AddRefs(searchTerm));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
searchTerm->SetAttrib(nsMsgSearchAttrib::JunkScoreOrigin);
|
|
searchTerm->SetOp(nsMsgSearchOp::Isnt);
|
|
searchTerm->SetBooleanAnd(true);
|
|
|
|
nsCOMPtr<nsIMsgSearchValue> searchValue;
|
|
searchTerm->GetValue(getter_AddRefs(searchValue));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
searchValue->SetAttrib(nsMsgSearchAttrib::JunkScoreOrigin);
|
|
searchValue->SetStr(NS_LITERAL_STRING("user"));
|
|
searchTerm->SetValue(searchValue);
|
|
|
|
searchTerms->InsertElementAt(searchTerm, count);
|
|
|
|
bool moveOnSpam, markAsReadOnSpam;
|
|
spamSettings->GetMoveOnSpam(&moveOnSpam);
|
|
if (moveOnSpam)
|
|
{
|
|
nsCString spamFolderURI;
|
|
rv = spamSettings->GetSpamFolderURI(getter_Copies(spamFolderURI));
|
|
if (NS_SUCCEEDED(rv) && (!spamFolderURI.IsEmpty()))
|
|
{
|
|
nsCOMPtr <nsIMsgRuleAction> moveAction;
|
|
rv = newFilter->CreateAction(getter_AddRefs(moveAction));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
moveAction->SetType(nsMsgFilterAction::MoveToFolder);
|
|
moveAction->SetTargetFolderUri(spamFolderURI);
|
|
newFilter->AppendAction(moveAction);
|
|
}
|
|
}
|
|
}
|
|
spamSettings->GetMarkAsReadOnSpam(&markAsReadOnSpam);
|
|
if (markAsReadOnSpam)
|
|
{
|
|
nsCOMPtr <nsIMsgRuleAction> markAsReadAction;
|
|
rv = newFilter->CreateAction(getter_AddRefs(markAsReadAction));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
markAsReadAction->SetType(nsMsgFilterAction::MarkRead);
|
|
newFilter->AppendAction(markAsReadAction);
|
|
}
|
|
}
|
|
filterList->InsertFilterAt(0, newFilter);
|
|
}
|
|
|
|
rv = serverFilterList->GetFilterNamed(noFilterName,
|
|
getter_AddRefs(newFilter));
|
|
if (newFilter && serverFilterTrustFlags & nsISpamSettings::TRUST_NEGATIVES)
|
|
{
|
|
newFilter->SetTemporary(true);
|
|
filterList->InsertFilterAt(0, newFilter);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsMsgIncomingServer::ConfigureTemporaryReturnReceiptsFilter(nsIMsgFilterList *filterList)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIMsgAccountManager> accountMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIMsgIdentity> identity;
|
|
rv = accountMgr->GetFirstIdentityForServer(this, getter_AddRefs(identity));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
// this can return success and a null identity...
|
|
|
|
bool useCustomPrefs = false;
|
|
int32_t incorp = nsIMsgMdnGenerator::eIncorporateInbox;
|
|
NS_ENSURE_TRUE(identity, NS_ERROR_NULL_POINTER);
|
|
|
|
identity->GetBoolAttribute("use_custom_prefs", &useCustomPrefs);
|
|
if (useCustomPrefs)
|
|
rv = GetIntValue("incorporate_return_receipt", &incorp);
|
|
else
|
|
{
|
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
|
if (prefs)
|
|
prefs->GetIntPref("mail.incorporate.return_receipt", &incorp);
|
|
}
|
|
|
|
bool enable = (incorp == nsIMsgMdnGenerator::eIncorporateSent);
|
|
|
|
// this is a temporary, internal mozilla filter
|
|
// it will not show up in the UI, it will not be written to disk
|
|
NS_NAMED_LITERAL_STRING(internalReturnReceiptFilterName, "mozilla-temporary-internal-MDN-receipt-filter");
|
|
|
|
nsCOMPtr<nsIMsgFilter> newFilter;
|
|
rv = filterList->GetFilterNamed(internalReturnReceiptFilterName,
|
|
getter_AddRefs(newFilter));
|
|
if (newFilter)
|
|
newFilter->SetEnabled(enable);
|
|
else if (enable)
|
|
{
|
|
nsCString actionTargetFolderUri;
|
|
rv = identity->GetFccFolder(actionTargetFolderUri);
|
|
if (!actionTargetFolderUri.IsEmpty())
|
|
{
|
|
filterList->CreateFilter(internalReturnReceiptFilterName,
|
|
getter_AddRefs(newFilter));
|
|
if (newFilter)
|
|
{
|
|
newFilter->SetEnabled(true);
|
|
// this internal filter is temporary
|
|
// and should not show up in the UI or be written to disk
|
|
newFilter->SetTemporary(true);
|
|
|
|
nsCOMPtr<nsIMsgSearchTerm> term;
|
|
nsCOMPtr<nsIMsgSearchValue> value;
|
|
|
|
rv = newFilter->CreateTerm(getter_AddRefs(term));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
rv = term->GetValue(getter_AddRefs(value));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
// we need to use OtherHeader + 1 so nsMsgFilter::GetTerm will
|
|
// return our custom header.
|
|
value->SetAttrib(nsMsgSearchAttrib::OtherHeader + 1);
|
|
value->SetStr(NS_LITERAL_STRING("multipart/report"));
|
|
term->SetAttrib(nsMsgSearchAttrib::OtherHeader + 1);
|
|
term->SetOp(nsMsgSearchOp::Contains);
|
|
term->SetBooleanAnd(true);
|
|
term->SetArbitraryHeader(NS_LITERAL_CSTRING("Content-Type"));
|
|
term->SetValue(value);
|
|
newFilter->AppendTerm(term);
|
|
}
|
|
}
|
|
rv = newFilter->CreateTerm(getter_AddRefs(term));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
rv = term->GetValue(getter_AddRefs(value));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
// XXX todo
|
|
// determine if ::OtherHeader is the best way to do this.
|
|
// see nsMsgSearchOfflineMail::MatchTerms()
|
|
value->SetAttrib(nsMsgSearchAttrib::OtherHeader + 1);
|
|
value->SetStr(NS_LITERAL_STRING("disposition-notification"));
|
|
term->SetAttrib(nsMsgSearchAttrib::OtherHeader + 1);
|
|
term->SetOp(nsMsgSearchOp::Contains);
|
|
term->SetBooleanAnd(true);
|
|
term->SetArbitraryHeader(NS_LITERAL_CSTRING("Content-Type"));
|
|
term->SetValue(value);
|
|
newFilter->AppendTerm(term);
|
|
}
|
|
}
|
|
nsCOMPtr<nsIMsgRuleAction> filterAction;
|
|
rv = newFilter->CreateAction(getter_AddRefs(filterAction));
|
|
if (NS_SUCCEEDED(rv))
|
|
{
|
|
filterAction->SetType(nsMsgFilterAction::MoveToFolder);
|
|
filterAction->SetTargetFolderUri(actionTargetFolderUri);
|
|
newFilter->AppendAction(filterAction);
|
|
filterList->InsertFilterAt(0, newFilter);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::ClearTemporaryReturnReceiptsFilter()
|
|
{
|
|
if (mFilterList)
|
|
{
|
|
nsCOMPtr<nsIMsgFilter> mdnFilter;
|
|
nsresult rv = mFilterList->GetFilterNamed(NS_LITERAL_STRING("mozilla-temporary-internal-MDN-receipt-filter"),
|
|
getter_AddRefs(mdnFilter));
|
|
if (NS_SUCCEEDED(rv) && mdnFilter)
|
|
return mFilterList->RemoveFilter(mdnFilter);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetMsgFolderFromURI(nsIMsgFolder *aFolderResource, const nsACString& aURI, nsIMsgFolder **aFolder)
|
|
{
|
|
nsCOMPtr<nsIMsgFolder> rootMsgFolder;
|
|
nsresult rv = GetRootMsgFolder(getter_AddRefs(rootMsgFolder));
|
|
NS_ENSURE_TRUE(rootMsgFolder, NS_ERROR_UNEXPECTED);
|
|
|
|
nsCOMPtr <nsIMsgFolder> msgFolder;
|
|
rv = rootMsgFolder->GetChildWithURI(aURI, true, true /*caseInsensitive*/, getter_AddRefs(msgFolder));
|
|
if (NS_FAILED(rv) || !msgFolder)
|
|
msgFolder = aFolderResource;
|
|
NS_IF_ADDREF(*aFolder = msgFolder);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetSpamSettings(nsISpamSettings **aSpamSettings)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSpamSettings);
|
|
|
|
nsAutoCString spamActionTargetAccount;
|
|
GetCharValue("spamActionTargetAccount", spamActionTargetAccount);
|
|
if (spamActionTargetAccount.IsEmpty())
|
|
{
|
|
GetServerURI(spamActionTargetAccount);
|
|
SetCharValue("spamActionTargetAccount", spamActionTargetAccount);
|
|
}
|
|
|
|
if (!mSpamSettings) {
|
|
nsresult rv;
|
|
mSpamSettings = do_CreateInstance(NS_SPAMSETTINGS_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
mSpamSettings->Initialize(this);
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
}
|
|
|
|
NS_ADDREF(*aSpamSettings = mSpamSettings);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetSpamFilterPlugin(nsIMsgFilterPlugin **aFilterPlugin)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aFilterPlugin);
|
|
if (!mFilterPlugin)
|
|
{
|
|
nsresult rv;
|
|
mFilterPlugin = do_GetService("@mozilla.org/messenger/filter-plugin;1?name=bayesianfilter", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
NS_IF_ADDREF(*aFilterPlugin = mFilterPlugin);
|
|
return NS_OK;
|
|
}
|
|
|
|
// get all the servers that defer to the account for the passed in server. Note that
|
|
// destServer may not be "this"
|
|
nsresult nsMsgIncomingServer::GetDeferredServers(nsIMsgIncomingServer *destServer, nsCOMArray<nsIPop3IncomingServer>& aServers)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIMsgAccountManager> accountManager
|
|
= do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr <nsIMsgAccount> thisAccount;
|
|
accountManager->FindAccountForServer(destServer, getter_AddRefs(thisAccount));
|
|
if (thisAccount)
|
|
{
|
|
nsCOMPtr<nsIArray> allServers;
|
|
nsCString accountKey;
|
|
thisAccount->GetKey(accountKey);
|
|
accountManager->GetAllServers(getter_AddRefs(allServers));
|
|
if (allServers)
|
|
{
|
|
uint32_t serverCount;
|
|
allServers->GetLength(&serverCount);
|
|
for (uint32_t i = 0; i < serverCount; i++)
|
|
{
|
|
nsCOMPtr<nsIPop3IncomingServer> server(do_QueryElementAt(allServers, i));
|
|
if (server)
|
|
{
|
|
nsCString deferredToAccount;
|
|
server->GetDeferredToAccount(deferredToAccount);
|
|
if (deferredToAccount.Equals(accountKey))
|
|
aServers.AppendElement(server);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsMsgIncomingServer::GetIsDeferredTo(bool *aIsDeferredTo)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aIsDeferredTo);
|
|
nsCOMPtr<nsIMsgAccountManager> accountManager
|
|
= do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID);
|
|
if (accountManager)
|
|
{
|
|
nsCOMPtr <nsIMsgAccount> thisAccount;
|
|
accountManager->FindAccountForServer(this, getter_AddRefs(thisAccount));
|
|
if (thisAccount)
|
|
{
|
|
nsCOMPtr<nsIArray> allServers;
|
|
nsCString accountKey;
|
|
thisAccount->GetKey(accountKey);
|
|
accountManager->GetAllServers(getter_AddRefs(allServers));
|
|
if (allServers)
|
|
{
|
|
uint32_t serverCount;
|
|
allServers->GetLength(&serverCount);
|
|
for (uint32_t i = 0; i < serverCount; i++)
|
|
{
|
|
nsCOMPtr <nsIMsgIncomingServer> server (do_QueryElementAt(allServers, i));
|
|
if (server)
|
|
{
|
|
nsCString deferredToAccount;
|
|
server->GetCharValue("deferred_to_account", deferredToAccount);
|
|
if (deferredToAccount.Equals(accountKey))
|
|
{
|
|
*aIsDeferredTo = true;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*aIsDeferredTo = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
const long kMaxDownloadTableSize = 500;
|
|
|
|
// hash the concatenation of the message-id and subject as the hash table key,
|
|
// and store the arrival index as the value. To limit the size of the hash table,
|
|
// we just throw out ones with a lower ordinal value than the cut-off point.
|
|
NS_IMETHODIMP nsMsgIncomingServer::IsNewHdrDuplicate(nsIMsgDBHdr *aNewHdr, bool *aResult)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
NS_ENSURE_ARG_POINTER(aNewHdr);
|
|
*aResult = false;
|
|
|
|
// If the message has been partially downloaded, the message should not
|
|
// be considered a duplicated message. See bug 714090.
|
|
uint32_t flags;
|
|
aNewHdr->GetFlags(&flags);
|
|
if (flags & nsMsgMessageFlags::Partial)
|
|
return NS_OK;
|
|
|
|
nsAutoCString strHashKey;
|
|
nsCString messageId, subject;
|
|
aNewHdr->GetMessageId(getter_Copies(messageId));
|
|
strHashKey.Append(messageId);
|
|
aNewHdr->GetSubject(getter_Copies(subject));
|
|
// err on the side of caution and ignore messages w/o subject or messageid.
|
|
if (subject.IsEmpty() || messageId.IsEmpty())
|
|
return NS_OK;
|
|
strHashKey.Append(subject);
|
|
int32_t hashValue = 0;
|
|
m_downloadedHdrs.Get(strHashKey, &hashValue);
|
|
if (hashValue)
|
|
*aResult = true;
|
|
else
|
|
{
|
|
// we store the current size of the hash table as the hash
|
|
// value - this allows us to delete older entries.
|
|
m_downloadedHdrs.Put(strHashKey, ++m_numMsgsDownloaded);
|
|
// Check if hash table is larger than some reasonable size
|
|
// and if is it, iterate over hash table deleting messages
|
|
// with an arrival index < number of msgs downloaded - half the reasonable size.
|
|
if (m_downloadedHdrs.Count() >= kMaxDownloadTableSize) {
|
|
for (auto iter = m_downloadedHdrs.Iter(); !iter.Done(); iter.Next()) {
|
|
if (iter.Data() < m_numMsgsDownloaded - kMaxDownloadTableSize/2) {
|
|
iter.Remove();
|
|
} else if (m_downloadedHdrs.Count() <= kMaxDownloadTableSize/2) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetForcePropertyEmpty(const char *aPropertyName, bool *_retval)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(_retval);
|
|
nsAutoCString nameEmpty(aPropertyName);
|
|
nameEmpty.Append(NS_LITERAL_CSTRING(".empty"));
|
|
nsCString value;
|
|
GetCharValue(nameEmpty.get(), value);
|
|
*_retval = value.EqualsLiteral("true");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::SetForcePropertyEmpty(const char *aPropertyName, bool aValue)
|
|
{
|
|
nsAutoCString nameEmpty(aPropertyName);
|
|
nameEmpty.Append(NS_LITERAL_CSTRING(".empty"));
|
|
return SetCharValue(nameEmpty.get(),
|
|
aValue ? NS_LITERAL_CSTRING("true") : NS_LITERAL_CSTRING(""));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMsgIncomingServer::GetSortOrder(int32_t* aSortOrder)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSortOrder);
|
|
*aSortOrder = 100000000;
|
|
return NS_OK;
|
|
}
|