diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/imap/src/nsImapProtocol.h | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/imap/src/nsImapProtocol.h')
-rw-r--r-- | comm/mailnews/imap/src/nsImapProtocol.h | 848 |
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___ |