diff options
Diffstat (limited to 'mailnews/local/src/nsPop3IncomingServer.cpp')
-rw-r--r-- | mailnews/local/src/nsPop3IncomingServer.cpp | 744 |
1 files changed, 744 insertions, 0 deletions
diff --git a/mailnews/local/src/nsPop3IncomingServer.cpp b/mailnews/local/src/nsPop3IncomingServer.cpp new file mode 100644 index 000000000..261d141a4 --- /dev/null +++ b/mailnews/local/src/nsPop3IncomingServer.cpp @@ -0,0 +1,744 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "prmem.h" +#include "plstr.h" +#include "prprf.h" + +#include "nsCOMPtr.h" +#include "nsIStringBundle.h" +#include "nsIPop3IncomingServer.h" +#include "nsPop3IncomingServer.h" +#include "nsIPop3Service.h" +#include "nsMsgBaseCID.h" +#include "nsMsgLocalCID.h" +#include "nsMsgFolderFlags.h" +#include "nsPop3Protocol.h" +#include "nsAutoPtr.h" +#include "nsMsgKeyArray.h" +#include "nsIMsgLocalMailFolder.h" +#include "nsIMsgAccountManager.h" +#include "nsIMsgMailNewsUrl.h" +#include "nsServiceManagerUtils.h" +#include "nsIMutableArray.h" +#include "nsMsgUtils.h" +#include "nsComponentManagerUtils.h" +#include "mozilla/Likely.h" + +static NS_DEFINE_CID(kCPop3ServiceCID, NS_POP3SERVICE_CID); + +class nsPop3GetMailChainer final : public nsIUrlListener +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIURLLISTENER + + nsPop3GetMailChainer(); + nsresult GetNewMailForServers(nsIPop3IncomingServer** servers, uint32_t count, + nsIMsgWindow *msgWindow, + nsIMsgFolder *folderToDownloadTo, nsIUrlListener *listener); + nsresult RunNextGetNewMail(); +protected: + ~nsPop3GetMailChainer(); + nsCOMPtr <nsIMsgFolder> m_folderToDownloadTo; + nsCOMPtr <nsIMsgWindow> m_downloadingMsgWindow; + nsCOMArray<nsIPop3IncomingServer> m_serversToGetNewMailFor; + nsCOMPtr <nsIUrlListener> m_listener; +}; + + + +NS_IMPL_ISUPPORTS_INHERITED(nsPop3IncomingServer, + nsMsgIncomingServer, + nsIPop3IncomingServer, + nsILocalMailIncomingServer) + +nsPop3IncomingServer::nsPop3IncomingServer() +{ + m_capabilityFlags = + POP3_AUTH_MECH_UNDEFINED | + POP3_HAS_AUTH_USER | // should be always there + POP3_GURL_UNDEFINED | + POP3_UIDL_UNDEFINED | + POP3_TOP_UNDEFINED | + POP3_XTND_XLST_UNDEFINED; + + m_canHaveFilters = true; + m_authenticated = false; +} + +nsPop3IncomingServer::~nsPop3IncomingServer() +{ +} + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + LeaveMessagesOnServer, + "leave_on_server") + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + HeadersOnly, + "headers_only") + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + DeleteMailLeftOnServer, + "delete_mail_left_on_server") + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + DotFix, + "dot_fix") + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + DeleteByAgeFromServer, + "delete_by_age_from_server") + +NS_IMPL_SERVERPREF_INT(nsPop3IncomingServer, + NumDaysToLeaveOnServer, + "num_days_to_leave_on_server") + + +NS_IMPL_SERVERPREF_BOOL(nsPop3IncomingServer, + DeferGetNewMail, + "defer_get_new_mail") + +NS_IMETHODIMP nsPop3IncomingServer::GetDeferredToAccount(nsACString& aRetVal) +{ + nsresult rv = GetCharValue("deferred_to_account", aRetVal); + if (aRetVal.IsEmpty()) + return rv; + // We need to repair broken profiles that defer to hidden or invalid servers, + // so find out if the deferred to account has a valid non-hidden server, and + // if not, defer to the local folders inbox. + nsCOMPtr<nsIMsgAccountManager> acctMgr = + do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID); + bool invalidAccount = true; + if (acctMgr) + { + nsCOMPtr<nsIMsgAccount> account; + nsCOMPtr<nsIMsgIncomingServer> server; + rv = acctMgr->GetAccount(aRetVal, getter_AddRefs(account)); + if (account) + { + account->GetIncomingServer(getter_AddRefs(server)); + if (server) + server->GetHidden(&invalidAccount); + } + if (invalidAccount) + { + nsCOMPtr<nsIMsgIncomingServer> localServer; + nsCOMPtr<nsIMsgAccount> localAccount; + + rv = acctMgr->GetLocalFoldersServer(getter_AddRefs(localServer)); + NS_ENSURE_SUCCESS(rv, rv); + // Try to copy any folders that have been stranded in the hidden account + // into the local folders account. + if (server) + { + nsCOMPtr<nsIMsgFolder> hiddenRootFolder; + nsCOMPtr<nsIMsgFolder> localFoldersRoot; + server->GetRootFolder(getter_AddRefs(hiddenRootFolder)); + localServer->GetRootFolder(getter_AddRefs(localFoldersRoot)); + if (hiddenRootFolder && localFoldersRoot) + { + // We're going to iterate over the folders in Local Folders-1, + // though I suspect only the Inbox will have messages. I don't + // think Sent Mail could end up here, but if any folders have + // messages, might as well copy them to the real Local Folders + // account. + nsCOMPtr<nsISimpleEnumerator> enumerator; + rv = hiddenRootFolder->GetSubFolders(getter_AddRefs(enumerator)); + if (NS_SUCCEEDED(rv)) + { + bool hasMore; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && + hasMore) + { + nsCOMPtr<nsISupports> item; + enumerator->GetNext(getter_AddRefs(item)); + nsCOMPtr<nsIMsgFolder> subFolder(do_QueryInterface(item)); + if (subFolder) + { + nsCOMPtr<nsIMsgDatabase> subFolderDB; + subFolder->GetMsgDatabase(getter_AddRefs(subFolderDB)); + if (subFolderDB) + { + // Copy any messages in this sub-folder of the hidden + // account to the corresponding folder in Local Folders. + RefPtr<nsMsgKeyArray> keys = new nsMsgKeyArray; + rv = subFolderDB->ListAllKeys(keys); + nsCOMPtr<nsIMutableArray> hdrsToCopy(do_CreateInstance(NS_ARRAY_CONTRACTID)); + MsgGetHeadersFromKeys(subFolderDB, keys->m_keys, hdrsToCopy); + uint32_t numHdrs = 0; + if (hdrsToCopy) + hdrsToCopy->GetLength(&numHdrs); + if (numHdrs) + { + // Look for a folder with the same name in Local Folders. + nsCOMPtr<nsIMsgFolder> dest; + nsString folderName; + subFolder->GetName(folderName); + localFoldersRoot->GetChildNamed(folderName, + getter_AddRefs(dest)); + if (dest) + dest->CopyMessages(subFolder, hdrsToCopy, false, + nullptr, nullptr, false,false); + // Should we copy the folder if the dest doesn't exist? + } + } + } + } + } + } + } + rv = acctMgr->FindAccountForServer(localServer, getter_AddRefs(localAccount)); + NS_ENSURE_SUCCESS(rv, rv); + if (!localAccount) + return NS_ERROR_NOT_AVAILABLE; + + localAccount->GetKey(aRetVal); + // Can't call SetDeferredToAccount because it calls GetDeferredToAccount. + return SetCharValue("deferred_to_account", aRetVal); + } + } + return rv; +} + +NS_IMETHODIMP nsPop3IncomingServer::SetDeferredToAccount(const nsACString& aAccountKey) +{ + nsCString deferredToAccount; + GetDeferredToAccount(deferredToAccount); + m_rootMsgFolder = nullptr; // clear this so we'll recalculate it on demand. + //Notify listeners who listen to every folder + + nsresult rv = SetCharValue("deferred_to_account", aAccountKey); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIFolderListener> folderListenerManager = + do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + { + + nsCOMPtr<nsIMsgFolder> rootFolder; + // use GetRootFolder, because that returns the real + // root, not the deferred to root. + rv = GetRootFolder(getter_AddRefs(rootFolder)); + if (rootFolder) + { + // if isDeferred state has changed, send notification + if (aAccountKey.IsEmpty() != deferredToAccount.IsEmpty()) + { + nsCOMPtr <nsIAtom> deferAtom = MsgGetAtom("isDeferred"); + nsCOMPtr <nsIAtom> canFileAtom = MsgGetAtom("CanFileMessages"); + folderListenerManager->OnItemBoolPropertyChanged(rootFolder, deferAtom, + !deferredToAccount.IsEmpty(), deferredToAccount.IsEmpty()); + folderListenerManager->OnItemBoolPropertyChanged(rootFolder, canFileAtom, + deferredToAccount.IsEmpty(), !deferredToAccount.IsEmpty()); + + // this hack causes the account manager ds to send notifications to the + // xul content builder that make the changed acct appear or disappear + // from the folder pane and related menus. + nsCOMPtr<nsIMsgAccountManager> acctMgr = + do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID); + if (acctMgr) + { + acctMgr->NotifyServerUnloaded(this); + acctMgr->NotifyServerLoaded(this); + // check if this newly deferred to account is the local folders account + // and needs to have a newly created INBOX. + if (!aAccountKey.IsEmpty()) + { + nsCOMPtr <nsIMsgAccount> account; + acctMgr->GetAccount(aAccountKey, getter_AddRefs(account)); + if (account) + { + nsCOMPtr <nsIMsgIncomingServer> server; + account->GetIncomingServer(getter_AddRefs(server)); + if (server) + { + nsCOMPtr <nsILocalMailIncomingServer> incomingLocalServer = do_QueryInterface(server); + if (incomingLocalServer) + { + nsCOMPtr <nsIMsgFolder> rootFolder; + rv = server->GetRootFolder(getter_AddRefs(rootFolder)); + NS_ENSURE_SUCCESS(rv, rv); + // this will fail if it already exists, which is fine. + rootFolder->CreateSubfolder(NS_LITERAL_STRING("Inbox"), nullptr); + } + } + } + } + } + } + } + } + return rv; +} + +//NS_IMPL_GETSET(nsPop3IncomingServer, Authenticated, bool, m_authenticated); + +NS_IMETHODIMP nsPop3IncomingServer::GetAuthenticated(bool *aAuthenticated) +{ + NS_ENSURE_ARG_POINTER(aAuthenticated); + *aAuthenticated = m_authenticated; + return NS_OK; +} + +NS_IMETHODIMP nsPop3IncomingServer::SetAuthenticated(bool aAuthenticated) +{ + m_authenticated = aAuthenticated; + return NS_OK; +} + +nsresult +nsPop3IncomingServer::GetPop3CapabilityFlags(uint32_t *flags) +{ + *flags = m_capabilityFlags; + return NS_OK; +} + +nsresult +nsPop3IncomingServer::SetPop3CapabilityFlags(uint32_t flags) +{ + m_capabilityFlags = flags; + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::GetRootMsgFolder(nsIMsgFolder **aRootMsgFolder) +{ + NS_ENSURE_ARG_POINTER(aRootMsgFolder); + nsresult rv = NS_OK; + if (!m_rootMsgFolder) + { + nsCString deferredToAccount; + GetDeferredToAccount(deferredToAccount); + if (deferredToAccount.IsEmpty()) + { + rv = CreateRootFolder(); + m_rootMsgFolder = m_rootFolder; + } + else + { + nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + nsCOMPtr <nsIMsgAccount> account; + rv = accountManager->GetAccount(deferredToAccount, getter_AddRefs(account)); + NS_ENSURE_SUCCESS(rv,rv); + if (account) + { + nsCOMPtr <nsIMsgIncomingServer> incomingServer; + rv = account->GetIncomingServer(getter_AddRefs(incomingServer)); + NS_ENSURE_SUCCESS(rv,rv); + // make sure we're not deferred to ourself... + if (incomingServer && incomingServer != this) + rv = incomingServer->GetRootMsgFolder(getter_AddRefs(m_rootMsgFolder)); + else + rv = NS_ERROR_FAILURE; + } + } + } + + NS_IF_ADDREF(*aRootMsgFolder = m_rootMsgFolder); + return m_rootMsgFolder ? rv : NS_ERROR_FAILURE; +} + +nsresult nsPop3IncomingServer::GetInbox(nsIMsgWindow *msgWindow, nsIMsgFolder **inbox) +{ + NS_ENSURE_ARG_POINTER(inbox); + nsCOMPtr<nsIMsgFolder> rootFolder; + nsresult rv = GetRootMsgFolder(getter_AddRefs(rootFolder)); + if(NS_SUCCEEDED(rv) && rootFolder) + { + rootFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, inbox); + } + + nsCOMPtr<nsIMsgLocalMailFolder> localInbox = do_QueryInterface(*inbox, &rv); + if (NS_SUCCEEDED(rv) && localInbox) + { + nsCOMPtr <nsIMsgDatabase> db; + rv = (*inbox)->GetMsgDatabase(getter_AddRefs(db)); + if (NS_FAILED(rv)) + { + (*inbox)->SetMsgDatabase(nullptr); + (void) localInbox->SetCheckForNewMessagesAfterParsing(true); + // this will cause a reparse of the mail folder. + localInbox->GetDatabaseWithReparse(nullptr, msgWindow, getter_AddRefs(db)); + rv = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE; + } + } + return rv; +} + +NS_IMETHODIMP nsPop3IncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow) +{ + nsresult rv; + nsCOMPtr<nsIPop3Service> pop3Service(do_GetService(kCPop3ServiceCID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIMsgFolder> inbox; + nsCOMPtr<nsIMsgFolder> rootMsgFolder; + nsCOMPtr<nsIUrlListener> urlListener; + rv = GetRootMsgFolder(getter_AddRefs(rootMsgFolder)); + NS_ENSURE_TRUE(rootMsgFolder, NS_ERROR_FAILURE); + + rootMsgFolder->GetFolderWithFlags(nsMsgFolderFlags::Inbox, + getter_AddRefs(inbox)); + if (!inbox) + return NS_ERROR_FAILURE; + + nsCOMPtr <nsIMsgIncomingServer> server; + inbox->GetServer(getter_AddRefs(server)); + + server->SetPerformingBiff(true); + + urlListener = do_QueryInterface(inbox); + + bool downloadOnBiff = false; + rv = GetDownloadOnBiff(&downloadOnBiff); + if (downloadOnBiff) + { + nsCOMPtr <nsIMsgLocalMailFolder> localInbox = do_QueryInterface(inbox, &rv); + if (localInbox && NS_SUCCEEDED(rv)) + { + bool valid = false; + nsCOMPtr <nsIMsgDatabase> db; + rv = inbox->GetMsgDatabase(getter_AddRefs(db)); + if (NS_SUCCEEDED(rv) && db) + rv = db->GetSummaryValid(&valid); + if (NS_SUCCEEDED(rv) && valid) + rv = pop3Service->GetNewMail(aMsgWindow, urlListener, inbox, this, nullptr); + else + { + bool isLocked; + inbox->GetLocked(&isLocked); + if (!isLocked) + rv = localInbox->GetDatabaseWithReparse(urlListener, aMsgWindow, getter_AddRefs(db)); + if (NS_SUCCEEDED(rv)) + rv = localInbox->SetCheckForNewMessagesAfterParsing(true); + } + } + } + else + rv = pop3Service->CheckForNewMail(aMsgWindow, urlListener, inbox, this, nullptr); + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::SetFlagsOnDefaultMailboxes() +{ + nsCOMPtr<nsIMsgFolder> rootFolder; + nsresult rv = GetRootFolder(getter_AddRefs(rootFolder)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(rootFolder, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // pop3 gets an inbox, but no queue (unsent messages) + localFolder->SetFlagsOnDefaultMailboxes(nsMsgFolderFlags::SpecialUse & + ~nsMsgFolderFlags::Queue); + return NS_OK; +} + + +NS_IMETHODIMP nsPop3IncomingServer::CreateDefaultMailboxes() +{ + nsresult rv = CreateLocalFolder(NS_LITERAL_STRING("Inbox")); + NS_ENSURE_SUCCESS(rv, rv); + + return CreateLocalFolder(NS_LITERAL_STRING("Trash")); +} + +// override this so we can say that deferred accounts can't have messages +// filed to them, which will remove them as targets of all the move/copy +// menu items. +NS_IMETHODIMP +nsPop3IncomingServer::GetCanFileMessagesOnServer(bool *aCanFileMessagesOnServer) +{ + NS_ENSURE_ARG_POINTER(aCanFileMessagesOnServer); + + nsCString deferredToAccount; + GetDeferredToAccount(deferredToAccount); + *aCanFileMessagesOnServer = deferredToAccount.IsEmpty(); + return NS_OK; +} + + +NS_IMETHODIMP +nsPop3IncomingServer::GetCanCreateFoldersOnServer(bool *aCanCreateFoldersOnServer) +{ + NS_ENSURE_ARG_POINTER(aCanCreateFoldersOnServer); + + nsCString deferredToAccount; + GetDeferredToAccount(deferredToAccount); + *aCanCreateFoldersOnServer = deferredToAccount.IsEmpty(); + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::VerifyLogon(nsIUrlListener *aUrlListener, + nsIMsgWindow *aMsgWindow, nsIURI **aURL) +{ + nsresult rv; + nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + return pop3Service->VerifyLogon(this, aUrlListener, aMsgWindow, aURL); +} + +NS_IMETHODIMP nsPop3IncomingServer::DownloadMailFromServers(nsIPop3IncomingServer** aServers, + uint32_t aCount, + nsIMsgWindow *aMsgWindow, + nsIMsgFolder *aFolder, + nsIUrlListener *aUrlListener) +{ + nsPop3GetMailChainer *getMailChainer = new nsPop3GetMailChainer; + NS_ENSURE_TRUE(getMailChainer, NS_ERROR_OUT_OF_MEMORY); + getMailChainer->AddRef(); // this object owns itself and releases when done. + return getMailChainer->GetNewMailForServers(aServers, aCount, aMsgWindow, aFolder, aUrlListener); +} + +NS_IMETHODIMP nsPop3IncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow, + nsIUrlListener *aUrlListener, + nsIMsgFolder *aInbox, + nsIURI **aResult) +{ + nsresult rv; + nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + return pop3Service->GetNewMail(aMsgWindow, aUrlListener, aInbox, this, aResult); +} + +// user has clicked get new messages on this server. If other servers defer to this server, +// we need to get new mail for them. But if this server defers to an other server, +// I think we only get new mail for this server. +NS_IMETHODIMP +nsPop3IncomingServer::GetNewMessages(nsIMsgFolder *aFolder, nsIMsgWindow *aMsgWindow, + nsIUrlListener *aUrlListener) +{ + nsresult rv; + + nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + + nsCOMPtr <nsIMsgFolder> inbox; + rv = GetInbox(aMsgWindow, getter_AddRefs(inbox)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr <nsIURI> url; + nsCOMPtr <nsIMsgIncomingServer> server; + nsCOMArray<nsIPop3IncomingServer> deferredServers; + nsCString deferredToAccount; + GetDeferredToAccount(deferredToAccount); + + if (deferredToAccount.IsEmpty()) + { + aFolder->GetServer(getter_AddRefs(server)); + GetDeferredServers(server, deferredServers); + } + if (deferredToAccount.IsEmpty() && !deferredServers.IsEmpty()) + { + nsPop3GetMailChainer *getMailChainer = new nsPop3GetMailChainer; + NS_ENSURE_TRUE(getMailChainer, NS_ERROR_OUT_OF_MEMORY); + getMailChainer->AddRef(); // this object owns itself and releases when done. + deferredServers.InsertElementAt(0, this); + return getMailChainer->GetNewMailForServers(deferredServers.Elements(), + deferredServers.Length(), aMsgWindow, inbox, aUrlListener); + } + if (m_runningProtocol) + return NS_MSG_FOLDER_BUSY; + + return pop3Service->GetNewMail(aMsgWindow, aUrlListener, inbox, this, getter_AddRefs(url)); +} + +NS_IMETHODIMP +nsPop3IncomingServer::GetDownloadMessagesAtStartup(bool *getMessagesAtStartup) +{ + NS_ENSURE_ARG_POINTER(getMessagesAtStartup); + // GetMessages is not automatically done for pop servers at startup. + // We need to trigger that action. Return true. + *getMessagesAtStartup = true; + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::GetCanBeDefaultServer(bool *canBeDefaultServer) +{ + NS_ENSURE_ARG_POINTER(canBeDefaultServer); + *canBeDefaultServer = true; + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::GetCanSearchMessages(bool *canSearchMessages) +{ + // this will return false if this server is deferred, which is what we want. + return GetCanFileMessagesOnServer(canSearchMessages); +} + +NS_IMETHODIMP +nsPop3IncomingServer::CloseCachedConnections() +{ + nsCOMPtr<nsIRequest> channel = do_QueryInterface(m_runningProtocol); + if (channel) + channel->Cancel(NS_ERROR_ABORT); + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::GetOfflineSupportLevel(int32_t *aSupportLevel) +{ + NS_ENSURE_ARG_POINTER(aSupportLevel); + + nsresult rv; + rv = GetIntValue("offline_support_level", aSupportLevel); + if (*aSupportLevel != OFFLINE_SUPPORT_LEVEL_UNDEFINED) return rv; + + // set default value + *aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE; + return NS_OK; +} + +NS_IMETHODIMP +nsPop3IncomingServer::SetRunningProtocol(nsIPop3Protocol *aProtocol) +{ + NS_ASSERTION(!aProtocol || !m_runningProtocol, "overriding running protocol"); + m_runningProtocol = aProtocol; + return NS_OK; +} + +NS_IMETHODIMP nsPop3IncomingServer::GetRunningProtocol(nsIPop3Protocol **aProtocol) +{ + NS_ENSURE_ARG_POINTER(aProtocol); + NS_IF_ADDREF(*aProtocol = m_runningProtocol); + return NS_OK; +} + +NS_IMETHODIMP nsPop3IncomingServer::AddUidlToMark(const char *aUidl, int32_t aMark) +{ + NS_ENSURE_ARG_POINTER(aUidl); + + Pop3UidlEntry *uidlEntry = PR_NEWZAP(Pop3UidlEntry); + NS_ENSURE_TRUE(uidlEntry, NS_ERROR_OUT_OF_MEMORY); + + uidlEntry->uidl = strdup(aUidl); + if (MOZ_UNLIKELY(!uidlEntry->uidl)) { + PR_Free(uidlEntry); + return NS_ERROR_OUT_OF_MEMORY; + } + + uidlEntry->status = (aMark == POP3_DELETE) ? DELETE_CHAR : + (aMark == POP3_FETCH_BODY) ? FETCH_BODY : KEEP; + m_uidlsToMark.AppendElement(uidlEntry); + return NS_OK; +} + +NS_IMETHODIMP nsPop3IncomingServer::MarkMessages() +{ + nsresult rv; + if (m_runningProtocol) + rv = m_runningProtocol->MarkMessages(&m_uidlsToMark); + else + { + nsCString hostName; + nsCString userName; + nsCOMPtr<nsIFile> localPath; + + GetLocalPath(getter_AddRefs(localPath)); + + GetHostName(hostName); + GetUsername(userName); + // do it all in one fell swoop + rv = nsPop3Protocol::MarkMsgForHost(hostName.get(), userName.get(), localPath, m_uidlsToMark); + } + uint32_t count = m_uidlsToMark.Length(); + for (uint32_t i = 0; i < count; i++) + { + Pop3UidlEntry *ue = m_uidlsToMark[i]; + PR_Free(ue->uidl); + PR_Free(ue); + } + m_uidlsToMark.Clear(); + return rv; +} + +NS_IMPL_ISUPPORTS(nsPop3GetMailChainer, nsIUrlListener) + +nsPop3GetMailChainer::nsPop3GetMailChainer() +{ +} +nsPop3GetMailChainer::~nsPop3GetMailChainer() +{ +} + +nsresult nsPop3GetMailChainer::GetNewMailForServers(nsIPop3IncomingServer** servers, + uint32_t count, nsIMsgWindow *msgWindow, + nsIMsgFolder *folderToDownloadTo, nsIUrlListener *listener) +{ + NS_ENSURE_ARG_POINTER(folderToDownloadTo); + + m_serversToGetNewMailFor.AppendElements(servers, count); + m_folderToDownloadTo = folderToDownloadTo; + m_downloadingMsgWindow = msgWindow; + m_listener = listener; + nsCOMPtr <nsIMsgDatabase> destFolderDB; + + nsresult rv = folderToDownloadTo->GetMsgDatabase(getter_AddRefs(destFolderDB)); + if (NS_FAILED(rv) || !destFolderDB) + { + nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(folderToDownloadTo); + if (localFolder) + { + localFolder->GetDatabaseWithReparse(this, msgWindow, getter_AddRefs(destFolderDB)); + return NS_OK; + } + } + return RunNextGetNewMail(); +} + +NS_IMETHODIMP +nsPop3GetMailChainer::OnStartRunningUrl(nsIURI *url) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsPop3GetMailChainer::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode) +{ + return RunNextGetNewMail(); +} + +nsresult nsPop3GetMailChainer::RunNextGetNewMail() +{ + nsresult rv; + uint32_t numServersLeft = m_serversToGetNewMailFor.Count(); + + for (; numServersLeft > 0;) + { + nsCOMPtr<nsIPop3IncomingServer> popServer(m_serversToGetNewMailFor[0]); + m_serversToGetNewMailFor.RemoveObjectAt(0); + numServersLeft--; + if (popServer) + { + bool deferGetNewMail = false; + nsCOMPtr <nsIMsgIncomingServer> downloadingToServer; + m_folderToDownloadTo->GetServer(getter_AddRefs(downloadingToServer)); + popServer->GetDeferGetNewMail(&deferGetNewMail); + nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(popServer); + nsCOMPtr<nsIPop3Protocol> protocol; + popServer->GetRunningProtocol(getter_AddRefs(protocol)); + if ((deferGetNewMail || downloadingToServer == server) && !protocol) + { + // have to call routine that just gets mail for one server, + // and ignores deferred servers... + if (server) + { + nsCOMPtr <nsIURI> url; + nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + return pop3Service->GetNewMail(m_downloadingMsgWindow, this, m_folderToDownloadTo, popServer, getter_AddRefs(url)); + } + } + } + } + rv = m_listener ? m_listener->OnStopRunningUrl(nullptr, NS_OK) : NS_OK; + Release(); // release ref to ourself. + return rv; +} |