summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/imap/src/nsImapProtocol.h
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/imap/src/nsImapProtocol.h')
-rw-r--r--comm/mailnews/imap/src/nsImapProtocol.h848
1 files changed, 848 insertions, 0 deletions
diff --git a/comm/mailnews/imap/src/nsImapProtocol.h b/comm/mailnews/imap/src/nsImapProtocol.h
new file mode 100644
index 0000000000..815ac103dc
--- /dev/null
+++ b/comm/mailnews/imap/src/nsImapProtocol.h
@@ -0,0 +1,848 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsImapProtocol_h___
+#define nsImapProtocol_h___
+
+#include "mozilla/Attributes.h"
+#include "nsIImapProtocol.h"
+#include "nsIImapUrl.h"
+
+#include "nsMsgProtocol.h"
+#include "nsIStreamListener.h"
+#include "nsIAsyncOutputStream.h"
+#include "nsIAsyncInputStream.h"
+#include "nsImapCore.h"
+#include "nsString.h"
+#include "nsIProgressEventSink.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsISocketTransport.h"
+
+// UI Thread proxy helper
+#include "nsIImapProtocolSink.h"
+
+#include "../public/nsIImapHostSessionList.h"
+#include "nsImapServerResponseParser.h"
+#include "nsImapFlagAndUidState.h"
+#include "nsImapNamespace.h"
+#include "nsTArray.h"
+#include "nsIWeakReferenceUtils.h"
+#include "nsMsgLineBuffer.h" // we need this to use the nsMsgLineStreamBuffer helper class...
+#include "nsIInputStream.h"
+#include "nsIMsgIncomingServer.h"
+#include "nsCOMArray.h"
+#include "nsIThread.h"
+#include "nsIRunnable.h"
+#include "nsIImapMockChannel.h"
+#include "nsILoadGroup.h"
+#include "nsCOMPtr.h"
+#include "nsIMsgWindow.h"
+#include "nsIImapHeaderXferInfo.h"
+#include "nsMsgLineBuffer.h"
+#include "nsIAsyncInputStream.h"
+#include "nsIMsgFolder.h"
+#include "nsIMsgAsyncPrompter.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "nsSyncRunnableHelpers.h"
+#include "nsICacheEntryOpenCallback.h"
+#include "nsIProtocolProxyCallback.h"
+#include "nsIStringBundle.h"
+#include "nsHashPropertyBag.h"
+#include "nsMailChannel.h"
+
+#include "mozilla/Monitor.h"
+
+class nsIMAPMessagePartID;
+class nsIPrefBranch;
+
+#define kDownLoadCacheSize 16000u // was 1536 - try making it bigger
+
+typedef struct _msg_line_info {
+ const char* adoptedMessageLine;
+ uint32_t uidOfMessage;
+} msg_line_info;
+
+class nsMsgImapLineDownloadCache : public nsIImapHeaderInfo,
+ public nsByteArray {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIIMAPHEADERINFO
+ nsMsgImapLineDownloadCache();
+ uint32_t CurrentUID();
+ uint32_t SpaceAvailable();
+ bool CacheEmpty();
+
+ msg_line_info* GetCurrentLineInfo();
+
+ private:
+ virtual ~nsMsgImapLineDownloadCache();
+
+ msg_line_info* fLineInfo;
+ int32_t m_msgSize;
+};
+
+#define kNumHdrsToXfer 10
+
+class nsMsgImapHdrXferInfo : public nsIImapHeaderXferInfo {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIIMAPHEADERXFERINFO
+ nsMsgImapHdrXferInfo();
+ void ResetAll(); // reset HeaderInfos for re-use
+ void ReleaseAll(); // release HeaderInfos (frees up memory)
+ // this will return null if we're full, in which case the client code
+ // should transfer the headers and retry.
+ nsIImapHeaderInfo* StartNewHdr();
+ // call when we've finished adding lines to current hdr
+ void FinishCurrentHdr();
+
+ private:
+ virtual ~nsMsgImapHdrXferInfo();
+ nsCOMArray<nsIImapHeaderInfo> m_hdrInfos;
+ int32_t m_nextFreeHdrInfo;
+};
+
+// This class contains the name of a mailbox and whether or not
+// its children have been listed.
+class nsIMAPMailboxInfo {
+ public:
+ nsIMAPMailboxInfo(const nsACString& aName, char aDelimiter);
+ virtual ~nsIMAPMailboxInfo();
+
+ void SetChildrenListed(bool childrenListed);
+ bool GetChildrenListed();
+ const nsACString& GetMailboxName();
+ char GetDelimiter();
+
+ protected:
+ nsCString mMailboxName;
+ bool mChildrenListed;
+ char mDelimiter;
+};
+
+// State Flags (Note, I use the word state in terms of storing
+// state information about the connection (authentication, have we sent
+// commands, etc. I do not intend it to refer to protocol state)
+// Use these flags in conjunction with SetFlag/TestFlag/ClearFlag instead
+// of creating PRBools for everything....
+// clang-format off
+#define IMAP_RECEIVED_GREETING 0x00000001 // should we pause for the next read
+#define IMAP_CONNECTION_IS_OPEN 0x00000004 // is the connection currently open?
+#define IMAP_WAITING_FOR_DATA 0x00000008
+#define IMAP_CLEAN_UP_URL_STATE 0x00000010 // processing clean up url state
+#define IMAP_ISSUED_LANGUAGE_REQUEST 0x00000020 // make sure we only issue the language
+ // request once per connection...
+#define IMAP_ISSUED_COMPRESS_REQUEST 0x00000040 // make sure we only request compression once
+
+// There are 3 types of progress strings for items downloaded from IMAP servers.
+// An index is needed to keep track of the current count of the number of each
+// item type downloaded. The IMAP_EMPTY_STRING_INDEX means no string displayed.
+#define IMAP_NUMBER_OF_PROGRESS_STRINGS 4
+#define IMAP_HEADERS_STRING_INDEX 0
+#define IMAP_FLAGS_STRING_INDEX 1
+#define IMAP_MESSAGES_STRING_INDEX 2
+#define IMAP_EMPTY_STRING_INDEX 3
+// clang-format on
+
+/**
+ * nsImapProtocol is, among other things, the underlying nsIChannel
+ * implementation for the IMAP protocol. However, it's usually hidden away
+ * behind nsImapMockChannel objects. It also represents the 'real' connection
+ * to the IMAP server - it maintains the nsISocketTransport.
+ * Because there can be multiple IMAP requests queued up, NS_NewChannel()
+ * will return nsImapMockChannel objects instead, to keep the request in a
+ * holding pattern until the connection is free. At which time the mock
+ * channel will just forward calls onward to the nsImapProtocol.
+ *
+ * The url scheme we implement here encodes various IMAP commands as URLs.
+ * Some URLs are just traditional I/O based nsIChannel transactions, but
+ * many others have side effects. For example, an IMAP folder discovery
+ * command might cause the creation of the nsImapMailFolder hierarchy under
+ * the the nsImapIncomingServer.
+ * Such side effects are communicated via the various "Sink" interfaces. This
+ * helps decouple the IMAP code from the rest of the system:
+ *
+ * - nsIImapServerSink (implemented by nsImapIncomingServer)
+ * - nsIImapMailFolderSink (implemented by nsImapMailFolder)
+ * - nsIImapMessageSink (implemented by nsImapMailFolder)
+ *
+ * Internal to nsImapProtocol, these sink classes all have corresponding proxy
+ * implementations (ImapServerSinkProxy, ImapMailFolderSinkProxy and
+ * ImapMessageSinkProxy). These allow us to safely call the sink objects, in
+ * a synchronous fashion, from I/O threads (threads other than the main one).
+ * When an IMAP routine calls a member function of one of these sink proxies,
+ * it dispatches a call to the real sink object on the main thread, then
+ * blocks until the call is completed.
+ */
+class nsImapProtocol : public nsIImapProtocol,
+ public nsIInputStreamCallback,
+ public nsSupportsWeakReference,
+ public nsMsgProtocol,
+ public nsIImapProtocolSink,
+ public nsIMsgAsyncPromptListener,
+ public nsIProtocolProxyCallback {
+ public:
+ struct TCPKeepalive {
+ // For enabling and setting TCP keepalive (not related to IMAP IDLE).
+ std::atomic<bool> enabled;
+ std::atomic<int32_t> idleTimeS;
+ std::atomic<int32_t> retryIntervalS;
+ };
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIINPUTSTREAMCALLBACK
+ NS_DECL_NSIPROTOCOLPROXYCALLBACK
+ nsImapProtocol();
+
+ virtual nsresult ProcessProtocolState(nsIURI* url,
+ nsIInputStream* inputStream,
+ uint64_t sourceOffset,
+ uint32_t length) override;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // we support the nsIImapProtocol interface
+ //////////////////////////////////////////////////////////////////////////////////
+ NS_DECL_NSIIMAPPROTOCOL
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // we support the nsIImapProtocolSink interface
+ //////////////////////////////////////////////////////////////////////////////////
+ NS_DECL_NSIIMAPPROTOCOLSINK
+
+ NS_DECL_NSIMSGASYNCPROMPTLISTENER
+
+ // message id string utilities.
+ uint32_t CountMessagesInIdString(const char* idString);
+ static bool HandlingMultipleMessages(const nsCString& messageIdString);
+ // escape slashes and double quotes in username/passwords for insecure login.
+ static void EscapeUserNamePasswordString(const char* strToEscape,
+ nsCString* resultStr);
+
+ // used to start fetching a message.
+ void GetShouldDownloadAllHeaders(bool* aResult);
+ void GetArbitraryHeadersToDownload(nsCString& aResult);
+ virtual void AdjustChunkSize();
+ virtual void FetchMessage(const nsCString& messageIds,
+ nsIMAPeFetchFields whatToFetch,
+ const char* fetchModifier = nullptr,
+ uint32_t startByte = 0, uint32_t numBytes = 0,
+ char* part = 0);
+ void FetchTryChunking(const nsCString& messageIds,
+ nsIMAPeFetchFields whatToFetch, bool idIsUid,
+ char* part, uint32_t downloadSize, bool tryChunking);
+ void FallbackToFetchWholeMsg(const nsCString& messageId,
+ uint32_t messageSize);
+ // used when streaming a message fetch
+ virtual nsresult BeginMessageDownLoad(
+ uint32_t totalSize, // for user, headers and body
+ const char* contentType); // some downloads are header only
+ virtual void HandleMessageDownLoadLine(const char* line, bool isPartialLine,
+ char* lineCopy = nullptr);
+ virtual void NormalMessageEndDownload();
+ virtual void AbortMessageDownLoad();
+ virtual void PostLineDownLoadEvent(const char* line, uint32_t uid);
+ void FlushDownloadCache();
+
+ virtual void SetMailboxDiscoveryStatus(EMailboxDiscoverStatus status);
+ virtual EMailboxDiscoverStatus GetMailboxDiscoveryStatus();
+
+ virtual void ProcessMailboxUpdate(bool handlePossibleUndo);
+ // Send log output...
+ void Log(const char* logSubName, const char* extraInfo, const char* logData);
+ static void LogImapUrl(const char* logMsg, nsIImapUrl* imapUrl);
+ // Comment from 4.5: We really need to break out the thread synchronizer from
+ // the connection class...Not sure what this means
+ bool GetPseudoInterrupted();
+
+ uint32_t GetMessageSize(const nsACString& messageId);
+ bool GetSubscribingNow();
+
+ bool DeathSignalReceived();
+ void ResetProgressInfo();
+ void SetActive(bool active);
+ bool GetActive();
+
+ bool GetShowAttachmentsInline();
+
+ // Sets whether or not the content referenced by the current ActiveEntry has
+ // been modified. Used for MIME parts on demand.
+ void SetContentModified(IMAP_ContentModifiedType modified);
+ bool GetShouldFetchAllParts();
+ bool GetIgnoreExpunges() { return m_ignoreExpunges; }
+ // Generic accessors required by the imap parser
+ char* CreateNewLineFromSocket();
+ nsresult GetConnectionStatus();
+ void SetConnectionStatus(nsresult status);
+
+ // Cleanup the connection and shutdown the thread.
+ void TellThreadToDie();
+
+ const nsCString&
+ GetImapHostName(); // return the host name from the url for the
+ // current connection
+ const nsCString& GetImapUserName(); // return the user name from the identity
+ const char*
+ GetImapServerKey(); // return the user name from the incoming server;
+
+ // state set by the imap parser...
+ void NotifyMessageFlags(imapMessageFlagsType flags,
+ const nsACString& keywords, nsMsgKey key,
+ uint64_t highestModSeq);
+ void NotifySearchHit(const char* hitLine);
+
+ // Event handlers for the imap parser.
+ void DiscoverMailboxSpec(nsImapMailboxSpec* adoptedBoxSpec);
+ void AlertUserEventUsingName(const char* aMessageId);
+ void AlertUserEvent(const char* message);
+ void AlertUserEventFromServer(const char* aServerEvent,
+ bool aForIdle = false);
+
+ void ProgressEventFunctionUsingName(const char* aMsgId);
+ void ProgressEventFunctionUsingNameWithString(const char* aMsgName,
+ const char* aExtraInfo);
+ void PercentProgressUpdateEvent(nsACString const& fmtStringName,
+ nsAString const& mailbox,
+ int64_t currentProgress, int64_t maxProgress);
+ void ShowProgress();
+
+ // utility function calls made by the server
+
+ void Copy(const char* messageList, const char* destinationMailbox,
+ bool idsAreUid);
+ void Search(const char* searchCriteria, bool useUID, bool notifyHit = true);
+ // imap commands issued by the parser
+ void Store(const nsCString& aMessageList, const char* aMessageData,
+ bool aIdsAreUid);
+ void ProcessStoreFlags(const nsCString& messageIds, bool idsAreUids,
+ imapMessageFlagsType flags, bool addFlags);
+ void IssueUserDefinedMsgCommand(const char* command, const char* messageList);
+ void FetchMsgAttribute(const nsCString& messageIds,
+ const nsCString& attribute);
+ void Expunge();
+ void UidExpunge(const nsCString& messageSet);
+ void ImapClose(bool shuttingDown = false, bool waitForResponse = true);
+ void Check();
+ void SelectMailbox(const char* mailboxName);
+ // more imap commands
+ void Logout(bool shuttingDown = false, bool waitForResponse = true);
+ void Noop();
+ void XServerInfo();
+ void Netscape();
+ void XMailboxInfo(const char* mailboxName);
+ void XAOL_Option(const char* option);
+ void MailboxData();
+ void GetMyRightsForFolder(const char* mailboxName);
+ void Bodystructure(const nsCString& messageId, bool idIsUid);
+
+ // this function does not ref count!!! be careful!!!
+ nsIImapUrl* GetCurrentUrl() { return m_runningUrl; }
+
+ // acl and namespace stuff
+ // notifies libmsg that we have a new personal/default namespace that we're
+ // using
+ void CommitNamespacesForHostEvent();
+ // notifies libmsg that we have new capability data for the current host
+ void CommitCapability();
+
+ // Adds a set of rights for a given user on a given mailbox on the current
+ // host. if userName is NULL, it means "me," or MYRIGHTS. rights is a single
+ // string of rights, as specified by RFC2086, the IMAP ACL extension.
+ void AddFolderRightsForUser(const char* mailboxName, const char* userName,
+ const char* rights);
+ // Clears all rights for the current folder, for all users.
+ void ClearAllFolderRights();
+ void RefreshFolderACLView(const char* mailboxName,
+ nsImapNamespace* nsForMailbox);
+
+ nsresult SetFolderAdminUrl(const char* mailboxName);
+ void HandleMemoryFailure();
+ void HandleCurrentUrlError();
+
+ // UIDPLUS extension
+ void SetCopyResponseUid(const char* msgIdString);
+
+ // Quota support
+ void UpdateFolderQuotaData(nsImapQuotaAction aAction, nsCString& aQuotaRoot,
+ uint64_t aUsed, uint64_t aMax);
+
+ bool GetPreferPlainText() { return m_preferPlainText; }
+
+ int32_t GetCurFetchSize() { return m_curFetchSize; }
+
+ const nsString& GetEmptyMimePartString() { return m_emptyMimePartString; }
+ void SetCapabilityResponseOccurred();
+
+ // Start event loop. This is called on IMAP thread
+ bool RunImapThreadMainLoop();
+
+ private:
+ virtual ~nsImapProtocol();
+ // the following flag is used to determine when a url is currently being run.
+ // It is cleared when we finish processng a url and it is set whenever we call
+ // Load on a url
+ bool m_urlInProgress;
+
+ /** The nsIImapURL that is currently running. */
+ nsCOMPtr<nsIImapUrl> m_runningUrl;
+ nsCOMPtr<nsIImapUrl> m_runningUrlLatest;
+ /** Current imap action associated with this connection. */
+ nsImapAction m_imapAction;
+
+ nsCString m_hostName;
+ nsCString m_userName;
+ nsCString m_serverKey;
+ char* m_dataOutputBuf;
+ RefPtr<nsMsgLineStreamBuffer> m_inputStreamBuffer;
+ nsCString m_trashFolderPath;
+
+ /** The socket connection to the IMAP server. */
+ nsCOMPtr<nsISocketTransport> m_transport;
+ nsCOMPtr<nsITransportSecurityInfo> m_securityInfo;
+
+ /** Stream to handle data coming in from the IMAP server. */
+ nsCOMPtr<nsIInputStream> m_inputStream;
+
+ nsCOMPtr<nsIAsyncInputStream> m_channelInputStream;
+ nsCOMPtr<nsIAsyncOutputStream> m_channelOutputStream;
+
+ /** The currently running request. */
+ nsCOMPtr<nsIImapMockChannel> m_mockChannel;
+
+ uint32_t m_bytesToChannel;
+ bool m_fetchingWholeMessage;
+ // nsCOMPtr<nsIRequest> mAsyncReadRequest; // we're going to cancel this when
+ // we're done with the conn.
+
+ // ******* Thread support *******
+ PRThread* m_thread;
+ mozilla::ReentrantMonitor
+ m_dataAvailableMonitor; // used to notify the arrival of data from the
+ // server
+ mozilla::ReentrantMonitor
+ m_urlReadyToRunMonitor; // used to notify the arrival of a new url to be
+ // processed
+ mozilla::ReentrantMonitor m_pseudoInterruptMonitor;
+ mozilla::ReentrantMonitor m_dataMemberMonitor;
+ mozilla::ReentrantMonitor m_threadDeathMonitor;
+ mozilla::ReentrantMonitor m_waitForBodyIdsMonitor;
+ mozilla::ReentrantMonitor m_fetchBodyListMonitor;
+ mozilla::ReentrantMonitor m_passwordReadyMonitor;
+ mozilla::Mutex mLock;
+ // If we get an async password prompt, this is where the UI thread
+ // stores the password, before notifying the imap thread of the password
+ // via the m_passwordReadyMonitor.
+ nsString m_password;
+ // Set to the result of nsImapServer::PromptPassword
+ nsresult m_passwordStatus;
+ bool m_passwordObtained;
+
+ bool m_imapThreadIsRunning;
+ void ImapThreadMainLoop(void);
+ nsresult m_connectionStatus;
+ nsCString m_connectionType;
+
+ bool m_nextUrlReadyToRun;
+ bool m_idleResponseReadyToHandle;
+ nsWeakPtr m_server;
+
+ RefPtr<ImapMailFolderSinkProxy> m_imapMailFolderSink;
+ RefPtr<ImapMailFolderSinkProxy> m_imapMailFolderSinkSelected;
+ RefPtr<ImapMessageSinkProxy> m_imapMessageSink;
+ RefPtr<ImapServerSinkProxy> m_imapServerSink;
+ RefPtr<ImapServerSinkProxy> m_imapServerSinkLatest;
+ RefPtr<ImapProtocolSinkProxy> m_imapProtocolSink;
+
+ // helper function to setup imap sink interface proxies
+ nsresult SetupSinkProxy();
+ // End thread support stuff
+ nsresult LoadImapUrlInternal();
+
+ bool GetDeleteIsMoveToTrash();
+ bool GetShowDeletedMessages();
+ nsCString m_currentCommand;
+ nsImapServerResponseParser m_parser;
+ nsImapServerResponseParser& GetServerStateParser() { return m_parser; }
+
+ bool HandleIdleResponses();
+ virtual bool ProcessCurrentURL();
+ void EstablishServerConnection();
+ virtual void ParseIMAPandCheckForNewMail(const char* commandString = nullptr,
+ bool ignoreBadNOResponses = false);
+ // biff
+ void PeriodicBiff();
+ void SendSetBiffIndicatorEvent(nsMsgBiffState newState);
+
+ // folder opening and listing header functions
+ void FolderHeaderDump(uint32_t* msgUids, uint32_t msgCount);
+ void FolderMsgDump(uint32_t* msgUids, uint32_t msgCount,
+ nsIMAPeFetchFields fields);
+ void FolderMsgDumpLoop(uint32_t* msgUids, uint32_t msgCount,
+ nsIMAPeFetchFields fields);
+ void WaitForPotentialListOfBodysToFetch(nsTArray<nsMsgKey>& msgIdList);
+ void HeaderFetchCompleted();
+ void UploadMessageFromFile(nsIFile* file, const char* mailboxName,
+ PRTime date, imapMessageFlagsType flags,
+ nsCString& keywords);
+
+ // mailbox name utilities.
+ void CreateEscapedMailboxName(const char* rawName, nsCString& escapedName);
+ void SetupMessageFlagsString(nsCString& flagString,
+ imapMessageFlagsType flags, uint16_t userFlags);
+
+ // body fetching listing data
+ bool m_fetchBodyListIsNew;
+ nsTArray<nsMsgKey> m_fetchBodyIdList;
+
+ // initialization function given a new url and transport layer
+ nsresult SetupWithUrl(nsIURI* aURL, nsISupports* aConsumer);
+ nsresult SetupWithUrlCallback(nsIProxyInfo* proxyInfo);
+ void ReleaseUrlState(bool rerunningUrl); // release any state that is stored
+ // on a per action basis.
+ /**
+ * Last ditch effort to run the url without using an imap connection.
+ * If it turns out that we don't need to run the url at all (e.g., we're
+ * trying to download a single message for offline use and it has already
+ * been downloaded, this function will send the appropriate notifications.
+ *
+ * @returns true if the url has been run locally, or doesn't need to be run.
+ */
+ bool TryToRunUrlLocally(nsIURI* aURL, nsISupports* aConsumer);
+
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // Communication methods --> Reading and writing protocol
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ // SendData not only writes the NULL terminated data in dataBuffer to our
+ // output stream but it also informs the consumer that the data has been
+ // written to the stream. aSuppressLogging --> set to true if you wish to
+ // suppress logging for this particular command. this is useful for making
+ // sure we don't log authentication information like the user's password
+ // (which was encoded anyway), but still we shouldn't add that information to
+ // the log.
+ nsresult SendData(const char* dataBuffer,
+ bool aSuppressLogging = false) override;
+
+ // state ported over from 4.5
+ bool m_pseudoInterrupted;
+ bool m_active;
+ bool m_folderNeedsSubscribing;
+ bool m_folderNeedsACLRefreshed;
+
+ bool m_threadShouldDie;
+
+ // use to prevent re-entering TellThreadToDie.
+ bool m_inThreadShouldDie;
+ // If the UI thread has signalled the IMAP thread to die, and the
+ // connection has timed out, this will be set to FALSE.
+ bool m_safeToCloseConnection;
+
+ RefPtr<nsImapFlagAndUidState> m_flagState;
+ nsMsgBiffState m_currentBiffState;
+ // manage the IMAP server command tags
+ // 11 = enough memory for the decimal representation of MAX_UINT + trailing
+ // nul
+ char m_currentServerCommandTag[11];
+ uint32_t m_currentServerCommandTagNumber;
+ void IncrementCommandTagNumber();
+ const char* GetServerCommandTag();
+
+ void StartTLS();
+
+ // login related methods.
+ nsresult GetPassword(nsString& password, bool aNewPasswordRequested);
+ void InitPrefAuthMethods(int32_t authMethodPrefValue,
+ nsIMsgIncomingServer* aServer);
+ nsresult ChooseAuthMethod();
+ void MarkAuthMethodAsFailed(eIMAPCapabilityFlags failedAuthMethod);
+ void ResetAuthMethods();
+
+ // All of these methods actually issue protocol
+ void Capability(); // query host for capabilities.
+ void ID(); // send RFC 2971 app info to server
+ void EnableUTF8Accept();
+ void EnableCondStore();
+ void StartCompressDeflate();
+ nsresult BeginCompressing();
+ void Language(); // set the language on the server if it supports it
+ void Namespace();
+ void InsecureLogin(const char* userName, const nsCString& password);
+ nsresult ClientID();
+ nsresult AuthLogin(const char* userName, const nsString& password,
+ eIMAPCapabilityFlag flag);
+ nsresult SendDataParseIMAPandCheckForNewMail(const char* data,
+ const char* command);
+ void ProcessAuthenticatedStateURL();
+ void ProcessAfterAuthenticated();
+ void ProcessSelectedStateURL();
+ bool TryToLogon();
+
+ // ProcessAuthenticatedStateURL() used to be one giant if statement. I've
+ // broken out a set of actions based on the imap action passed into the url.
+ // The following functions are imap protocol handlers for each action. They
+ // are called by ProcessAuthenticatedStateUrl.
+ void OnLSubFolders();
+ void OnAppendMsgFromFile();
+
+ char* GetFolderPathString(); // OK to call from UI thread
+
+ char* OnCreateServerSourceFolderPathString();
+ char* OnCreateServerDestinationFolderPathString();
+ nsresult CreateServerSourceFolderPathString(char** result);
+ void OnCreateFolder(const char* aSourceMailbox);
+ void OnEnsureExistsFolder(const char* aSourceMailbox);
+ void OnSubscribe(const char* aSourceMailbox);
+ void OnUnsubscribe(const char* aSourceMailbox);
+ void RefreshACLForFolderIfNecessary(const char* mailboxName);
+ void RefreshACLForFolder(const char* aSourceMailbox);
+ void GetACLForFolder(const char* aMailboxName);
+ void OnRefreshAllACLs();
+ void OnListFolder(const char* aSourceMailbox, bool aBool);
+ void OnStatusForFolder(const char* sourceMailbox);
+ void OnDeleteFolder(const char* aSourceMailbox);
+ void OnRenameFolder(const char* aSourceMailbox);
+ void OnMoveFolderHierarchy(const char* aSourceMailbox);
+ void DeleteFolderAndMsgs(const char* aSourceMailbox);
+ void RemoveMsgsAndExpunge();
+ void FindMailboxesIfNecessary();
+ void CreateMailbox(const char* mailboxName);
+ void DeleteMailbox(const char* mailboxName);
+ void RenameMailbox(const char* existingName, const char* newName);
+ void RemoveHierarchyDelimiter(nsCString& mailboxName);
+ bool CreateMailboxRespectingSubscriptions(const char* mailboxName);
+ bool DeleteMailboxRespectingSubscriptions(const char* mailboxName);
+ bool RenameMailboxRespectingSubscriptions(const char* existingName,
+ const char* newName,
+ bool reallyRename);
+ // notify the fe that a folder was deleted
+ void FolderDeleted(const char* mailboxName);
+ // notify the fe that a folder creation failed
+ void FolderNotCreated(const char* mailboxName);
+ // notify the fe that a folder was deleted
+ void FolderRenamed(const char* oldName, const char* newName);
+
+ bool FolderIsSelected(const char* mailboxName);
+
+ bool MailboxIsNoSelectMailbox(const char* mailboxName);
+ bool FolderNeedsACLInitialized(const char* folderName);
+ void DiscoverMailboxList();
+ void DiscoverAllAndSubscribedBoxes();
+ void MailboxDiscoveryFinished();
+ void NthLevelChildList(const char* onlineMailboxPrefix, int32_t depth);
+ // LIST SUBSCRIBED command (from RFC 5258) crashes some servers. so we need to
+ // identify those servers
+ bool GetListSubscribedIsBrokenOnServer();
+ void Lsub(const char* mailboxPattern, bool addDirectoryIfNecessary);
+ void List(const char* mailboxPattern, bool addDirectoryIfNecessary,
+ bool useXLIST = false);
+ void Subscribe(const char* mailboxName);
+ void Unsubscribe(const char* mailboxName);
+ void Idle();
+ void EndIdle(bool waitForResponse = true);
+ // Some imap servers include the mailboxName following the dir-separator in
+ // the list of subfolders of the mailboxName. In fact, they are the same. So
+ // we should decide if we should delete such subfolder and provide feedback if
+ // the delete operation succeed.
+ bool DeleteSubFolders(const char* aMailboxName, bool& aDeleteSelf);
+ bool RenameHierarchyByHand(const char* oldParentMailboxName,
+ const char* newParentMailboxName);
+ bool RetryUrl();
+
+ nsresult GlobalInitialization(nsIPrefBranch* aPrefBranch);
+ nsresult Configure(int32_t TooFastTime, int32_t IdealTime,
+ int32_t ChunkAddSize, int32_t ChunkSize,
+ int32_t ChunkThreshold, bool FetchByChunks);
+ nsresult GetMsgWindow(nsIMsgWindow** aMsgWindow);
+ // End Process AuthenticatedState Url helper methods
+
+ virtual char const* GetType() override { return "imap"; }
+
+ // Quota support
+ void GetQuotaDataIfSupported(const char* aBoxName);
+
+ // CondStore support - true if server supports it, and the user hasn't
+ // disabled it.
+ bool UseCondStore();
+ // false if pref "mail.server.serverxxx.use_condstore" is false;
+ bool m_useCondStore;
+ // COMPRESS=DEFLATE support - true if server supports it, and the user hasn't
+ // disabled it.
+ bool UseCompressDeflate();
+ // false if pref "mail.server.serverxxx.use_compress_deflate" is false;
+ bool m_useCompressDeflate;
+ // these come from the nsIDBFolderInfo in the msgDatabase and
+ // are initialized in nsImapProtocol::SetupWithUrl.
+ uint64_t mFolderLastModSeq;
+ int32_t mFolderTotalMsgCount;
+ uint32_t mFolderHighestUID;
+ bool m_allowUTF8Accept;
+
+ bool m_isGmailServer;
+ nsTArray<nsCString> mCustomDBHeaders;
+ nsTArray<nsCString> mCustomHeaders;
+ bool m_trackingTime;
+ PRTime m_startTime;
+ PRTime m_endTime;
+ PRTime m_lastActiveTime;
+ int32_t m_tooFastTime;
+ int32_t m_idealTime;
+ int32_t m_chunkAddSize;
+ int32_t m_chunkStartSize;
+ bool m_fetchByChunks;
+ bool m_sendID;
+ int32_t m_curFetchSize;
+ bool m_ignoreExpunges;
+ eIMAPCapabilityFlags m_prefAuthMethods; // set of capability flags (in
+ // nsImapCore.h) for auth methods
+ eIMAPCapabilityFlags m_failedAuthMethods; // ditto
+ eIMAPCapabilityFlag m_currentAuthMethod; // exactly one capability flag, or 0
+ int32_t m_socketType;
+ int32_t m_chunkSize;
+ int32_t m_chunkThreshold;
+ RefPtr<nsMsgImapLineDownloadCache> m_downloadLineCache;
+ RefPtr<nsMsgImapHdrXferInfo> m_hdrDownloadCache;
+ nsCOMPtr<nsIImapHeaderInfo> m_curHdrInfo;
+ // mapping between mailboxes and the corresponding folder flags
+ nsTHashMap<nsCStringHashKey, int32_t> m_standardListMailboxes;
+ // mapping between special xlist mailboxes and the corresponding folder flags
+ nsTHashMap<nsCStringHashKey, int32_t> m_specialXListMailboxes;
+
+ nsCOMPtr<nsIImapHostSessionList> m_hostSessionList;
+
+ bool m_fromHeaderSeen;
+
+ nsString mAcceptLanguages;
+
+ nsCString m_clientId;
+
+ // progress stuff
+ void SetProgressString(uint32_t aStringIndex);
+
+ nsCString m_progressStringName;
+ uint32_t m_stringIndex;
+ int32_t m_progressCurrentNumber[IMAP_NUMBER_OF_PROGRESS_STRINGS];
+ int32_t m_progressExpectedNumber;
+ nsCString m_lastProgressStringName;
+ int32_t m_lastPercent;
+ int64_t m_lastProgressTime;
+
+ bool m_notifySearchHit;
+ bool m_needNoop;
+ bool m_idle;
+ bool m_useIdle;
+ int32_t m_noopCount;
+ bool m_autoSubscribe, m_autoUnsubscribe, m_autoSubscribeOnOpen;
+ bool m_closeNeededBeforeSelect;
+ bool m_retryUrlOnError;
+ bool m_preferPlainText;
+ bool m_forceSelect;
+
+ int32_t m_uidValidity; // stored uid validity for the selected folder.
+
+ enum EMailboxHierarchyNameState {
+ kNoOperationInProgress,
+ // kDiscoverBaseFolderInProgress, - Unused. Keeping for historical reasons.
+ kDiscoverTrashFolderInProgress,
+ kDeleteSubFoldersInProgress,
+ kListingForInfoOnly,
+ kListingForInfoAndDiscovery,
+ kDiscoveringNamespacesOnly,
+ kXListing,
+ kListingForFolderFlags,
+ kListingForCreate
+ };
+ EMailboxHierarchyNameState m_hierarchyNameState;
+ EMailboxDiscoverStatus m_discoveryStatus;
+ nsTArray<nsIMAPMailboxInfo*> m_listedMailboxList;
+ nsTArray<nsCString>* m_deletableChildren;
+ uint32_t m_flagChangeCount;
+ PRTime m_lastCheckTime;
+
+ bool CheckNeeded();
+
+ nsString m_emptyMimePartString;
+
+ RefPtr<mozilla::mailnews::OAuth2ThreadHelper> mOAuth2Support;
+ bool m_capabilityResponseOccurred;
+
+ nsresult IsTransportAlive(bool* alive);
+ nsresult TransportStartTLS();
+ void GetTransportSecurityInfo(nsITransportSecurityInfo** aSecurityInfo);
+};
+
+// This small class is a "mock" channel because it is a mockery of the imap
+// channel's implementation... it's a light weight channel that we can return to
+// necko when they ask for a channel on a url before we actually have an imap
+// protocol instance around which can run the url. Please see my comments in
+// nsIImapMockChannel.idl for more details..
+//
+// Threading concern: This class lives entirely in the UI thread.
+
+class nsICacheEntry;
+
+class nsImapMockChannel : public nsIImapMockChannel,
+ public nsICacheEntryOpenCallback,
+ public nsITransportEventSink,
+ public nsSupportsWeakReference,
+ public nsMailChannel,
+ public nsHashPropertyBag {
+ public:
+ friend class nsImapProtocol;
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIIMAPMOCKCHANNEL
+ NS_DECL_NSICHANNEL
+ NS_DECL_NSIREQUEST
+ NS_DECL_NSICACHEENTRYOPENCALLBACK
+ NS_DECL_NSITRANSPORTEVENTSINK
+
+ nsImapMockChannel();
+ static nsresult Create(const nsIID& iid, void** result);
+ nsresult RunOnStopRequestFailure();
+
+ protected:
+ virtual ~nsImapMockChannel();
+ nsCOMPtr<nsIURI> m_url;
+
+ nsCOMPtr<nsIURI> m_originalUrl;
+ nsCOMPtr<nsILoadGroup> m_loadGroup;
+ nsCOMPtr<nsILoadInfo> m_loadInfo;
+ nsCOMPtr<nsIStreamListener> m_channelListener;
+ nsresult m_cancelStatus;
+ nsLoadFlags mLoadFlags;
+ nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
+ nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
+ nsCOMPtr<nsISupports> mOwner;
+ nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
+ nsCString mContentType;
+ nsCString mCharset;
+ nsWeakPtr mProtocol;
+
+ bool mChannelClosed;
+ bool mReadingFromCache;
+ int64_t mContentLength;
+ bool mWritingToCache;
+
+ mozilla::Monitor mSuspendedMonitor;
+ bool mSuspended;
+
+ nsresult ResumeAndNotifyOne();
+
+ // cache related helper methods
+ nsresult OpenCacheEntry(); // makes a request to the cache service for a
+ // cache entry for a url
+ bool ReadFromLocalCache(); // attempts to read the url out of our local
+ // (offline) cache....
+ nsresult ReadFromCache2(nsICacheEntry* entry); // pipes message from cache2
+ // entry to channel listener
+ nsresult NotifyStartEndReadFromCache(bool start);
+
+ // we end up daisy chaining multiple nsIStreamListeners into the load process.
+ nsresult SetupPartExtractorListener(nsIImapUrl* aUrl,
+ nsIStreamListener* aConsumer);
+
+ uint32_t mContentDisposition;
+};
+
+#endif // nsImapProtocol_h___