summaryrefslogtreecommitdiffstats
path: root/mailnews/local/src/nsPop3IncomingServer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/local/src/nsPop3IncomingServer.cpp')
-rw-r--r--mailnews/local/src/nsPop3IncomingServer.cpp744
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;
+}