gecko-dev/mailnews/base/src/nsMsgAccountManager.cpp
dwitte%stanford.edu 270d3909ca bug 100649: Length() being used where IsEmpty() is meant
treewide changes to convert incorrect usages of string.Length() to string.IsEmpty().

thanks to afatecha@idea.com.py (Ariel Fatecha) for the patch. r=dwitte, sr=jst.

got the ok from Asa to land into a closed tree.
2003-05-23 21:34:47 +00:00

2345 lines
68 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alec Flett <alecf@netscape.com>
* Seth Spitzer <sspitzer@netscape.com>
* Bhuvan Racham <racham@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* The account manager service - manages all accounts, servers, and identities
*/
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsMsgAccountManager.h"
#include "nsMsgBaseCID.h"
#include "nsMsgCompCID.h"
#include "prmem.h"
#include "prcmon.h"
#include "prthread.h"
#include "plstr.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "nsUnicharUtils.h"
#include "nscore.h"
#include "nsCRT.h" // for nsCRT::strtok
#include "prprf.h"
#include "nsIMsgFolderCache.h"
#include "nsFileStream.h"
#include "nsMsgUtils.h"
#include "nsIFileSpec.h"
#include "nsILocalFile.h"
#include "nsIURL.h"
#include "nsNetCID.h"
#include "nsISmtpService.h"
#include "nsIMsgBiffManager.h"
#include "nsIMsgPurgeService.h"
#include "nsIObserverService.h"
#include "nsIMsgMailSession.h"
#include "nsIEventQueueService.h"
#include "nsIDirectoryService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsMsgFolderFlags.h"
#include "nsIRDFService.h"
#include "nsRDFCID.h"
#include "nsIImapIncomingServer.h"
#include "nsIImapUrl.h"
#include "nsIMessengerOSIntegration.h"
#define PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS "mail.accountmanager.accounts"
#define PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT "mail.accountmanager.defaultaccount"
#define PREF_MAIL_ACCOUNTMANAGER_LOCALFOLDERSSERVER "mail.accountmanager.localfoldersserver"
#define PREF_MAIL_SERVER_PREFIX "mail.server."
#define ACCOUNT_PREFIX "account"
#define SERVER_PREFIX "server"
#define ID_PREFIX "id"
#define ABOUT_TO_GO_OFFLINE_TOPIC "network:offline-about-to-go-offline"
#define ACCOUNT_DELIMITER ","
#define APPEND_ACCOUNTS_VERSION_PREF_NAME "append_preconfig_accounts.version"
#define MAILNEWS_ROOT_PREF "mailnews."
#define PREF_MAIL_ACCOUNTMANAGER_APPEND_ACCOUNTS "mail.accountmanager.appendaccounts"
static NS_DEFINE_CID(kMsgAccountCID, NS_MSGACCOUNT_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
static NS_DEFINE_CID(kMsgBiffManagerCID, NS_MSGBIFFMANAGER_CID);
static NS_DEFINE_CID(kMsgFolderCacheCID, NS_MSGFOLDERCACHE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
// use this to search for all servers with the given hostname/iid and
// put them in "servers"
typedef struct _findServerEntry {
const char *hostname;
const char *username;
const char *type;
PRBool useRealSetting;
nsIMsgIncomingServer *server;
} findServerEntry;
typedef struct _findServerByKeyEntry {
const char *key;
PRInt32 index;
} findServerByKeyEntry;
// use this to search for all servers that match "server" and
// put all identities in "identities"
typedef struct _findIdentitiesByServerEntry {
nsISupportsArray *identities;
nsIMsgIncomingServer *server;
} findIdentitiesByServerEntry;
typedef struct _findServersByIdentityEntry {
nsISupportsArray *servers;
nsIMsgIdentity *identity;
} findServersByIdentityEntry;
typedef struct _findAccountByKeyEntry {
const char* key;
nsIMsgAccount* account;
} findAccountByKeyEntry;
NS_IMPL_THREADSAFE_ISUPPORTS4(nsMsgAccountManager,
nsIMsgAccountManager,
nsIObserver,
nsISupportsWeakReference,
nsIUrlListener)
nsMsgAccountManager::nsMsgAccountManager() :
m_accountsLoaded(PR_FALSE),
m_defaultAccount(nsnull),
m_emptyTrashInProgress(PR_FALSE),
m_cleanupInboxInProgress(PR_FALSE),
m_haveShutdown(PR_FALSE),
m_shutdownInProgress(PR_FALSE),
m_prefs(0)
{
}
nsMsgAccountManager::~nsMsgAccountManager()
{
nsresult rv;
if(!m_haveShutdown)
{
Shutdown();
//Don't remove from Observer service in Shutdown because Shutdown also gets called
//from xpcom shutdown observer. And we don't want to remove from the service in that case.
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->RemoveObserver(this, ABOUT_TO_GO_OFFLINE_TOPIC);
}
}
}
nsresult nsMsgAccountManager::Init()
{
nsresult rv;
rv = NS_NewISupportsArray(getter_AddRefs(m_accounts));
if(NS_FAILED(rv)) return rv;
rv = NS_NewISupportsArray(getter_AddRefs(mFolderListeners));
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
{
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
observerService->AddObserver(this, "quit-application" , PR_TRUE);
observerService->AddObserver(this, ABOUT_TO_GO_OFFLINE_TOPIC, PR_TRUE);
observerService->AddObserver(this, "session-logout", PR_TRUE);
observerService->AddObserver(this, "profile-before-change", PR_TRUE);
}
return NS_OK;
}
nsresult nsMsgAccountManager::Shutdown()
{
if (m_haveShutdown) {
// do not shutdown twice
return NS_OK;
}
nsresult rv;
if(m_msgFolderCache)
{
WriteToFolderCache(m_msgFolderCache);
}
(void)ShutdownServers();
(void)UnloadAccounts();
//shutdown removes nsIIncomingServer listener from biff manager, so do it after accounts have been unloaded
nsCOMPtr<nsIMsgBiffManager> biffService = do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && biffService)
biffService->Shutdown();
//shutdown removes nsIIncomingServer listener from purge service, so do it after accounts have been unloaded
nsCOMPtr<nsIMsgPurgeService> purgeService = do_GetService(NS_MSGPURGESERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && purgeService)
purgeService->Shutdown();
if (m_prefs) {
nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
m_prefs = 0;
}
m_msgFolderCache = nsnull;
m_haveShutdown = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::GetShutdownInProgress(PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = m_shutdownInProgress;
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
{
if(!nsCRT::strcmp(aTopic,NS_XPCOM_SHUTDOWN_OBSERVER_ID))
{
Shutdown();
return NS_OK;
}
if (!nsCRT::strcmp(aTopic,"quit-application"))
{
m_shutdownInProgress = PR_TRUE;
return NS_OK;
}
if (!nsCRT::strcmp(aTopic, ABOUT_TO_GO_OFFLINE_TOPIC))
{
nsAutoString dataString(NS_LITERAL_STRING("offline"));
if (someData)
{
nsAutoString someDataString(someData);
if (dataString == someDataString)
CloseCachedConnections();
}
return NS_OK;
}
if (!nsCRT::strcmp(aTopic, "session-logout"))
{
m_incomingServers.Enumerate(hashLogoutOfServer, nsnull);
return NS_OK;
}
if (!nsCRT::strcmp(aTopic, "profile-before-change"))
{
Shutdown();
return NS_OK;
}
return NS_OK;
}
nsresult
nsMsgAccountManager::getPrefService()
{
// get the prefs service
nsresult rv = NS_OK;
if (!m_prefs)
rv = nsServiceManager::GetService(kPrefServiceCID,
NS_GET_IID(nsIPref),
(nsISupports**)&m_prefs);
if (NS_FAILED(rv)) return rv;
/* m_prefs is good now */
return NS_OK;
}
void
nsMsgAccountManager::getUniqueKey(const char* prefix,
nsHashtable *hashTable,
nsCString& aResult)
{
PRInt32 i=1;
PRBool unique=PR_FALSE;
do {
aResult=prefix;
aResult.AppendInt(i++);
nsCStringKey hashKey(aResult);
void* hashElement = hashTable->Get(&hashKey);
if (!hashElement) unique=PR_TRUE;
} while (!unique);
}
void
nsMsgAccountManager::getUniqueAccountKey(const char *prefix,
nsISupportsArray *accounts,
nsCString& aResult)
{
PRInt32 i=1;
PRBool unique = PR_FALSE;
findAccountByKeyEntry findEntry;
findEntry.account = nsnull;
do {
aResult = prefix;
aResult.AppendInt(i++);
findEntry.key = aResult.get();
accounts->EnumerateForwards(findAccountByKey, (void *)&findEntry);
if (!findEntry.account) unique=PR_TRUE;
findEntry.account = nsnull;
} while (!unique);
}
nsresult
nsMsgAccountManager::CreateIdentity(nsIMsgIdentity **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
nsresult rv;
nsCAutoString key;
getUniqueKey(ID_PREFIX, &m_identities, key);
rv = createKeyedIdentity(key.get(), _retval);
return rv;
}
nsresult
nsMsgAccountManager::GetIdentity(const char* key,
nsIMsgIdentity **_retval)
{
if (!_retval) return NS_ERROR_NULL_POINTER;
// null or empty key does not return an identity!
if (!key || !key[0]) {
*_retval = nsnull;
return NS_OK;
}
nsresult rv;
// check for the identity in the hash table
nsCStringKey hashKey(key);
nsISupports *idsupports = (nsISupports*)m_identities.Get(&hashKey);
nsCOMPtr<nsIMsgIdentity> identity = do_QueryInterface(idsupports, &rv);
if (NS_SUCCEEDED(rv)) {
*_retval = identity;
NS_ADDREF(*_retval);
return NS_OK;
}
// identity doesn't exist. create it.
rv = createKeyedIdentity(key, _retval);
return rv;
}
/*
* the shared identity-creation code
* create an identity and add it to the accountmanager's list.
*/
nsresult
nsMsgAccountManager::createKeyedIdentity(const char* key,
nsIMsgIdentity ** aIdentity)
{
nsresult rv;
nsCOMPtr<nsIMsgIdentity> identity;
rv = nsComponentManager::CreateInstance(NS_MSGIDENTITY_CONTRACTID,
nsnull,
NS_GET_IID(nsIMsgIdentity),
getter_AddRefs(identity));
if (NS_FAILED(rv)) return rv;
identity->SetKey(NS_CONST_CAST(char *,key));
nsCStringKey hashKey(key);
// addref for the hash table`
nsISupports* idsupports = identity;
NS_ADDREF(idsupports);
m_identities.Put(&hashKey, (void *)idsupports);
*aIdentity = identity;
NS_ADDREF(*aIdentity);
return NS_OK;
}
nsresult
nsMsgAccountManager::CreateIncomingServer(const char* username,
const char* hostname,
const char* type,
nsIMsgIncomingServer **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
nsresult rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCAutoString key;
getUniqueKey(SERVER_PREFIX, &m_incomingServers, key);
return createKeyedServer(key.get(), username, hostname, type, _retval);
}
nsresult
nsMsgAccountManager::GetIncomingServer(const char* key,
nsIMsgIncomingServer **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
nsresult rv=NS_OK;
nsCStringKey hashKey(key);
nsCOMPtr<nsIMsgIncomingServer> server =
do_QueryInterface((nsISupports*)m_incomingServers.Get(&hashKey), &rv);
if (NS_SUCCEEDED(rv)) {
*_retval = server;
NS_ADDREF(*_retval);
return NS_OK;
}
// server doesn't exist, so create it
// this is really horrible because we are doing our own prefname munging
// instead of leaving it up to the incoming server.
// this should be fixed somehow so that we can create the incoming server
// and then read from the incoming server's attributes
// in order to create the right kind of server, we have to look
// at the pref for this server to get the username, hostname, and type
nsCAutoString serverPrefPrefix(PREF_MAIL_SERVER_PREFIX);
serverPrefPrefix += key;
nsCAutoString serverPref;
//
// .type
serverPref = serverPrefPrefix;
serverPref += ".type";
nsXPIDLCString serverType;
rv = m_prefs->CopyCharPref(serverPref.get(), getter_Copies(serverType));
NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_INITIALIZED);
//
// .userName
serverPref = serverPrefPrefix;
serverPref += ".userName";
nsXPIDLCString username;
rv = m_prefs->CopyCharPref(serverPref.get(), getter_Copies(username));
// .hostname
serverPref = serverPrefPrefix;
serverPref += ".hostname";
nsXPIDLCString hostname;
rv = m_prefs->CopyCharPref(serverPref.get(), getter_Copies(hostname));
NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_INITIALIZED);
// the server type doesn't exist. That's bad.
rv = createKeyedServer(key, username, hostname, serverType, _retval);
NS_ENSURE_SUCCESS(rv, rv);
return rv;
}
/*
* create a server when you know the key and the type
*/
nsresult
nsMsgAccountManager::createKeyedServer(const char* key,
const char* username,
const char* hostname,
const char* type,
nsIMsgIncomingServer ** aServer)
{
nsresult rv;
//construct the contractid
nsCAutoString serverContractID(NS_MSGINCOMINGSERVER_CONTRACTID_PREFIX);
serverContractID += type;
// finally, create the server
nsCOMPtr<nsIMsgIncomingServer> server =
do_CreateInstance(serverContractID.get(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
server->SetKey(key);
server->SetType(type);
server->SetUsername(username);
server->SetHostName(hostname);
nsCStringKey hashKey(key);
// addref for the hashtable
nsISupports* serversupports = server;
NS_ADDREF(serversupports);
m_incomingServers.Put(&hashKey, serversupports);
// now add all listeners that are supposed to be
// waiting on root folders
nsCOMPtr<nsIFolder> rootFolder;
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
mFolderListeners->EnumerateForwards(addListenerToFolder,
(void *)(nsIFolder*)rootFolder);
*aServer = server;
NS_ADDREF(*aServer);
return NS_OK;
}
PRBool
nsMsgAccountManager::addListenerToFolder(nsISupports *element, void *data)
{
nsresult rv;
nsIFolder *rootFolder = (nsIFolder *)data;
nsCOMPtr<nsIFolderListener> listener = do_QueryInterface(element, &rv);
NS_ENSURE_SUCCESS(rv, PR_TRUE);
rootFolder->AddFolderListener(listener);
return PR_TRUE;
}
PRBool
nsMsgAccountManager::removeListenerFromFolder(nsISupports *element, void *data)
{
nsresult rv;
nsIFolder *rootFolder = (nsIFolder *)data;
nsCOMPtr<nsIFolderListener> listener = do_QueryInterface(element, &rv);
NS_ENSURE_SUCCESS(rv, PR_TRUE);
rootFolder->RemoveFolderListener(listener);
return PR_TRUE;
}
NS_IMETHODIMP
nsMsgAccountManager::DuplicateAccount(nsIMsgAccount *aAccount)
{
NS_ENSURE_ARG_POINTER(aAccount);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMsgAccountManager::RemoveIdentity(nsIMsgIdentity *aIdentity)
{
// finish this
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::RemoveAccount(nsIMsgAccount *aAccount)
{
NS_ENSURE_ARG_POINTER(aAccount);
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
// order is important!
// remove it from the prefs first
nsXPIDLCString key;
rv = aAccount->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return rv;
rv = removeKeyedAccount(key);
if (NS_FAILED(rv)) return rv;
// we were able to save the new prefs (i.e. not locked) so now remove it
// from the account manager... ignore the error though, because the only
// possible problem is that it wasn't in the hash table anyway... and if
// so, it doesn't matter.
m_accounts->RemoveElement(aAccount);
// if it's the default, clear the default account
if (m_defaultAccount.get() == aAccount) {
SetDefaultAccount(nsnull);
}
// XXX - need to figure out if this is the last time this server is
// being used, and only send notification then.
// (and only remove from hashtable then too!)
nsCOMPtr<nsIMsgIncomingServer> server;
rv = aAccount->GetIncomingServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server) {
nsXPIDLCString serverKey;
rv = server->GetKey(getter_Copies(serverKey));
NS_ENSURE_SUCCESS(rv,rv);
LogoutOfServer(server); // close cached connections and forget session password
// invalidate the FindServer() cache if we are removing the cached server
if (m_lastFindServerResult) {
nsXPIDLCString cachedServerKey;
rv = m_lastFindServerResult->GetKey(getter_Copies(cachedServerKey));
NS_ENSURE_SUCCESS(rv,rv);
if (!nsCRT::strcmp((const char *)serverKey,(const char *)cachedServerKey)) {
rv = SetLastServerFound(nsnull,"","","");
NS_ENSURE_SUCCESS(rv,rv);
}
}
nsCStringKey hashKey(serverKey);
nsIMsgIncomingServer* removedServer =
(nsIMsgIncomingServer*) m_incomingServers.Remove(&hashKey);
//NS_ASSERTION(server.get() == removedServer, "Key maps to different server. something wacky is going on");
// remove reference from hashtable
NS_IF_RELEASE(removedServer);
nsCOMPtr<nsIFolder> rootFolder;
server->GetRootFolder(getter_AddRefs(rootFolder));
nsCOMPtr<nsISupportsArray> allDescendents;
NS_NewISupportsArray(getter_AddRefs(allDescendents));
rootFolder->ListDescendents(allDescendents);
PRUint32 cnt =0;
rv = allDescendents->Count(&cnt);
NS_ENSURE_SUCCESS(rv,rv);
for (PRUint32 i=0; i< cnt;i++)
{
nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(allDescendents, i, &rv);
folder->ForceDBClosed();
}
mFolderListeners->EnumerateForwards(removeListenerFromFolder,
(void*)rootFolder);
NotifyServerUnloaded(server);
rv = server->RemoveFiles();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove the files associated with server");
// now clear out the server once and for all.
// watch out! could be scary
server->ClearAllValues();
rootFolder->Shutdown(PR_TRUE);
}
nsCOMPtr<nsISupportsArray> identityArray;
rv = aAccount->GetIdentities(getter_AddRefs(identityArray));
if (NS_SUCCEEDED(rv)) {
PRUint32 count=0;
identityArray->Count(&count);
PRUint32 i;
for (i=0; i<count; i++) {
nsCOMPtr<nsIMsgIdentity> identity;
rv = identityArray->QueryElementAt(i, NS_GET_IID(nsIMsgIdentity),
(void **)getter_AddRefs(identity));
if (NS_SUCCEEDED(rv))
// clear out all identity information.
// watch out! could be scary
identity->ClearAllValues();
}
}
aAccount->ClearAllValues();
return NS_OK;
}
// remove the account with the given key.
// note that this does NOT remove any of the related prefs
// (like the server, identity, etc)
nsresult
nsMsgAccountManager::removeKeyedAccount(const char *key)
{
nsresult rv;
rv = getPrefService();
if (NS_FAILED(rv)) return rv;
nsXPIDLCString accountList;
rv = m_prefs->CopyCharPref(PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS,
getter_Copies(accountList));
if (NS_FAILED(rv)) return rv;
// reconstruct the new account list, re-adding all accounts except
// the one with 'key'
nsCAutoString newAccountList;
char *newStr;
char *rest = NS_CONST_CAST(char *,(const char*)accountList);
char *token = nsCRT::strtok(rest, ",", &newStr);
while (token) {
nsCAutoString testKey(token);
testKey.StripWhitespace();
// re-add the candidate key only if it's not the key we're looking for
if (!testKey.IsEmpty() && !testKey.Equals(key)) {
if (!newAccountList.IsEmpty())
newAccountList += ',';
newAccountList += testKey;
}
token = nsCRT::strtok(newStr, ",", &newStr);
}
// Update mAccountKeyList to reflect the deletion
mAccountKeyList = newAccountList;
// now write the new account list back to the prefs
rv = m_prefs->SetCharPref(PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS,
newAccountList.get());
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
/* get the default account. If no default account, pick the first account */
NS_IMETHODIMP
nsMsgAccountManager::GetDefaultAccount(nsIMsgAccount * *aDefaultAccount)
{
NS_ENSURE_ARG_POINTER(aDefaultAccount);
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
PRUint32 count;
if (!m_defaultAccount) {
m_accounts->Count(&count);
if (count == 0) {
*aDefaultAccount=nsnull;
return NS_ERROR_FAILURE;
}
nsXPIDLCString defaultKey;
rv = m_prefs->CopyCharPref(PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT,
getter_Copies(defaultKey));
if (NS_SUCCEEDED(rv)) {
GetAccount(defaultKey, getter_AddRefs(m_defaultAccount));
} else {
PRUint32 index;
PRBool foundValidDefaultAccount = PR_FALSE;
for (index = 0; index < count; index++) {
nsCOMPtr<nsIMsgAccount> aAccount;
rv = m_accounts->QueryElementAt(index, NS_GET_IID(nsIMsgAccount),
(void **)getter_AddRefs(aAccount));
if (NS_SUCCEEDED(rv)) {
// get incoming server
nsCOMPtr <nsIMsgIncomingServer> server;
rv = aAccount->GetIncomingServer(getter_AddRefs(server));
NS_ENSURE_SUCCESS(rv,rv);
PRBool canBeDefaultServer = PR_FALSE;
if (server)
server->GetCanBeDefaultServer(&canBeDefaultServer);
// if this can serve as default server, set it as default and
// break outof the loop.
if (canBeDefaultServer) {
SetDefaultAccount(aAccount);
foundValidDefaultAccount = PR_TRUE;
break;
}
}
}
if (!foundValidDefaultAccount) {
// get the first account and use it.
// we need to fix this scenario.
nsCOMPtr<nsIMsgAccount> firstAccount;
rv = m_accounts->QueryElementAt(0, NS_GET_IID(nsIMsgAccount),
(void **)getter_AddRefs(firstAccount));
SetDefaultAccount(firstAccount);
}
}
}
*aDefaultAccount = m_defaultAccount;
NS_IF_ADDREF(*aDefaultAccount);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::SetDefaultAccount(nsIMsgAccount * aDefaultAccount)
{
if (m_defaultAccount != aDefaultAccount)
{
nsCOMPtr<nsIMsgAccount> oldAccount = m_defaultAccount;
m_defaultAccount = aDefaultAccount;
// it's ok if this fails
setDefaultAccountPref(aDefaultAccount);
// ok if notifications fail
notifyDefaultServerChange(oldAccount, aDefaultAccount);
}
return NS_OK;
}
// fire notifications
nsresult
nsMsgAccountManager::notifyDefaultServerChange(nsIMsgAccount *aOldAccount,
nsIMsgAccount *aNewAccount)
{
nsresult rv;
nsCOMPtr<nsIMsgIncomingServer> server;
nsCOMPtr<nsIFolder> rootFolder;
// first tell old server it's no longer the default
if (aOldAccount) {
rv = aOldAccount->GetIncomingServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server) {
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
rootFolder->NotifyBoolPropertyChanged(kDefaultServerAtom,
PR_TRUE, PR_FALSE);
}
}
// now tell new server it is.
if (aNewAccount) {
rv = aNewAccount->GetIncomingServer(getter_AddRefs(server));
if (NS_SUCCEEDED(rv) && server) {
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
if (NS_SUCCEEDED(rv) && rootFolder)
rootFolder->NotifyBoolPropertyChanged(kDefaultServerAtom,
PR_FALSE, PR_TRUE);
}
}
if (aOldAccount && aNewAccount) //only notify if the user goes and changes default account
{
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv))
observerService->NotifyObservers(nsnull,"mailDefaultAccountChanged",nsnull);
}
return NS_OK;
}
nsresult
nsMsgAccountManager::setDefaultAccountPref(nsIMsgAccount* aDefaultAccount)
{
nsresult rv;
rv = getPrefService();
NS_ENSURE_SUCCESS(rv,rv);
if (aDefaultAccount) {
nsXPIDLCString key;
rv = aDefaultAccount->GetKey(getter_Copies(key));
NS_ENSURE_SUCCESS(rv, rv);
rv = m_prefs->SetCharPref(PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT, key);
NS_ENSURE_SUCCESS(rv,rv);
}
else
// don't care if this fails
m_prefs->ClearUserPref(PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT);
return NS_OK;
}
// enumaration for sending unload notifications
PRBool
nsMsgAccountManager::hashUnloadServer(nsHashKey *aKey, void *aData,
void *closure)
{
nsresult rv;
nsCOMPtr<nsIMsgIncomingServer> server =
do_QueryInterface((nsISupports*)aData, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
nsMsgAccountManager *accountManager = (nsMsgAccountManager*)closure;
accountManager->NotifyServerUnloaded(server);
nsCOMPtr<nsIFolder> rootFolder;
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
accountManager->mFolderListeners->EnumerateForwards(removeListenerFromFolder,
(void *)(nsIFolder*)rootFolder);
if(NS_SUCCEEDED(rv))
rootFolder->Shutdown(PR_TRUE);
return PR_TRUE;
}
/* static */ void nsMsgAccountManager::LogoutOfServer(nsIMsgIncomingServer *aServer)
{
nsresult rv = aServer->Shutdown();
NS_ASSERTION(NS_SUCCEEDED(rv), "Shutdown of server failed");
rv = aServer->ForgetSessionPassword();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to remove the password associated with server");
}
/* static */ PRBool
nsMsgAccountManager::hashLogoutOfServer(nsHashKey *aKey, void *aData,
void *closure)
{
nsresult rv;
nsCOMPtr<nsIMsgIncomingServer> server =
do_QueryInterface((nsISupports*)aData, &rv);
if (NS_SUCCEEDED(rv))
LogoutOfServer(server);
return PR_TRUE;
}
nsresult nsMsgAccountManager::GetFolderCache(nsIMsgFolderCache* *aFolderCache)
{
if (!aFolderCache) return NS_ERROR_NULL_POINTER;
nsresult rv = NS_OK;
if (!m_msgFolderCache)
{
rv = nsComponentManager::CreateInstance(kMsgFolderCacheCID,
NULL,
NS_GET_IID(nsIMsgFolderCache),
getter_AddRefs(m_msgFolderCache));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIFile> cacheFile;
nsCOMPtr <nsIFileSpec> cacheFileSpec;
rv = NS_GetSpecialDirectory(NS_APP_MESSENGER_FOLDER_CACHE_50_DIR, getter_AddRefs(cacheFile));
if (NS_FAILED(rv)) return rv;
// TODO: Make nsIMsgFolderCache::Init take an nsIFile and
// avoid this conversion.
rv = NS_NewFileSpecFromIFile(cacheFile, getter_AddRefs(cacheFileSpec));
if (NS_FAILED(rv)) return rv;
m_msgFolderCache->Init(cacheFileSpec);
}
*aFolderCache = m_msgFolderCache;
NS_IF_ADDREF(*aFolderCache);
return rv;
}
// enumaration for writing out accounts to folder cache.
PRBool nsMsgAccountManager::writeFolderCache(nsHashKey *aKey, void *aData,
void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
nsIMsgFolderCache *folderCache = (nsIMsgFolderCache *)closure;
server->WriteToFolderCache(folderCache);
return PR_TRUE;
}
// enumeration for empty trash on exit
PRBool PR_CALLBACK nsMsgAccountManager::cleanupOnExit(nsHashKey *aKey, void *aData,
void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
PRBool emptyTrashOnExit = PR_FALSE;
PRBool cleanupInboxOnExit = PR_FALSE;
nsresult rv;
if (WeAreOffline())
return PR_TRUE;
server->GetEmptyTrashOnExit(&emptyTrashOnExit);
nsCOMPtr <nsIImapIncomingServer> imapserver = do_QueryInterface(server);
if (imapserver)
imapserver->GetCleanupInboxOnExit(&cleanupInboxOnExit);
if (emptyTrashOnExit || cleanupInboxOnExit)
{
nsCOMPtr<nsIFolder> root;
server->GetRootFolder(getter_AddRefs(root));
nsXPIDLCString type;
server->GetType(getter_Copies(type));
if (root)
{
nsCOMPtr<nsIMsgFolder> folder;
folder = do_QueryInterface(root);
if (folder)
{
nsXPIDLCString passwd;
PRBool serverRequiresPasswordForAuthentication = PR_TRUE;
PRBool isImap = (type ? PL_strcmp(type, "imap") == 0 :
PR_FALSE);
if (isImap)
{
server->GetServerRequiresPasswordForBiff(&serverRequiresPasswordForAuthentication);
server->GetPassword(getter_Copies(passwd));
}
if (!isImap || (isImap && (!serverRequiresPasswordForAuthentication || (passwd &&
strlen((const char*) passwd)))))
{
nsCOMPtr<nsIUrlListener> urlListener;
nsCOMPtr<nsIMsgAccountManager> accountManager =
do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQueue;
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(eventQueue));
if (isImap)
urlListener = do_QueryInterface(accountManager, &rv);
if (isImap && cleanupInboxOnExit)
{
nsCOMPtr<nsIEnumerator> aEnumerator;
folder->GetSubFolders(getter_AddRefs(aEnumerator));
nsCOMPtr<nsISupports> aSupport;
rv = aEnumerator->First();
while (NS_SUCCEEDED(rv))
{
rv = aEnumerator->CurrentItem(getter_AddRefs(aSupport));
nsCOMPtr<nsIMsgFolder>inboxFolder = do_QueryInterface(aSupport);
PRUint32 flags;
inboxFolder->GetFlags(&flags);
if (flags & MSG_FOLDER_FLAG_INBOX)
{
rv = inboxFolder->Compact(urlListener, nsnull /* msgwindow */);
if (NS_SUCCEEDED(rv))
accountManager->SetFolderDoingCleanupInbox(inboxFolder);
break;
}
else
rv = aEnumerator->Next();
}
}
if (emptyTrashOnExit)
{
rv = folder->EmptyTrash(nsnull, urlListener);
if (isImap && NS_SUCCEEDED(rv))
accountManager->SetFolderDoingEmptyTrash(folder);
}
if (isImap && urlListener)
{
PRBool inProgress = PR_FALSE;
if (cleanupInboxOnExit)
{
accountManager->GetCleanupInboxInProgress(&inProgress);
while (inProgress)
{
accountManager->GetCleanupInboxInProgress(&inProgress);
PR_CEnterMonitor(folder);
PR_CWait(folder, PR_MicrosecondsToInterval(1000UL));
PR_CExitMonitor(folder);
if (eventQueue)
eventQueue->ProcessPendingEvents();
}
}
if (emptyTrashOnExit)
{
accountManager->GetEmptyTrashInProgress(&inProgress);
while (inProgress)
{
accountManager->GetEmptyTrashInProgress(&inProgress);
PR_CEnterMonitor(folder);
PR_CWait(folder, PR_MicrosecondsToInterval(1000UL));
PR_CExitMonitor(folder);
if (eventQueue)
eventQueue->ProcessPendingEvents();
}
}
}
}
}
}
}
return PR_TRUE;
}
PRBool nsMsgAccountManager::closeCachedConnections(nsHashKey *aKey, void *aData, void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
server->CloseCachedConnections();
return PR_TRUE;
}
PRBool nsMsgAccountManager::shutdown(nsHashKey *aKey, void *aData, void *closure)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer*)aData;
server->Shutdown();
return PR_TRUE;
}
/* readonly attribute nsISupportsArray accounts; */
NS_IMETHODIMP
nsMsgAccountManager::GetAccounts(nsISupportsArray **_retval)
{
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> accounts;
NS_NewISupportsArray(getter_AddRefs(accounts));
accounts->AppendElements(m_accounts);
*_retval = accounts;
NS_ADDREF(*_retval);
return NS_OK;
}
PRBool
nsMsgAccountManager::hashElementToArray(nsHashKey *aKey, void *aData,
void *closure)
{
nsISupports* element = (nsISupports*)aData;
nsISupportsArray* array = (nsISupportsArray*)closure;
array->AppendElement(element);
return PR_TRUE;
}
PRBool
nsMsgAccountManager::hashElementRelease(nsHashKey *aKey, void *aData,
void *closure)
{
nsISupports* element = (nsISupports*)aData;
NS_RELEASE(element);
return PR_TRUE; // return true to remove this element
}
/* nsISupportsArray GetAllIdentities (); */
NS_IMETHODIMP
nsMsgAccountManager::GetAllIdentities(nsISupportsArray **_retval)
{
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> identities;
rv = NS_NewISupportsArray(getter_AddRefs(identities));
if (NS_FAILED(rv)) return rv;
// convert hash table->nsISupportsArray of identities
m_accounts->EnumerateForwards(getIdentitiesToArray,
(void *)(nsISupportsArray*)identities);
// convert nsISupportsArray->nsISupportsArray
// when do we free the nsISupportsArray?
*_retval = identities;
NS_ADDREF(*_retval);
return rv;
}
PRBool
nsMsgAccountManager::addIdentityIfUnique(nsISupports *element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgIdentity> identity = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) {
printf("addIdentityIfUnique problem\n");
return PR_TRUE;
}
nsISupportsArray *array = (nsISupportsArray*)aData;
nsXPIDLCString key;
rv = identity->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return PR_TRUE;
PRUint32 count=0;
rv = array->Count(&count);
if (NS_FAILED(rv)) return PR_TRUE;
PRBool found=PR_FALSE;
PRUint32 i;
for (i=0; i<count; i++) {
nsCOMPtr<nsISupports> thisElement;
array->GetElementAt(i, getter_AddRefs(thisElement));
nsCOMPtr<nsIMsgIdentity> thisIdentity =
do_QueryInterface(thisElement, &rv);
if (NS_FAILED(rv)) continue;
nsXPIDLCString thisKey;
thisIdentity->GetKey(getter_Copies(thisKey));
if (PL_strcmp(key, thisKey)==0) {
found = PR_TRUE;
break;
}
}
if (!found)
array->AppendElement(identity);
return PR_TRUE;
}
PRBool
nsMsgAccountManager::getIdentitiesToArray(nsISupports *element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
nsCOMPtr<nsISupportsArray> identities;
rv = account->GetIdentities(getter_AddRefs(identities));
if (NS_FAILED(rv)) return PR_TRUE;
identities->EnumerateForwards(addIdentityIfUnique, aData);
return PR_TRUE;
}
/* nsISupportsArray GetAllServers (); */
NS_IMETHODIMP
nsMsgAccountManager::GetAllServers(nsISupportsArray **_retval)
{
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> servers;
rv = NS_NewISupportsArray(getter_AddRefs(servers));
if (NS_FAILED(rv)) return rv;
// enumerate by going through the list of accounts, so that we
// get the order correct
m_incomingServers.Enumerate(getServersToArray,
(void *)(nsISupportsArray*)servers);
*_retval = servers;
NS_ADDREF(*_retval);
return rv;
}
PRBool PR_CALLBACK
nsMsgAccountManager::getServersToArray(nsHashKey *aKey,
void *element,
void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgIncomingServer> server =
do_QueryInterface((nsISupports*)element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
nsISupportsArray *array = (nsISupportsArray*)aData;
nsCOMPtr<nsISupports> serverSupports = do_QueryInterface(server);
if (NS_SUCCEEDED(rv))
array->AppendElement(serverSupports);
return PR_TRUE;
}
nsresult
nsMsgAccountManager::LoadAccounts()
{
nsresult rv;
// for now safeguard multiple calls to this function
if (m_accountsLoaded)
return NS_OK;
kDefaultServerAtom = do_GetAtom("DefaultServer");
//Ensure biff service has started
nsCOMPtr<nsIMsgBiffManager> biffService =
do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
biffService->Init();
//Ensure purge service has started
nsCOMPtr<nsIMsgPurgeService> purgeService =
do_GetService(NS_MSGPURGESERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
purgeService->Init();
// Ensure messenger OS integration service has started
// note, you can't expect the integrationService to be there
// we don't have OS integration on all platforms.
nsCOMPtr<nsIMessengerOSIntegration> integrationService =
do_GetService(NS_MESSENGEROSINTEGRATION_CONTRACTID, &rv);
// mail.accountmanager.accounts is the main entry point for all accounts
nsXPIDLCString accountList;
rv = getPrefService();
if (NS_SUCCEEDED(rv)) {
rv = m_prefs->CopyCharPref(PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS,
getter_Copies(accountList));
/**
* Check to see if we need to add pre-configured accounts.
* Following prefs are important to note in understanding the procedure here.
*
* 1. pref("mailnews.append_preconfig_accounts.version", version number);
* This pref registers the current version in the user prefs file. A default value
* is stored in mailnews.js file. If a given vendor needs to add more preconfigured
* accounts, the default version number can be increased. Comparing version
* number from user's prefs file and the default one from mailnews.js, we
* can add new accounts and any other version level changes that need to be done.
*
* 2. pref("mail.accountmanager.appendaccounts", <comma separated account list>);
* This pref contains the list of pre-configured accounts that ISP/Vendor wants to
* to add to the existing accounts list.
*/
nsCOMPtr<nsIPrefBranch> defaultsPrefBranch;
rv = m_prefs->GetDefaultBranch(MAILNEWS_ROOT_PREF, getter_AddRefs(defaultsPrefBranch));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr<nsIPrefBranch> prefBranch;
rv = m_prefs->GetBranch(MAILNEWS_ROOT_PREF, getter_AddRefs(prefBranch));
NS_ENSURE_SUCCESS(rv,rv);
PRInt32 appendAccountsCurrentVersion=0;
PRInt32 appendAccountsDefaultVersion=0;
rv = prefBranch->GetIntPref(APPEND_ACCOUNTS_VERSION_PREF_NAME, &appendAccountsCurrentVersion);
NS_ENSURE_SUCCESS(rv,rv);
rv = defaultsPrefBranch->GetIntPref(APPEND_ACCOUNTS_VERSION_PREF_NAME, &appendAccountsDefaultVersion);
NS_ENSURE_SUCCESS(rv,rv);
// Update the account list if needed
if ((appendAccountsCurrentVersion <= appendAccountsDefaultVersion)) {
// Get a list of pre-configured accounts
nsXPIDLCString appendAccountList;
rv = m_prefs->CopyCharPref(PREF_MAIL_ACCOUNTMANAGER_APPEND_ACCOUNTS,
getter_Copies(appendAccountList));
// If there are pre-configured accounts, we need to add them to the existing list.
if (!appendAccountList.IsEmpty()) {
if (!accountList.IsEmpty()) {
nsCStringArray existingAccountsArray;
existingAccountsArray.ParseString(accountList.get(), ACCOUNT_DELIMITER);
// Tokenize the data and add each account if it is not already there
// in the user's current mailnews account list
char *newAccountStr;
char *preConfigAccountsStr = ToNewCString(appendAccountList);
char *token = nsCRT::strtok(preConfigAccountsStr, ACCOUNT_DELIMITER, &newAccountStr);
nsCAutoString newAccount;
while (token) {
if (token && *token) {
newAccount.Assign(token);
newAccount.StripWhitespace();
if (existingAccountsArray.IndexOf(newAccount) == -1) {
accountList += ",";
accountList += newAccount;
}
}
token = nsCRT::strtok(newAccountStr, ACCOUNT_DELIMITER, &newAccountStr);
}
PR_Free(preConfigAccountsStr);
}
else {
accountList = appendAccountList;
}
// Increase the version number so that updates will happen as and when needed
rv = prefBranch->SetIntPref(APPEND_ACCOUNTS_VERSION_PREF_NAME, appendAccountsCurrentVersion + 1);
}
}
}
m_accountsLoaded = PR_TRUE; //It is ok to return null accounts like when we create new profile
m_haveShutdown = PR_FALSE;
if (!accountList || !accountList[0]) {
return NS_OK;
}
/* parse accountList and run loadAccount on each string, comma-separated */
nsCOMPtr<nsIMsgAccount> account;
char *newStr;
char *rest = NS_CONST_CAST(char*,(const char*)accountList);
nsCAutoString str;
char *token = nsCRT::strtok(rest, ",", &newStr);
while (token) {
str = token;
str.StripWhitespace();
if (!str.IsEmpty()) {
rv = GetAccount(str.get(), getter_AddRefs(account));
}
// force load of accounts (need to find a better way to do this
nsCOMPtr<nsISupportsArray> identities;
account->GetIdentities(getter_AddRefs(identities));
nsCOMPtr<nsIMsgIncomingServer> server;
account->GetIncomingServer(getter_AddRefs(server));
token = nsCRT::strtok(newStr, ",", &newStr);
}
/* finished loading accounts */
return NS_OK;
}
PRBool
nsMsgAccountManager::getAccountList(nsISupports *element, void *aData)
{
nsresult rv;
nsCAutoString* accountList = (nsCAutoString*) aData;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString key;
rv = account->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return PR_TRUE;
if ((*accountList).IsEmpty())
(*accountList).Append(key);
else {
(*accountList) += ',';
(*accountList).Append(key);
}
return PR_TRUE;
}
// this routine goes through all the identities and makes sure
// that the special folders for each identity have the
// correct special folder flags set, e.g, the Sent folder has
// the sent flag set.
//
// it also goes through all the spam settings for each account
// and makes sure the folder flags are set there, too
NS_IMETHODIMP
nsMsgAccountManager::SetSpecialFolders()
{
nsresult rv;
nsCOMPtr<nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv);
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr<nsISupportsArray> identities;
GetAllIdentities(getter_AddRefs(identities));
PRUint32 idCount=0;
identities->Count(&idCount);
PRUint32 id;
nsXPIDLCString identityKey;
for (id=0; id<idCount; id++)
{
nsCOMPtr<nsISupports> thisSupports;
rv = identities->GetElementAt(id, getter_AddRefs(thisSupports));
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIMsgIdentity>
thisIdentity = do_QueryInterface(thisSupports, &rv);
if (NS_SUCCEEDED(rv) && thisIdentity)
{
nsXPIDLCString folderUri;
nsCOMPtr<nsIRDFResource> res;
nsCOMPtr<nsIMsgFolder> folder;
thisIdentity->GetFccFolder(getter_Copies(folderUri));
if (folderUri && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
{
folder = do_QueryInterface(res, &rv);
nsCOMPtr <nsIFolder> parent;
if (folder && NS_SUCCEEDED(rv))
{
rv = folder->GetParent(getter_AddRefs(parent));
if (NS_SUCCEEDED(rv) && parent)
rv = folder->SetFlag(MSG_FOLDER_FLAG_SENTMAIL);
}
}
thisIdentity->GetDraftFolder(getter_Copies(folderUri));
if (folderUri && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
{
folder = do_QueryInterface(res, &rv);
if (NS_SUCCEEDED(rv))
rv = folder->SetFlag(MSG_FOLDER_FLAG_DRAFTS);
}
thisIdentity->GetStationeryFolder(getter_Copies(folderUri));
if (folderUri && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
{
folder = do_QueryInterface(res, &rv);
if (folder && NS_SUCCEEDED(rv))
{
nsCOMPtr <nsIFolder> parent;
rv = folder->GetParent(getter_AddRefs(parent));
if (NS_SUCCEEDED(rv) && parent) // only set flag if folder is real
rv = folder->SetFlag(MSG_FOLDER_FLAG_TEMPLATES);
}
}
}
}
// XXX todo
// get all servers
// get all spam settings for each server
// set the JUNK folder flag on the spam folders, right?
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::UnloadAccounts()
{
// release the default account
kDefaultServerAtom = nsnull;
m_defaultAccount=nsnull;
m_incomingServers.Enumerate(hashUnloadServer, this);
m_accounts->Clear(); // will release all elements
m_identities.Reset(hashElementRelease, nsnull);
m_incomingServers.Reset(hashElementRelease, nsnull);
m_accountsLoaded = PR_FALSE;
mAccountKeyList.Truncate(0);
SetLastServerFound(nsnull,"","","");
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::ShutdownServers()
{
m_incomingServers.Enumerate(shutdown, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::CloseCachedConnections()
{
m_incomingServers.Enumerate(closeCachedConnections, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::CleanupOnExit()
{
m_incomingServers.Enumerate(cleanupOnExit, nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::WriteToFolderCache(nsIMsgFolderCache *folderCache)
{
m_incomingServers.Enumerate(writeFolderCache, folderCache);
return folderCache->Close();
}
nsresult
nsMsgAccountManager::createKeyedAccount(const char* key,
nsIMsgAccount ** aAccount)
{
nsCOMPtr<nsIMsgAccount> account;
nsresult rv;
rv = nsComponentManager::CreateInstance(kMsgAccountCID,
nsnull,
NS_GET_IID(nsIMsgAccount),
(void **)getter_AddRefs(account));
if (NS_FAILED(rv)) return rv;
account->SetKey(NS_CONST_CAST(char*,(const char*)key));
// add to internal nsISupportsArray
m_accounts->AppendElement(NS_STATIC_CAST(nsISupports*, account));
// add to string list
if (mAccountKeyList.IsEmpty())
mAccountKeyList = key;
else {
mAccountKeyList += ",";
mAccountKeyList += key;
}
rv = getPrefService();
if (NS_SUCCEEDED(rv))
m_prefs->SetCharPref(PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS,
mAccountKeyList.get());
*aAccount = account;
NS_ADDREF(*aAccount);
return NS_OK;
}
nsresult
nsMsgAccountManager::CreateAccount(nsIMsgAccount **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
nsCAutoString key;
getUniqueAccountKey(ACCOUNT_PREFIX, m_accounts, key);
return createKeyedAccount(key.get(), _retval);
}
nsresult
nsMsgAccountManager::GetAccount(const char* key,
nsIMsgAccount **_retval)
{
if (!_retval) return NS_ERROR_NULL_POINTER;
findAccountByKeyEntry findEntry;
findEntry.key = key;
findEntry.account = nsnull;
m_accounts->EnumerateForwards(findAccountByKey, (void *)&findEntry);
if (findEntry.account) {
*_retval = findEntry.account;
NS_ADDREF(*_retval);
return NS_OK;
}
// not found, create on demand
return createKeyedAccount(key, _retval);
}
nsresult
nsMsgAccountManager::FindServerIndex(nsIMsgIncomingServer* server,
PRInt32* result)
{
NS_ENSURE_ARG_POINTER(server);
nsresult rv;
nsXPIDLCString key;
rv = server->GetKey(getter_Copies(key));
findServerByKeyEntry findEntry;
findEntry.key = key;
findEntry.index = -1;
// do this by account because the account list is in order
m_accounts->EnumerateForwards(findServerIndexByServer, (void *)&findEntry);
// even if the search failed, we can return index.
// this means that all servers not in the array return an index higher
// than all "registered" servers
*result = findEntry.index;
return NS_OK;
}
PRBool
nsMsgAccountManager::findServerIndexByServer(nsISupports *element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element);
findServerByKeyEntry *entry = (findServerByKeyEntry*) aData;
// increment the index;
entry->index++;
nsCOMPtr<nsIMsgIncomingServer> server;
rv = account->GetIncomingServer(getter_AddRefs(server));
if (!server || NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString key;
rv = server->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return PR_TRUE;
// stop when found,
// index will be set to the current index
if (nsCRT::strcmp(key, entry->key)==0)
return PR_FALSE;
return PR_TRUE;
}
PRBool
nsMsgAccountManager::findAccountByKey(nsISupports* element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
findAccountByKeyEntry *entry = (findAccountByKeyEntry*) aData;
nsXPIDLCString key;
account->GetKey(getter_Copies(key));
if (PL_strcmp(key, entry->key)==0) {
entry->account = account;
return PR_FALSE; // stop when found
}
return PR_TRUE;
}
NS_IMETHODIMP nsMsgAccountManager::AddIncomingServerListener(nsIIncomingServerListener *serverListener)
{
m_incomingServerListeners.AppendObject(serverListener);
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::RemoveIncomingServerListener(nsIIncomingServerListener *serverListener)
{
m_incomingServerListeners.RemoveObject(serverListener);
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::NotifyServerLoaded(nsIMsgIncomingServer *server)
{
PRInt32 count = m_incomingServerListeners.Count();
for(PRInt32 i = 0; i < count; i++)
{
nsIIncomingServerListener* listener = m_incomingServerListeners[i];
listener->OnServerLoaded(server);
}
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::NotifyServerUnloaded(nsIMsgIncomingServer *server)
{
PRInt32 count = m_incomingServerListeners.Count();
server->SetFilterList(nsnull); // clear this to cut shutdown leaks. we are always passing valid non-null server here.
for(PRInt32 i = 0; i < count; i++)
{
nsIIncomingServerListener* listener = m_incomingServerListeners[i];
listener->OnServerUnloaded(server);
}
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::NotifyServerChanged(nsIMsgIncomingServer *server)
{
PRInt32 count = m_incomingServerListeners.Count();
for(PRInt32 i = 0; i < count; i++)
{
nsIIncomingServerListener* listener = m_incomingServerListeners[i];
listener->OnServerChanged(server);
}
return NS_OK;
}
nsresult
nsMsgAccountManager::InternalFindServer(const char* username,
const char* hostname,
const char* type,
PRBool useRealSetting,
nsIMsgIncomingServer** aResult)
{
nsresult rv;
nsCOMPtr<nsISupportsArray> servers;
// If 'useRealSetting' is set then we want to scan all existing accounts
// to make sure there's no duplicate including those whose host and/or
// user names have been changed.
if (!useRealSetting &&
(!nsCRT::strcmp((hostname?hostname:""),m_lastFindServerHostName.get())) &&
(!nsCRT::strcmp((username?username:""),m_lastFindServerUserName.get())) &&
(!nsCRT::strcmp((type?type:""),m_lastFindServerType.get())) &&
m_lastFindServerResult)
{
NS_ADDREF(*aResult = m_lastFindServerResult);
return NS_OK;
}
rv = GetAllServers(getter_AddRefs(servers));
if (NS_FAILED(rv)) return rv;
findServerEntry serverInfo;
// "" acts as the wild card.
// hostname might be blank, pass "" instead
serverInfo.hostname = hostname ? hostname : "";
// username might be blank, pass "" instead
serverInfo.username = username ? username : "";
// type might be blank, pass "" instead
serverInfo.type = type ? type : "";
serverInfo.useRealSetting = useRealSetting;
serverInfo.server = *aResult = nsnull;
servers->EnumerateForwards(findServer, (void *)&serverInfo);
if (!serverInfo.server) return NS_ERROR_UNEXPECTED;
// cache for next time
rv = SetLastServerFound(serverInfo.server, hostname, username, type);
NS_ENSURE_SUCCESS(rv,rv);
*aResult = serverInfo.server;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::FindServer(const char* username,
const char* hostname,
const char* type,
nsIMsgIncomingServer** aResult)
{
return(InternalFindServer(username, hostname, type, PR_FALSE, aResult));
}
// Interface called by UI js only (always return true).
NS_IMETHODIMP
nsMsgAccountManager::FindRealServer(const char* username,
const char* hostname,
const char* type,
nsIMsgIncomingServer** aResult)
{
InternalFindServer(username, hostname, type, PR_TRUE, aResult);
return NS_OK;
}
PRBool
nsMsgAccountManager::findAccountByServerKey(nsISupports *element,
void *aData)
{
nsresult rv;
findAccountByKeyEntry *entry = (findAccountByKeyEntry*)aData;
nsCOMPtr<nsIMsgAccount> account =
do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
nsCOMPtr<nsIMsgIncomingServer> server;
rv = account->GetIncomingServer(getter_AddRefs(server));
if (!server || NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString key;
rv = server->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return PR_TRUE;
// if the keys are equal, the servers are equal
if (PL_strcmp(key, entry->key)==0) {
entry->account = account;
return PR_FALSE; // stop on first found account
}
return PR_TRUE;
}
NS_IMETHODIMP
nsMsgAccountManager::FindAccountForServer(nsIMsgIncomingServer *server,
nsIMsgAccount **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (!server) {
(*aResult) = nsnull;
return NS_OK;
}
nsresult rv;
nsXPIDLCString key;
rv = server->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return rv;
findAccountByKeyEntry entry;
entry.key = key;
entry.account = nsnull;
m_accounts->EnumerateForwards(findAccountByServerKey, (void *)&entry);
if (entry.account) {
*aResult = entry.account;
NS_ADDREF(*aResult);
}
return NS_OK;
}
// if the aElement matches the given hostname, add it to the given array
PRBool
nsMsgAccountManager::findServer(nsISupports *aElement, void *data)
{
nsresult rv;
nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(aElement, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
findServerEntry *entry = (findServerEntry*) data;
nsXPIDLCString thisHostname;
if (entry->useRealSetting)
rv = server->GetRealHostName(getter_Copies(thisHostname));
else
rv = server->GetHostName(getter_Copies(thisHostname));
if (NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString thisUsername;
if (entry->useRealSetting)
rv = server->GetRealUsername(getter_Copies(thisUsername));
else
rv = server->GetUsername(getter_Copies(thisUsername));
if (NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString thisType;
rv = server->GetType(getter_Copies(thisType));
if (NS_FAILED(rv)) return PR_TRUE;
// treat "" as a wild card, so if the caller passed in "" for the desired attribute
// treat it as a match
PRBool checkType = PL_strcmp(entry->type, "");
PRBool checkHostname = PL_strcmp(entry->hostname,"");
PRBool checkUsername = PL_strcmp(entry->username,"");
if ((!checkType || (PL_strcmp(entry->type, thisType)==0)) &&
(!checkHostname || (PL_strcasecmp(entry->hostname, thisHostname)==0)) &&
(!checkUsername || (PL_strcmp(entry->username, thisUsername)==0)))
{
entry->server = server;
return PR_FALSE; // stop on first find
}
return PR_TRUE;
}
NS_IMETHODIMP
nsMsgAccountManager::GetFirstIdentityForServer(nsIMsgIncomingServer *aServer, nsIMsgIdentity **aIdentity)
{
NS_ENSURE_ARG_POINTER(aServer);
NS_ENSURE_ARG_POINTER(aIdentity);
nsCOMPtr<nsISupportsArray> identities;
nsresult rv = GetIdentitiesForServer(aServer, getter_AddRefs(identities));
NS_ENSURE_SUCCESS(rv, rv);
// not all servers have identities
// for example, Local Folders
PRUint32 numIdentities;
rv = identities->Count(&numIdentities);
NS_ENSURE_SUCCESS(rv, rv);
if (numIdentities > 0) {
nsCOMPtr<nsIMsgIdentity> identity;
rv = identities->QueryElementAt(0, NS_GET_IID(nsIMsgIdentity),
(void **)getter_AddRefs(identity));
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(*aIdentity = identity);
}
else
*aIdentity = nsnull;
return rv;
}
NS_IMETHODIMP
nsMsgAccountManager::GetIdentitiesForServer(nsIMsgIncomingServer *server,
nsISupportsArray **_retval)
{
NS_ENSURE_ARG_POINTER(server);
NS_ENSURE_ARG_POINTER(_retval);
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> identities;
rv = NS_NewISupportsArray(getter_AddRefs(identities));
if (NS_FAILED(rv)) return rv;
findIdentitiesByServerEntry identityInfo;
identityInfo.server = server;
identityInfo.identities = identities;
m_accounts->EnumerateForwards(findIdentitiesForServer,
(void *)&identityInfo);
// do an addref for the caller.
*_retval = identities;
NS_ADDREF(*_retval);
return NS_OK;
}
PRBool
nsMsgAccountManager::findIdentitiesForServer(nsISupports* element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
findIdentitiesByServerEntry *entry = (findIdentitiesByServerEntry*)aData;
nsCOMPtr<nsIMsgIncomingServer> thisServer;
rv = account->GetIncomingServer(getter_AddRefs(thisServer));
if (NS_FAILED(rv)) return PR_TRUE;
nsXPIDLCString serverKey;
NS_ASSERTION(thisServer, "thisServer is null");
NS_ASSERTION(entry, "entry is null");
NS_ASSERTION(entry->server, "entry->server is null");
// if this happens, bail.
if (!thisServer || !entry || !(entry->server)) return PR_TRUE;
entry->server->GetKey(getter_Copies(serverKey));
nsXPIDLCString thisServerKey;
thisServer->GetKey(getter_Copies(thisServerKey));
if (PL_strcmp(serverKey, thisServerKey)==0) {
// add all these elements to the nsISupports array
nsCOMPtr<nsISupportsArray> theseIdentities;
rv = account->GetIdentities(getter_AddRefs(theseIdentities));
if (NS_SUCCEEDED(rv))
rv = entry->identities->AppendElements(theseIdentities);
}
return PR_TRUE;
}
NS_IMETHODIMP
nsMsgAccountManager::GetServersForIdentity(nsIMsgIdentity *identity,
nsISupportsArray **_retval)
{
nsresult rv;
rv = LoadAccounts();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> servers;
rv = NS_NewISupportsArray(getter_AddRefs(servers));
if (NS_FAILED(rv)) return rv;
findServersByIdentityEntry serverInfo;
serverInfo.identity = identity;
serverInfo.servers = servers;
m_accounts->EnumerateForwards(findServersForIdentity,
(void *)&serverInfo);
// do an addref for the caller.
*_retval = servers;
NS_ADDREF(*_retval);
return NS_OK;
}
PRBool
nsMsgAccountManager::findServersForIdentity(nsISupports *element, void *aData)
{
nsresult rv;
nsCOMPtr<nsIMsgAccount> account = do_QueryInterface(element, &rv);
if (NS_FAILED(rv)) return PR_TRUE;
findServersByIdentityEntry *entry = (findServersByIdentityEntry*)aData;
nsCOMPtr<nsISupportsArray> identities;
account->GetIdentities(getter_AddRefs(identities));
PRUint32 idCount=0;
identities->Count(&idCount);
PRUint32 id;
nsXPIDLCString identityKey;
rv = entry->identity->GetKey(getter_Copies(identityKey));
for (id=0; id<idCount; id++) {
// convert supports->Identity
nsCOMPtr<nsISupports> thisSupports;
rv = identities->GetElementAt(id, getter_AddRefs(thisSupports));
if (NS_FAILED(rv)) continue;
nsCOMPtr<nsIMsgIdentity>
thisIdentity = do_QueryInterface(thisSupports, &rv);
if (NS_SUCCEEDED(rv)) {
nsXPIDLCString thisIdentityKey;
rv = thisIdentity->GetKey(getter_Copies(thisIdentityKey));
if (NS_SUCCEEDED(rv) && PL_strcmp(identityKey, thisIdentityKey) == 0) {
nsCOMPtr<nsIMsgIncomingServer> thisServer;
rv = account->GetIncomingServer(getter_AddRefs(thisServer));
if (thisServer && NS_SUCCEEDED(rv)) {
entry->servers->AppendElement(thisServer);
break;
}
}
}
}
return PR_TRUE;
}
nsresult
nsMsgAccountManager::AddRootFolderListener(nsIFolderListener *aListener)
{
nsresult rv;
NS_ENSURE_TRUE(aListener, NS_OK);
// first add listener to the list
rv = mFolderListeners->AppendElement(aListener);
// now add the listener to all loaded accounts
m_incomingServers.Enumerate(addListener, (void *)aListener);
return NS_OK;
}
nsresult
nsMsgAccountManager::RemoveRootFolderListener(nsIFolderListener *aListener)
{
nsresult rv;
NS_ENSURE_TRUE(aListener, NS_OK);
// remove the listener from the notification list
rv = mFolderListeners->RemoveElement(aListener);
// remove the listener from the individual folders
m_incomingServers.Enumerate(removeListener, (void *)aListener);
return NS_OK;
}
// enumeration functions
PRBool
nsMsgAccountManager::addListener(nsHashKey *aKey, void *element, void *aData)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer *)element;
nsIFolderListener* listener = (nsIFolderListener *)aData;
nsresult rv;
nsCOMPtr<nsIFolder> rootFolder;
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
NS_ENSURE_SUCCESS(rv, PR_TRUE);
rv = rootFolder->AddFolderListener(listener);
NS_ENSURE_SUCCESS(rv, PR_TRUE);
return PR_TRUE;
}
PRBool
nsMsgAccountManager::removeListener(nsHashKey *aKey, void *element, void *aData)
{
nsIMsgIncomingServer *server = (nsIMsgIncomingServer *)element;
nsIFolderListener* listener = (nsIFolderListener *)aData;
nsresult rv;
nsCOMPtr<nsIFolder> rootFolder;
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
NS_ENSURE_SUCCESS(rv, PR_TRUE);
rv = rootFolder->RemoveFolderListener(listener);
NS_ENSURE_SUCCESS(rv, PR_TRUE);
return PR_TRUE;
}
NS_IMETHODIMP nsMsgAccountManager::SetLocalFoldersServer(nsIMsgIncomingServer *aServer)
{
nsresult rv;
if (!aServer) return NS_ERROR_NULL_POINTER;
nsXPIDLCString key;
rv = aServer->GetKey(getter_Copies(key));
if (NS_FAILED(rv)) return rv;
rv = m_prefs->SetCharPref(PREF_MAIL_ACCOUNTMANAGER_LOCALFOLDERSSERVER, (const char *)key);
return rv;
}
NS_IMETHODIMP nsMsgAccountManager::GetLocalFoldersServer(nsIMsgIncomingServer **aServer)
{
nsXPIDLCString serverKey;
nsresult rv;
if (!aServer) return NS_ERROR_NULL_POINTER;
if (!m_prefs) {
rv = getPrefService();
NS_ENSURE_SUCCESS(rv,rv);
}
rv = m_prefs->CopyCharPref(PREF_MAIL_ACCOUNTMANAGER_LOCALFOLDERSSERVER,
getter_Copies(serverKey));
if (NS_SUCCEEDED(rv) && ((const char *)serverKey)) {
rv = GetIncomingServer(serverKey, aServer);
if (!*aServer) return NS_ERROR_FAILURE;
return rv;
}
// try ("nobody","Local Folders","none"), and work down to any "none" server.
rv = FindServer("nobody","Local Folders","none",aServer);
if (NS_FAILED(rv) || !*aServer) {
rv = FindServer("nobody",nsnull,"none",aServer);
if (NS_FAILED(rv) || !*aServer) {
rv = FindServer(nsnull,"Local Folders","none",aServer);
if (NS_FAILED(rv) || !*aServer) {
rv = FindServer(nsnull,nsnull,"none",aServer);
}
}
}
if (NS_FAILED(rv)) return rv;
if (!*aServer) return NS_ERROR_FAILURE;
rv = SetLocalFoldersServer(*aServer);
return rv;
}
// nsIUrlListener methods
NS_IMETHODIMP
nsMsgAccountManager::OnStartRunningUrl(nsIURI * aUrl)
{
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::OnStopRunningUrl(nsIURI * aUrl, nsresult aExitCode)
{
if (aUrl)
{
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(aUrl);
if (imapUrl)
{
nsImapAction imapAction = nsIImapUrl::nsImapTest;
imapUrl->GetImapAction(&imapAction);
switch(imapAction)
{
case nsIImapUrl::nsImapExpungeFolder:
if (m_folderDoingCleanupInbox)
{
PR_CEnterMonitor(m_folderDoingCleanupInbox);
PR_CNotifyAll(m_folderDoingCleanupInbox);
m_cleanupInboxInProgress = PR_FALSE;
PR_CExitMonitor(m_folderDoingCleanupInbox);
m_folderDoingCleanupInbox=nsnull; //reset to nsnull
}
break;
case nsIImapUrl::nsImapDeleteAllMsgs:
if (m_folderDoingEmptyTrash)
{
PR_CEnterMonitor(m_folderDoingEmptyTrash);
PR_CNotifyAll(m_folderDoingEmptyTrash);
m_emptyTrashInProgress = PR_FALSE;
PR_CExitMonitor(m_folderDoingEmptyTrash);
m_folderDoingEmptyTrash = nsnull; //reset to nsnull;
}
break;
default:
break;
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::SetFolderDoingEmptyTrash(nsIMsgFolder *folder)
{
m_folderDoingEmptyTrash = folder;
m_emptyTrashInProgress = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::GetEmptyTrashInProgress(PRBool *bVal)
{
NS_ENSURE_ARG_POINTER(bVal);
*bVal = m_emptyTrashInProgress;
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::SetFolderDoingCleanupInbox(nsIMsgFolder *folder)
{
m_folderDoingCleanupInbox = folder;
m_cleanupInboxInProgress = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::GetCleanupInboxInProgress(PRBool *bVal)
{
NS_ENSURE_ARG_POINTER(bVal);
*bVal = m_cleanupInboxInProgress;
return NS_OK;
}
nsresult
nsMsgAccountManager::SetLastServerFound(nsIMsgIncomingServer *server, const char *hostname, const char *username, const char *type)
{
m_lastFindServerResult = server;
m_lastFindServerHostName = hostname;
m_lastFindServerUserName = username;
m_lastFindServerType = type;
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::SaveAccountInfo()
{
nsresult rv;
rv = getPrefService();
NS_ENSURE_SUCCESS(rv,rv);
return m_prefs->SavePrefFile(nsnull);
}