1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsImapProtocol_h___ 7 #define nsImapProtocol_h___ 8 9 #include "mozilla/Attributes.h" 10 #include "nsIImapProtocol.h" 11 #include "nsIImapUrl.h" 12 13 #include "nsMsgProtocol.h" 14 #include "nsIStreamListener.h" 15 #include "nsIAsyncOutputStream.h" 16 #include "nsIAsyncInputStream.h" 17 #include "nsImapCore.h" 18 #include "nsString.h" 19 #include "nsIProgressEventSink.h" 20 #include "nsIInterfaceRequestor.h" 21 #include "nsISocketTransport.h" 22 23 // UI Thread proxy helper 24 #include "nsIImapProtocolSink.h" 25 26 #include "nsIImapHostSessionList.h" 27 #include "nsImapServerResponseParser.h" 28 #include "nsImapFlagAndUidState.h" 29 #include "nsImapNamespace.h" 30 #include "nsTArray.h" 31 #include "nsIWeakReferenceUtils.h" 32 #include "nsMsgLineBuffer.h" // we need this to use the nsMsgLineStreamBuffer helper class... 33 #include "nsIInputStream.h" 34 #include "nsIMsgIncomingServer.h" 35 #include "nsCOMArray.h" 36 #include "nsIThread.h" 37 #include "nsIRunnable.h" 38 #include "nsIImapMockChannel.h" 39 #include "nsILoadGroup.h" 40 #include "nsCOMPtr.h" 41 #include "nsIMsgWindow.h" 42 #include "nsIImapHeaderXferInfo.h" 43 #include "nsMsgLineBuffer.h" 44 #include "nsIAsyncInputStream.h" 45 #include "nsIMsgFolder.h" 46 #include "nsIMsgAsyncPrompter.h" 47 #include "mozilla/ReentrantMonitor.h" 48 #include "nsSyncRunnableHelpers.h" 49 #include "nsICacheEntryOpenCallback.h" 50 #include "nsIProtocolProxyCallback.h" 51 #include "nsIStringBundle.h" 52 #include "nsHashPropertyBag.h" 53 54 #include "mozilla/Monitor.h" 55 56 class nsIMAPMessagePartID; 57 class nsIPrefBranch; 58 59 #define kDownLoadCacheSize 16000u // was 1536 - try making it bigger 60 61 typedef struct _msg_line_info { 62 const char* adoptedMessageLine; 63 uint32_t uidOfMessage; 64 } msg_line_info; 65 66 class nsMsgImapLineDownloadCache : public nsIImapHeaderInfo, 67 public nsByteArray { 68 public: 69 NS_DECL_THREADSAFE_ISUPPORTS 70 NS_DECL_NSIIMAPHEADERINFO 71 nsMsgImapLineDownloadCache(); 72 uint32_t CurrentUID(); 73 uint32_t SpaceAvailable(); 74 bool CacheEmpty(); 75 76 msg_line_info* GetCurrentLineInfo(); 77 78 private: 79 virtual ~nsMsgImapLineDownloadCache(); 80 81 msg_line_info* fLineInfo; 82 int32_t m_msgSize; 83 }; 84 85 #define kNumHdrsToXfer 10 86 87 class nsMsgImapHdrXferInfo : public nsIImapHeaderXferInfo { 88 public: 89 NS_DECL_THREADSAFE_ISUPPORTS 90 NS_DECL_NSIIMAPHEADERXFERINFO 91 nsMsgImapHdrXferInfo(); 92 void ResetAll(); // reset HeaderInfos for re-use 93 void ReleaseAll(); // release HeaderInfos (frees up memory) 94 // this will return null if we're full, in which case the client code 95 // should transfer the headers and retry. 96 nsIImapHeaderInfo* StartNewHdr(); 97 // call when we've finished adding lines to current hdr 98 void FinishCurrentHdr(); 99 100 private: 101 virtual ~nsMsgImapHdrXferInfo(); 102 nsCOMArray<nsIImapHeaderInfo> m_hdrInfos; 103 int32_t m_nextFreeHdrInfo; 104 }; 105 106 // This class contains the name of a mailbox and whether or not 107 // its children have been listed. 108 class nsIMAPMailboxInfo { 109 public: 110 nsIMAPMailboxInfo(const nsACString& aName, char aDelimiter); 111 virtual ~nsIMAPMailboxInfo(); 112 113 void SetChildrenListed(bool childrenListed); 114 bool GetChildrenListed(); 115 const nsACString& GetMailboxName(); 116 char GetDelimiter(); 117 118 protected: 119 nsCString mMailboxName; 120 bool mChildrenListed; 121 char mDelimiter; 122 }; 123 124 // State Flags (Note, I use the word state in terms of storing 125 // state information about the connection (authentication, have we sent 126 // commands, etc. I do not intend it to refer to protocol state) 127 // Use these flags in conjunction with SetFlag/TestFlag/ClearFlag instead 128 // of creating PRBools for everything.... 129 // clang-format off 130 #define IMAP_RECEIVED_GREETING 0x00000001 // should we pause for the next read 131 #define IMAP_CONNECTION_IS_OPEN 0x00000004 // is the connection currently open? 132 #define IMAP_WAITING_FOR_DATA 0x00000008 133 #define IMAP_CLEAN_UP_URL_STATE 0x00000010 // processing clean up url state 134 #define IMAP_ISSUED_LANGUAGE_REQUEST 0x00000020 // make sure we only issue the language 135 // request once per connection... 136 #define IMAP_ISSUED_COMPRESS_REQUEST 0x00000040 // make sure we only request compression once 137 138 // There are 3 types of progress strings for items downloaded from IMAP servers. 139 // An index is needed to keep track of the current count of the number of each 140 // item type downloaded. The IMAP_EMPTY_STRING_INDEX means no string displayed. 141 #define IMAP_NUMBER_OF_PROGRESS_STRINGS 4 142 #define IMAP_HEADERS_STRING_INDEX 0 143 #define IMAP_FLAGS_STRING_INDEX 1 144 #define IMAP_MESSAGES_STRING_INDEX 2 145 #define IMAP_EMPTY_STRING_INDEX 3 146 // clang-format on 147 148 /** 149 * nsImapProtocol is, among other things, the underlying nsIChannel 150 * implementation for the IMAP protocol. However, it's usually hidden away 151 * behind nsImapMockChannel objects. It also represents the 'real' connection 152 * to the IMAP server - it maintains the nsISocketTransport. 153 * Because there can be multiple IMAP requests queued up, NS_NewChannel() 154 * will return nsImapMockChannel objects instead, to keep the request in a 155 * holding pattern until the connection is free. At which time the mock 156 * channel will just forward calls onward to the nsImapProtocol. 157 * 158 * The url scheme we implement here encodes various IMAP commands as URLs. 159 * Some URLs are just traditional I/O based nsIChannel transactions, but 160 * many others have side effects. For example, an IMAP folder discovery 161 * command might cause the creation of the nsImapMailFolder hierarchy under 162 * the the nsImapIncomingServer. 163 * Such side effects are communicated via the various "Sink" interfaces. This 164 * helps decouple the IMAP code from the rest of the system: 165 * 166 * - nsIImapServerSink (implemented by nsImapIncomingServer) 167 * - nsIImapMailFolderSink (implemented by nsImapMailFolder) 168 * - nsIImapMessageSink (implemented by nsImapMailFolder) 169 * 170 * Internal to nsImapProtocol, these sink classes all have corresponding proxy 171 * implementations (ImapServerSinkProxy, ImapMailFolderSinkProxy and 172 * ImapMessageSinkProxy). These allow us to safely call the sink objects, in 173 * a synchronous fashion, from I/O threads (threads other than the main one). 174 * When an IMAP routine calls a member function of one of these sink proxies, 175 * it dispatches a call to the real sink object on the main thread, then 176 * blocks until the call is completed. 177 */ 178 class nsImapProtocol : public nsIImapProtocol, 179 public nsIInputStreamCallback, 180 public nsSupportsWeakReference, 181 public nsMsgProtocol, 182 public nsIImapProtocolSink, 183 public nsIMsgAsyncPromptListener, 184 public nsIProtocolProxyCallback { 185 public: 186 struct TCPKeepalive { 187 // For enabling and setting TCP keepalive (not related to IMAP IDLE). 188 std::atomic<bool> enabled; 189 std::atomic<int32_t> idleTimeS; 190 std::atomic<int32_t> retryIntervalS; 191 }; 192 193 NS_DECL_ISUPPORTS_INHERITED 194 NS_DECL_NSIINPUTSTREAMCALLBACK 195 NS_DECL_NSIPROTOCOLPROXYCALLBACK 196 nsImapProtocol(); 197 198 virtual nsresult ProcessProtocolState(nsIURI* url, 199 nsIInputStream* inputStream, 200 uint64_t sourceOffset, 201 uint32_t length) override; 202 203 ////////////////////////////////////////////////////////////////////////////////// 204 // we support the nsIImapProtocol interface 205 ////////////////////////////////////////////////////////////////////////////////// 206 NS_DECL_NSIIMAPPROTOCOL 207 208 ////////////////////////////////////////////////////////////////////////////////// 209 // we support the nsIImapProtocolSink interface 210 ////////////////////////////////////////////////////////////////////////////////// 211 NS_DECL_NSIIMAPPROTOCOLSINK 212 213 NS_DECL_NSIMSGASYNCPROMPTLISTENER 214 215 // message id string utilities. 216 uint32_t CountMessagesInIdString(const char* idString); 217 static bool HandlingMultipleMessages(const nsCString& messageIdString); 218 // escape slashes and double quotes in username/passwords for insecure login. 219 static void EscapeUserNamePasswordString(const char* strToEscape, 220 nsCString* resultStr); 221 222 // used to start fetching a message. 223 void GetShouldDownloadAllHeaders(bool* aResult); 224 void GetArbitraryHeadersToDownload(nsCString& aResult); 225 virtual void AdjustChunkSize(); 226 virtual void FetchMessage(const nsCString& messageIds, 227 nsIMAPeFetchFields whatToFetch, 228 const char* fetchModifier = nullptr, 229 uint32_t startByte = 0, uint32_t numBytes = 0, 230 char* part = 0); 231 void FetchTryChunking(const nsCString& messageIds, 232 nsIMAPeFetchFields whatToFetch, bool idIsUid, 233 char* part, uint32_t downloadSize, bool tryChunking); 234 virtual void PipelinedFetchMessageParts( 235 nsCString& uid, const nsTArray<nsIMAPMessagePartID>& parts); 236 void FallbackToFetchWholeMsg(const nsCString& messageId, 237 uint32_t messageSize); 238 // used when streaming a message fetch 239 virtual nsresult BeginMessageDownLoad( 240 uint32_t totalSize, // for user, headers and body 241 const char* contentType); // some downloads are header only 242 virtual void HandleMessageDownLoadLine(const char* line, bool isPartialLine, 243 char* lineCopy = nullptr); 244 virtual void NormalMessageEndDownload(); 245 virtual void AbortMessageDownLoad(); 246 virtual void PostLineDownLoadEvent(const char* line, uint32_t uid); 247 void FlushDownloadCache(); 248 249 virtual void SetMailboxDiscoveryStatus(EMailboxDiscoverStatus status); 250 virtual EMailboxDiscoverStatus GetMailboxDiscoveryStatus(); 251 252 virtual void ProcessMailboxUpdate(bool handlePossibleUndo); 253 // Send log output... 254 void Log(const char* logSubName, const char* extraInfo, const char* logData); 255 static void LogImapUrl(const char* logMsg, nsIImapUrl* imapUrl); 256 // Comment from 4.5: We really need to break out the thread synchronizer from 257 // the connection class...Not sure what this means 258 bool GetPseudoInterrupted(); 259 void PseudoInterrupt(bool the_interrupt); 260 261 uint32_t GetMessageSize(const nsACString& messageId); 262 bool GetSubscribingNow(); 263 264 bool DeathSignalReceived(); 265 void ResetProgressInfo(); 266 void SetActive(bool active); 267 bool GetActive(); 268 269 bool GetShowAttachmentsInline(); 270 271 // Sets whether or not the content referenced by the current ActiveEntry has 272 // been modified. Used for MIME parts on demand. 273 void SetContentModified(IMAP_ContentModifiedType modified); 274 bool GetShouldFetchAllParts(); GetIgnoreExpunges()275 bool GetIgnoreExpunges() { return m_ignoreExpunges; } 276 // Generic accessors required by the imap parser 277 char* CreateNewLineFromSocket(); 278 nsresult GetConnectionStatus(); 279 void SetConnectionStatus(nsresult status); 280 281 // Cleanup the connection and shutdown the thread. 282 void TellThreadToDie(); 283 284 const nsCString& 285 GetImapHostName(); // return the host name from the url for the 286 // current connection 287 const nsCString& GetImapUserName(); // return the user name from the identity 288 const char* 289 GetImapServerKey(); // return the user name from the incoming server; 290 291 // state set by the imap parser... 292 void NotifyMessageFlags(imapMessageFlagsType flags, 293 const nsACString& keywords, nsMsgKey key, 294 uint64_t highestModSeq); 295 void NotifySearchHit(const char* hitLine); 296 297 // Event handlers for the imap parser. 298 void DiscoverMailboxSpec(nsImapMailboxSpec* adoptedBoxSpec); 299 void AlertUserEventUsingName(const char* aMessageId); 300 void AlertUserEvent(const char* message); 301 void AlertUserEventFromServer(const char* aServerEvent, 302 bool aForIdle = false); 303 304 void ProgressEventFunctionUsingName(const char* aMsgId); 305 void ProgressEventFunctionUsingNameWithString(const char* aMsgName, 306 const char* aExtraInfo); 307 void PercentProgressUpdateEvent(nsACString const& fmtStringName, 308 nsAString const& mailbox, 309 int64_t currentProgress, int64_t maxProgress); 310 void ShowProgress(); 311 312 // utility function calls made by the server 313 314 void Copy(const char* messageList, const char* destinationMailbox, 315 bool idsAreUid); 316 void Search(const char* searchCriteria, bool useUID, bool notifyHit = true); 317 // imap commands issued by the parser 318 void Store(const nsCString& aMessageList, const char* aMessageData, 319 bool aIdsAreUid); 320 void ProcessStoreFlags(const nsCString& messageIds, bool idsAreUids, 321 imapMessageFlagsType flags, bool addFlags); 322 void IssueUserDefinedMsgCommand(const char* command, const char* messageList); 323 void FetchMsgAttribute(const nsCString& messageIds, 324 const nsCString& attribute); 325 void Expunge(); 326 void UidExpunge(const nsCString& messageSet); 327 void Close(bool shuttingDown = false, bool waitForResponse = true); 328 void Check(); 329 void SelectMailbox(const char* mailboxName); 330 // more imap commands 331 void Logout(bool shuttingDown = false, bool waitForResponse = true); 332 void Noop(); 333 void XServerInfo(); 334 void Netscape(); 335 void XMailboxInfo(const char* mailboxName); 336 void XAOL_Option(const char* option); 337 void MailboxData(); 338 void GetMyRightsForFolder(const char* mailboxName); 339 void Bodystructure(const nsCString& messageId, bool idIsUid); 340 void PipelinedFetchMessageParts(const char* uid, 341 const nsTArray<nsIMAPMessagePartID>& parts); 342 343 // this function does not ref count!!! be careful!!! GetCurrentUrl()344 nsIImapUrl* GetCurrentUrl() { return m_runningUrl; } 345 346 // acl and namespace stuff 347 // notifies libmsg that we have a new personal/default namespace that we're 348 // using 349 void CommitNamespacesForHostEvent(); 350 // notifies libmsg that we have new capability data for the current host 351 void CommitCapability(); 352 353 // Adds a set of rights for a given user on a given mailbox on the current 354 // host. if userName is NULL, it means "me," or MYRIGHTS. rights is a single 355 // string of rights, as specified by RFC2086, the IMAP ACL extension. 356 void AddFolderRightsForUser(const char* mailboxName, const char* userName, 357 const char* rights); 358 // Clears all rights for the current folder, for all users. 359 void ClearAllFolderRights(); 360 void RefreshFolderACLView(const char* mailboxName, 361 nsImapNamespace* nsForMailbox); 362 363 nsresult SetFolderAdminUrl(const char* mailboxName); 364 void HandleMemoryFailure(); 365 void HandleCurrentUrlError(); 366 367 // UIDPLUS extension 368 void SetCopyResponseUid(const char* msgIdString); 369 370 // Quota support 371 void UpdateFolderQuotaData(nsImapQuotaAction aAction, nsCString& aQuotaRoot, 372 uint64_t aUsed, uint64_t aMax); 373 GetPreferPlainText()374 bool GetPreferPlainText() { return m_preferPlainText; } 375 GetCurFetchSize()376 int32_t GetCurFetchSize() { return m_curFetchSize; } 377 GetEmptyMimePartString()378 const nsString& GetEmptyMimePartString() { return m_emptyMimePartString; } 379 void SetCapabilityResponseOccurred(); 380 381 // Start event loop. This is called on IMAP thread 382 bool RunImapThreadMainLoop(); 383 384 private: 385 virtual ~nsImapProtocol(); 386 // the following flag is used to determine when a url is currently being run. 387 // It is cleared when we finish processng a url and it is set whenever we call 388 // Load on a url 389 bool m_urlInProgress; 390 391 /** The nsIImapURL that is currently running. */ 392 nsCOMPtr<nsIImapUrl> m_runningUrl; 393 nsCOMPtr<nsIImapUrl> m_runningUrlLatest; 394 /** Current imap action associated with this connection. */ 395 nsImapAction m_imapAction; 396 397 nsCString m_hostName; 398 nsCString m_userName; 399 nsCString m_serverKey; 400 nsCString m_realHostName; 401 char* m_dataOutputBuf; 402 RefPtr<nsMsgLineStreamBuffer> m_inputStreamBuffer; 403 nsCString m_trashFolderPath; 404 405 /** The socket connection to the IMAP server. */ 406 nsCOMPtr<nsISocketTransport> m_transport; 407 408 /** Stream to handle data coming in from the IMAP server. */ 409 nsCOMPtr<nsIInputStream> m_inputStream; 410 411 nsCOMPtr<nsIAsyncInputStream> m_channelInputStream; 412 nsCOMPtr<nsIAsyncOutputStream> m_channelOutputStream; 413 414 /** The currently running request. */ 415 nsCOMPtr<nsIImapMockChannel> m_mockChannel; 416 417 uint32_t m_bytesToChannel; 418 bool m_fetchingWholeMessage; 419 // nsCOMPtr<nsIRequest> mAsyncReadRequest; // we're going to cancel this when 420 // we're done with the conn. 421 422 // ******* Thread support ******* 423 PRThread* m_thread; 424 mozilla::ReentrantMonitor 425 m_dataAvailableMonitor; // used to notify the arrival of data from the 426 // server 427 mozilla::ReentrantMonitor 428 m_urlReadyToRunMonitor; // used to notify the arrival of a new url to be 429 // processed 430 mozilla::ReentrantMonitor m_pseudoInterruptMonitor; 431 mozilla::ReentrantMonitor m_dataMemberMonitor; 432 mozilla::ReentrantMonitor m_threadDeathMonitor; 433 mozilla::ReentrantMonitor m_waitForBodyIdsMonitor; 434 mozilla::ReentrantMonitor m_fetchBodyListMonitor; 435 mozilla::ReentrantMonitor m_passwordReadyMonitor; 436 mozilla::Mutex mLock; 437 // If we get an async password prompt, this is where the UI thread 438 // stores the password, before notifying the imap thread of the password 439 // via the m_passwordReadyMonitor. 440 nsString m_password; 441 // Set to the result of nsImapServer::PromptPassword 442 nsresult m_passwordStatus; 443 bool m_passwordObtained; 444 445 bool m_imapThreadIsRunning; 446 void ImapThreadMainLoop(void); 447 nsresult m_connectionStatus; 448 nsCString m_connectionType; 449 450 bool m_nextUrlReadyToRun; 451 nsWeakPtr m_server; 452 453 RefPtr<ImapMailFolderSinkProxy> m_imapMailFolderSink; 454 RefPtr<ImapMessageSinkProxy> m_imapMessageSink; 455 RefPtr<ImapServerSinkProxy> m_imapServerSink; 456 RefPtr<ImapServerSinkProxy> m_imapServerSinkLatest; 457 RefPtr<ImapProtocolSinkProxy> m_imapProtocolSink; 458 459 // helper function to setup imap sink interface proxies 460 nsresult SetupSinkProxy(); 461 // End thread support stuff 462 nsresult LoadImapUrlInternal(); 463 464 bool GetDeleteIsMoveToTrash(); 465 bool GetShowDeletedMessages(); 466 nsCString m_currentCommand; 467 nsImapServerResponseParser m_parser; GetServerStateParser()468 nsImapServerResponseParser& GetServerStateParser() { return m_parser; } 469 470 void HandleIdleResponses(); 471 virtual bool ProcessCurrentURL(); 472 void EstablishServerConnection(); 473 virtual void ParseIMAPandCheckForNewMail(const char* commandString = nullptr, 474 bool ignoreBadNOResponses = false); 475 // biff 476 void PeriodicBiff(); 477 void SendSetBiffIndicatorEvent(nsMsgBiffState newState); 478 479 // folder opening and listing header functions 480 void FolderHeaderDump(uint32_t* msgUids, uint32_t msgCount); 481 void FolderMsgDump(uint32_t* msgUids, uint32_t msgCount, 482 nsIMAPeFetchFields fields); 483 void FolderMsgDumpLoop(uint32_t* msgUids, uint32_t msgCount, 484 nsIMAPeFetchFields fields); 485 void WaitForPotentialListOfBodysToFetch(nsTArray<nsMsgKey>& msgIdList); 486 void HeaderFetchCompleted(); 487 void UploadMessageFromFile(nsIFile* file, const char* mailboxName, 488 PRTime date, imapMessageFlagsType flags, 489 nsCString& keywords); 490 491 // mailbox name utilities. 492 void CreateEscapedMailboxName(const char* rawName, nsCString& escapedName); 493 void SetupMessageFlagsString(nsCString& flagString, 494 imapMessageFlagsType flags, uint16_t userFlags); 495 496 // body fetching listing data 497 bool m_fetchBodyListIsNew; 498 nsTArray<nsMsgKey> m_fetchBodyIdList; 499 500 // initialization function given a new url and transport layer 501 nsresult SetupWithUrl(nsIURI* aURL, nsISupports* aConsumer); 502 nsresult SetupWithUrlCallback(nsIProxyInfo* proxyInfo); 503 void ReleaseUrlState(bool rerunningUrl); // release any state that is stored 504 // on a per action basis. 505 /** 506 * Last ditch effort to run the url without using an imap connection. 507 * If it turns out that we don't need to run the url at all (e.g., we're 508 * trying to download a single message for offline use and it has already 509 * been downloaded, this function will send the appropriate notifications. 510 * 511 * @returns true if the url has been run locally, or doesn't need to be run. 512 */ 513 bool TryToRunUrlLocally(nsIURI* aURL, nsISupports* aConsumer); 514 515 //////////////////////////////////////////////////////////////////////////////////////// 516 // Communication methods --> Reading and writing protocol 517 //////////////////////////////////////////////////////////////////////////////////////// 518 519 // SendData not only writes the NULL terminated data in dataBuffer to our 520 // output stream but it also informs the consumer that the data has been 521 // written to the stream. aSuppressLogging --> set to true if you wish to 522 // suppress logging for this particular command. this is useful for making 523 // sure we don't log authentication information like the user's password 524 // (which was encoded anyway), but still we shouldn't add that information to 525 // the log. 526 nsresult SendData(const char* dataBuffer, 527 bool aSuppressLogging = false) override; 528 529 // state ported over from 4.5 530 bool m_pseudoInterrupted; 531 bool m_active; 532 bool m_folderNeedsSubscribing; 533 bool m_folderNeedsACLRefreshed; 534 535 bool m_threadShouldDie; 536 537 // use to prevent re-entering TellThreadToDie. 538 bool m_inThreadShouldDie; 539 // if the UI thread has signalled the IMAP thread to die, and the 540 // connection has timed out, this will be set to FALSE. 541 bool m_safeToCloseConnection; 542 543 RefPtr<nsImapFlagAndUidState> m_flagState; 544 nsMsgBiffState m_currentBiffState; 545 // manage the IMAP server command tags 546 // 11 = enough memory for the decimal representation of MAX_UINT + trailing 547 // nul 548 char m_currentServerCommandTag[11]; 549 uint32_t m_currentServerCommandTagNumber; 550 void IncrementCommandTagNumber(); 551 const char* GetServerCommandTag(); 552 553 void StartTLS(); 554 555 // login related methods. 556 nsresult GetPassword(nsString& password, bool aNewPasswordRequested); 557 void InitPrefAuthMethods(int32_t authMethodPrefValue, 558 nsIMsgIncomingServer* aServer); 559 nsresult ChooseAuthMethod(); 560 void MarkAuthMethodAsFailed(eIMAPCapabilityFlags failedAuthMethod); 561 void ResetAuthMethods(); 562 563 // All of these methods actually issue protocol 564 void Capability(); // query host for capabilities. 565 void ID(); // send RFC 2971 app info to server 566 void EnableUTF8Accept(); 567 void EnableCondStore(); 568 void StartCompressDeflate(); 569 nsresult BeginCompressing(); 570 void Language(); // set the language on the server if it supports it 571 void Namespace(); 572 void InsecureLogin(const char* userName, const nsCString& password); 573 nsresult ClientID(); 574 nsresult AuthLogin(const char* userName, const nsString& password, 575 eIMAPCapabilityFlag flag); 576 nsresult SendDataParseIMAPandCheckForNewMail(const char* data, 577 const char* command); 578 void ProcessAuthenticatedStateURL(); 579 void ProcessAfterAuthenticated(); 580 void ProcessSelectedStateURL(); 581 bool TryToLogon(); 582 583 // Process Authenticated State Url used to be one giant if statement. I've 584 // broken out a set of actions based on the imap action passed into the url. 585 // The following functions are imap protocol handlers for each action. They 586 // are called by ProcessAuthenticatedStateUrl. 587 void OnLSubFolders(); 588 void OnAppendMsgFromFile(); 589 590 char* GetFolderPathString(); // OK to call from UI thread 591 592 char* OnCreateServerSourceFolderPathString(); 593 char* OnCreateServerDestinationFolderPathString(); 594 nsresult CreateServerSourceFolderPathString(char** result); 595 void OnCreateFolder(const char* aSourceMailbox); 596 void OnEnsureExistsFolder(const char* aSourceMailbox); 597 void OnSubscribe(const char* aSourceMailbox); 598 void OnUnsubscribe(const char* aSourceMailbox); 599 void RefreshACLForFolderIfNecessary(const char* mailboxName); 600 void RefreshACLForFolder(const char* aSourceMailbox); 601 void GetACLForFolder(const char* aMailboxName); 602 void OnRefreshAllACLs(); 603 void OnListFolder(const char* aSourceMailbox, bool aBool); 604 void OnStatusForFolder(const char* sourceMailbox); 605 void OnDeleteFolder(const char* aSourceMailbox); 606 void OnRenameFolder(const char* aSourceMailbox); 607 void OnMoveFolderHierarchy(const char* aSourceMailbox); 608 void DeleteFolderAndMsgs(const char* aSourceMailbox); 609 void RemoveMsgsAndExpunge(); 610 void FindMailboxesIfNecessary(); 611 void CreateMailbox(const char* mailboxName); 612 void DeleteMailbox(const char* mailboxName); 613 void RenameMailbox(const char* existingName, const char* newName); 614 void RemoveHierarchyDelimiter(nsCString& mailboxName); 615 bool CreateMailboxRespectingSubscriptions(const char* mailboxName); 616 bool DeleteMailboxRespectingSubscriptions(const char* mailboxName); 617 bool RenameMailboxRespectingSubscriptions(const char* existingName, 618 const char* newName, 619 bool reallyRename); 620 // notify the fe that a folder was deleted 621 void FolderDeleted(const char* mailboxName); 622 // notify the fe that a folder creation failed 623 void FolderNotCreated(const char* mailboxName); 624 // notify the fe that a folder was deleted 625 void FolderRenamed(const char* oldName, const char* newName); 626 627 bool FolderIsSelected(const char* mailboxName); 628 629 bool MailboxIsNoSelectMailbox(const char* mailboxName); 630 bool FolderNeedsACLInitialized(const char* folderName); 631 void DiscoverMailboxList(); 632 void DiscoverAllAndSubscribedBoxes(); 633 void MailboxDiscoveryFinished(); 634 void NthLevelChildList(const char* onlineMailboxPrefix, int32_t depth); 635 // LIST SUBSCRIBED command (from RFC 5258) crashes some servers. so we need to 636 // identify those servers 637 bool GetListSubscribedIsBrokenOnServer(); 638 bool IsExtraSelectNeeded(); 639 void Lsub(const char* mailboxPattern, bool addDirectoryIfNecessary); 640 void List(const char* mailboxPattern, bool addDirectoryIfNecessary, 641 bool useXLIST = false); 642 void Subscribe(const char* mailboxName); 643 void Unsubscribe(const char* mailboxName); 644 void Idle(); 645 void EndIdle(bool waitForResponse = true); 646 // Some imap servers include the mailboxName following the dir-separator in 647 // the list of subfolders of the mailboxName. In fact, they are the same. So 648 // we should decide if we should delete such subfolder and provide feedback if 649 // the delete operation succeed. 650 bool DeleteSubFolders(const char* aMailboxName, bool& aDeleteSelf); 651 bool RenameHierarchyByHand(const char* oldParentMailboxName, 652 const char* newParentMailboxName); 653 bool RetryUrl(); 654 655 nsresult GlobalInitialization(nsIPrefBranch* aPrefBranch); 656 nsresult Configure(int32_t TooFastTime, int32_t IdealTime, 657 int32_t ChunkAddSize, int32_t ChunkSize, 658 int32_t ChunkThreshold, bool FetchByChunks); 659 nsresult GetMsgWindow(nsIMsgWindow** aMsgWindow); 660 // End Process AuthenticatedState Url helper methods 661 GetType()662 virtual char const* GetType() override { return "imap"; } 663 664 // Quota support 665 void GetQuotaDataIfSupported(const char* aBoxName); 666 667 // CondStore support - true if server supports it, and the user hasn't 668 // disabled it. 669 bool UseCondStore(); 670 // false if pref "mail.server.serverxxx.use_condstore" is false; 671 bool m_useCondStore; 672 // COMPRESS=DEFLATE support - true if server supports it, and the user hasn't 673 // disabled it. 674 bool UseCompressDeflate(); 675 // false if pref "mail.server.serverxxx.use_compress_deflate" is false; 676 bool m_useCompressDeflate; 677 // these come from the nsIDBFolderInfo in the msgDatabase and 678 // are initialized in nsImapProtocol::SetupWithUrl. 679 uint64_t mFolderLastModSeq; 680 int32_t mFolderTotalMsgCount; 681 uint32_t mFolderHighestUID; 682 uint32_t mFolderNumDeleted; 683 bool m_allowUTF8Accept; 684 685 bool m_isGmailServer; 686 nsTArray<nsCString> mCustomDBHeaders; 687 nsTArray<nsCString> mCustomHeaders; 688 bool m_trackingTime; 689 PRTime m_startTime; 690 PRTime m_endTime; 691 PRTime m_lastActiveTime; 692 int32_t m_tooFastTime; 693 int32_t m_idealTime; 694 int32_t m_chunkAddSize; 695 int32_t m_chunkStartSize; 696 bool m_fetchByChunks; 697 bool m_sendID; 698 int32_t m_curFetchSize; 699 bool m_ignoreExpunges; 700 eIMAPCapabilityFlags m_prefAuthMethods; // set of capability flags (in 701 // nsImapCore.h) for auth methods 702 eIMAPCapabilityFlags m_failedAuthMethods; // ditto 703 eIMAPCapabilityFlag m_currentAuthMethod; // exactly one capability flag, or 0 704 int32_t m_socketType; 705 int32_t m_chunkSize; 706 int32_t m_chunkThreshold; 707 RefPtr<nsMsgImapLineDownloadCache> m_downloadLineCache; 708 RefPtr<nsMsgImapHdrXferInfo> m_hdrDownloadCache; 709 nsCOMPtr<nsIImapHeaderInfo> m_curHdrInfo; 710 // mapping between mailboxes and the corresponding folder flags 711 nsTHashMap<nsCStringHashKey, int32_t> m_standardListMailboxes; 712 // mapping between special xlist mailboxes and the corresponding folder flags 713 nsTHashMap<nsCStringHashKey, int32_t> m_specialXListMailboxes; 714 715 nsCOMPtr<nsIImapHostSessionList> m_hostSessionList; 716 717 bool m_fromHeaderSeen; 718 719 nsString mAcceptLanguages; 720 721 nsCString m_clientId; 722 723 // progress stuff 724 void SetProgressString(uint32_t aStringIndex); 725 726 nsCString m_progressStringName; 727 uint32_t m_stringIndex; 728 int32_t m_progressCurrentNumber[IMAP_NUMBER_OF_PROGRESS_STRINGS]; 729 int32_t m_progressExpectedNumber; 730 nsCString m_lastProgressStringName; 731 int32_t m_lastPercent; 732 int64_t m_lastProgressTime; 733 734 bool m_notifySearchHit; 735 bool m_needNoop; 736 bool m_idle; 737 bool m_useIdle; 738 int32_t m_noopCount; 739 bool m_autoSubscribe, m_autoUnsubscribe, m_autoSubscribeOnOpen; 740 bool m_closeNeededBeforeSelect; 741 bool m_retryUrlOnError; 742 bool m_preferPlainText; 743 nsCString m_forceSelectValue; 744 bool m_forceSelect; 745 746 int32_t m_uidValidity; // stored uid validity for the selected folder. 747 748 enum EMailboxHierarchyNameState { 749 kNoOperationInProgress, 750 // kDiscoverBaseFolderInProgress, - Unused. Keeping for historical reasons. 751 kDiscoverTrashFolderInProgress, 752 kDeleteSubFoldersInProgress, 753 kListingForInfoOnly, 754 kListingForInfoAndDiscovery, 755 kDiscoveringNamespacesOnly, 756 kXListing, 757 kListingForFolderFlags, 758 kListingForCreate 759 }; 760 EMailboxHierarchyNameState m_hierarchyNameState; 761 EMailboxDiscoverStatus m_discoveryStatus; 762 nsTArray<nsIMAPMailboxInfo*> m_listedMailboxList; 763 nsTArray<char*>* m_deletableChildren; 764 uint32_t m_flagChangeCount; 765 PRTime m_lastCheckTime; 766 767 bool CheckNeeded(); 768 769 nsString m_emptyMimePartString; 770 771 RefPtr<mozilla::mailnews::OAuth2ThreadHelper> mOAuth2Support; 772 bool m_capabilityResponseOccurred; 773 }; 774 775 // This small class is a "mock" channel because it is a mockery of the imap 776 // channel's implementation... it's a light weight channel that we can return to 777 // necko when they ask for a channel on a url before we actually have an imap 778 // protocol instance around which can run the url. Please see my comments in 779 // nsIImapMockChannel.idl for more details.. 780 // 781 // Threading concern: This class lives entirely in the UI thread. 782 783 class nsICacheEntry; 784 785 class nsImapMockChannel : public nsIImapMockChannel, 786 public nsICacheEntryOpenCallback, 787 public nsITransportEventSink, 788 public nsSupportsWeakReference, 789 public nsHashPropertyBag { 790 public: 791 friend class nsImapProtocol; 792 793 NS_DECL_ISUPPORTS_INHERITED 794 NS_DECL_NSIIMAPMOCKCHANNEL 795 NS_DECL_NSICHANNEL 796 NS_DECL_NSIREQUEST 797 NS_DECL_NSICACHEENTRYOPENCALLBACK 798 NS_DECL_NSITRANSPORTEVENTSINK 799 800 nsImapMockChannel(); 801 static nsresult Create(const nsIID& iid, void** result); 802 nsresult RunOnStopRequestFailure(); 803 804 protected: 805 virtual ~nsImapMockChannel(); 806 nsCOMPtr<nsIURI> m_url; 807 808 nsCOMPtr<nsIURI> m_originalUrl; 809 nsCOMPtr<nsILoadGroup> m_loadGroup; 810 nsCOMPtr<nsILoadInfo> m_loadInfo; 811 nsCOMPtr<nsIStreamListener> m_channelListener; 812 nsresult m_cancelStatus; 813 nsLoadFlags mLoadFlags; 814 nsCOMPtr<nsIProgressEventSink> mProgressEventSink; 815 nsCOMPtr<nsIInterfaceRequestor> mCallbacks; 816 nsCOMPtr<nsISupports> mOwner; 817 nsCOMPtr<nsISupports> mSecurityInfo; 818 nsCOMPtr<nsIRequest> 819 mCacheRequest; // the request associated with a read from the cache 820 nsCString mContentType; 821 nsCString mCharset; 822 nsWeakPtr mProtocol; 823 824 bool mChannelClosed; 825 bool mReadingFromCache; 826 bool mTryingToReadPart; 827 int64_t mContentLength; 828 829 mozilla::Monitor mSuspendedMonitor; 830 bool mSuspended; 831 832 nsresult ResumeAndNotifyOne(); 833 834 // cache related helper methods 835 nsresult OpenCacheEntry(); // makes a request to the cache service for a 836 // cache entry for a url 837 bool ReadFromLocalCache(); // attempts to read the url out of our local 838 // (offline) cache.... 839 nsresult 840 ReadFromImapConnection(); // creates a new imap connection to read the url 841 nsresult ReadFromMemCache(nsICacheEntry* entry); // attempts to read the url 842 // out of our memory cache 843 nsresult NotifyStartEndReadFromCache(bool start); 844 845 // we end up daisy chaining multiple nsIStreamListeners into the load process. 846 nsresult SetupPartExtractorListener(nsIImapUrl* aUrl, 847 nsIStreamListener* aConsumer); 848 849 uint32_t mContentDisposition; 850 }; 851 852 #endif // nsImapProtocol_h___ 853