diff options
Diffstat (limited to 'mailnews/local/src/nsPop3Protocol.h')
-rw-r--r-- | mailnews/local/src/nsPop3Protocol.h | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/mailnews/local/src/nsPop3Protocol.h b/mailnews/local/src/nsPop3Protocol.h new file mode 100644 index 000000000..a937427d1 --- /dev/null +++ b/mailnews/local/src/nsPop3Protocol.h @@ -0,0 +1,402 @@ +/* -*- 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 nsPop3Protocol_h__ +#define nsPop3Protocol_h__ + +#include "mozilla/Attributes.h" +#include "nsIStreamListener.h" +#include "nsIOutputStream.h" +#include "nsIInputStream.h" +#include "nsIPop3URL.h" +#include "nsIPop3Sink.h" +#include "nsMsgLineBuffer.h" +#include "nsMsgProtocol.h" +#include "nsIPop3Protocol.h" +#include "MailNewsTypes.h" +#include "nsIStringBundle.h" +#include "nsIMsgStatusFeedback.h" +#include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... +#include "nsIAuthModule.h" +#include "nsITimer.h" +#include "nsIMsgAsyncPrompter.h" + +#include "prerror.h" +#include "plhash.h" +#include "nsCOMPtr.h" + +/* A more guaranteed way of making sure that we never get duplicate messages +is to always get each message's UIDL (if the server supports it) +and use these for storing up deletes which were not committed on the +server. Based on our experience, it looks like we do NOT need to +do this (it has performance tradeoffs, etc.). To turn it on, three +things need to happen: #define POP_ALWAYS_USE_UIDL_FOR_DUPLICATES, verify that +the uidl's are correctly getting added when the delete response is received, +and change the POP3_QUIT_RESPONSE state to flush the newly committed deletes. */ + +/* + * Cannot have the following line uncommented. It is defined. + * #ifdef POP_ALWAYS_USE_UIDL_FOR_DUPLICATES will always be evaluated + * as true. + * +#define POP_ALWAYS_USE_UIDL_FOR_DUPLICATES 0 + * + */ + +#define MK_OUT_OF_MEMORY -207 +#define MK_POP3_PASSWORD_UNDEFINED -313 +#define XP_NO_ANSWER 14401 +#define XP_THE_PREVIOUSLY_ENTERED_PASSWORD_IS_INVALID_ETC 14405 +#define XP_PASSWORD_FOR_POP3_USER 14590 + +#define OUTPUT_BUFFER_SIZE 8192 // maximum size of command string + +/* structure to hold data pertaining to the active state of + * a transfer in progress. + * + */ + +enum Pop3CapabilityEnum { + POP3_CAPABILITY_UNDEFINED = 0x00000000, + POP3_HAS_XSENDER = 0x00000001, + POP3_GURL_UNDEFINED = 0x00000002, + POP3_HAS_GURL = 0x00000004, + POP3_UIDL_UNDEFINED = 0x00000008, + POP3_HAS_UIDL = 0x00000010, + POP3_XTND_XLST_UNDEFINED = 0x00000020, + POP3_HAS_XTND_XLST = 0x00000040, + POP3_TOP_UNDEFINED = 0x00000080, + POP3_HAS_TOP = 0x00000100, + POP3_AUTH_MECH_UNDEFINED = 0x00000200, + POP3_HAS_AUTH_USER = 0x00000400, + POP3_HAS_AUTH_LOGIN = 0x00000800, + POP3_HAS_AUTH_PLAIN = 0x00001000, + POP3_HAS_AUTH_CRAM_MD5 = 0x00002000, + POP3_HAS_AUTH_APOP = 0x00004000, + POP3_HAS_AUTH_NTLM = 0x00008000, + POP3_HAS_AUTH_MSN = 0x00010000, + POP3_HAS_RESP_CODES = 0x00020000, + POP3_HAS_AUTH_RESP_CODE = 0x00040000, + POP3_HAS_STLS = 0x00080000, + POP3_HAS_AUTH_GSSAPI = 0x00100000 +}; + +// TODO use value > 0? +#define POP3_HAS_AUTH_NONE 0 +#define POP3_HAS_AUTH_ANY 0x00001C00 +#define POP3_HAS_AUTH_ANY_SEC 0x0011E000 + +enum Pop3StatesEnum { + POP3_READ_PASSWORD, // 0 + // + POP3_START_CONNECT, // 1 + POP3_FINISH_CONNECT, // 2 + POP3_WAIT_FOR_RESPONSE, // 3 + POP3_WAIT_FOR_START_OF_CONNECTION_RESPONSE, // 4 + POP3_SEND_USERNAME, // 5 + + POP3_SEND_PASSWORD, // 6 + POP3_SEND_STAT, // 7 + POP3_GET_STAT, // 8 + POP3_SEND_LIST, // 9 + POP3_GET_LIST, // 10 + + POP3_SEND_UIDL_LIST, // 11 + POP3_GET_UIDL_LIST, // 12 + POP3_SEND_XTND_XLST_MSGID, // 13 + POP3_GET_XTND_XLST_MSGID, // 14 + POP3_GET_MSG, // 15 + + POP3_SEND_TOP, // 16 + POP3_TOP_RESPONSE, // 17 + POP3_SEND_RETR, // 18 + POP3_RETR_RESPONSE, // 19 + POP3_SEND_DELE, // 20 + + POP3_DELE_RESPONSE, // 21 + POP3_SEND_QUIT, // 22 + POP3_DONE, // 23 + POP3_ERROR_DONE, // 24 + POP3_FREE, // 25 + POP3_SEND_AUTH, // 26 + POP3_AUTH_RESPONSE, // 27 + POP3_SEND_CAPA, // 28 + POP3_CAPA_RESPONSE, // 29 + POP3_PROCESS_AUTH, // 30 + POP3_NEXT_AUTH_STEP, // 31 + + POP3_AUTH_LOGIN, // 32 + POP3_AUTH_LOGIN_RESPONSE, // 33 + POP3_AUTH_NTLM, // 34 + POP3_AUTH_NTLM_RESPONSE, // 35 + POP3_SEND_XSENDER, // 36 + POP3_XSENDER_RESPONSE, // 37 + POP3_SEND_GURL, // 38 + + POP3_GURL_RESPONSE, // 39 + POP3_QUIT_RESPONSE, // 40 + POP3_TLS_RESPONSE, // 41 + + POP3_AUTH_GSSAPI, // 42 + POP3_AUTH_GSSAPI_FIRST, // 43 + POP3_AUTH_GSSAPI_STEP, // 44 + + /** + * Async wait to obtain the password and deal with the result. + * The *PREOBTAIN* states are used for where we try and get the password + * before we've initiated a connection to the server. + */ + POP3_OBTAIN_PASSWORD_EARLY, // 45 + POP3_FINISH_OBTAIN_PASSWORD_EARLY, // 46 + POP3_OBTAIN_PASSWORD_BEFORE_USERNAME, // 47 + POP3_FINISH_OBTAIN_PASSWORD_BEFORE_USERNAME,// 48 + POP3_OBTAIN_PASSWORD_BEFORE_PASSWORD, // 49 + POP3_FINISH_OBTAIN_PASSWORD_BEFORE_PASSWORD // 50 +}; + + +#define KEEP 'k' /* If we want to keep this item on server. */ +#define DELETE_CHAR 'd' /* If we want to delete this item. */ +#define TOO_BIG 'b' /* item left on server because it was too big */ +#define FETCH_BODY 'f' /* Fetch full body of a partial msg */ + +typedef struct Pop3UidlEntry { /* information about this message */ + char* uidl; + char status; // KEEP=='k', DELETE='d' TOO_BIG='b' FETCH_BODY='f' + uint32_t dateReceived; // time message received, used for aging +} Pop3UidlEntry; + +typedef struct Pop3UidlHost { + char* host; + char* user; + PLHashTable * hash; + Pop3UidlEntry* uidlEntries; + struct Pop3UidlHost* next; +} Pop3UidlHost; + +typedef struct Pop3MsgInfo { + int32_t msgnum; + int32_t size; + char* uidl; +} Pop3MsgInfo; + +typedef struct _Pop3ConData { + bool leave_on_server; /* Whether we're supposed to leave messages + on server. */ + bool headers_only; /* Whether to just fetch headers on initial + downloads. */ + int32_t size_limit; /* Leave messages bigger than this on the + server and only download a partial + message. */ + uint32_t capability_flags; /* What capability this server has? */ + + Pop3StatesEnum next_state; /* the next state or action to be taken */ + Pop3StatesEnum next_state_after_response; + bool pause_for_read; /* Pause now for next read? */ + + bool command_succeeded; /* did the last command succeed? */ + bool list_done; /* did we get the complete list of msgIDs? */ + int32_t first_msg; + + uint32_t obuffer_size; + uint32_t obuffer_fp; + + int32_t really_new_messages; + int32_t real_new_counter; + int32_t number_of_messages; + Pop3MsgInfo *msg_info; /* Message sizes and uidls (used only if we + are playing games that involve leaving + messages on the server). */ + int32_t last_accessed_msg; + int32_t cur_msg_size; + bool truncating_cur_msg; /* are we using top and uidl? */ + bool msg_del_started; /* True if MSG_BeginMailDel... + * called + */ + bool only_check_for_new_mail; + nsMsgBiffState biffstate; /* If just checking for, what the answer is. */ + + bool verify_logon; /* true if we're just seeing if we can logon */ + + void *msg_closure; + + bool graph_progress_bytes_p; /* whether we should display info about + the bytes transferred (usually we + display info about the number of + messages instead.) */ + + Pop3UidlHost *uidlinfo; + PLHashTable *newuidl; + char *only_uidl; /* If non-NULL, then load only this UIDL. */ + + bool get_url; + bool seenFromHeader; + int32_t parsed_bytes; + int32_t pop3_size; + bool dot_fix; + bool assumed_end; + nsresult urlStatus; +} Pop3ConData; + +// 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) +#define POP3_PAUSE_FOR_READ 0x00000001 /* should we pause for the next read */ +#define POP3_PASSWORD_FAILED 0x00000002 +#define POP3_STOPLOGIN 0x00000004 /* error loging in, so stop here */ +#define POP3_AUTH_FAILURE 0x00000008 /* extended code said authentication failed */ + + +class nsPop3Protocol : public nsMsgProtocol, + public nsIPop3Protocol, + public nsIMsgAsyncPromptListener +{ +public: + nsPop3Protocol(nsIURI* aURL); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIPOP3PROTOCOL + NS_DECL_NSIMSGASYNCPROMPTLISTENER + + nsresult Initialize(nsIURI * aURL); + virtual nsresult LoadUrl(nsIURI *aURL, nsISupports * aConsumer = nullptr) override; + void Cleanup(); + + const char* GetUsername() { return m_username.get(); } + void SetUsername(const char* name); + + nsresult StartGetAsyncPassword(Pop3StatesEnum aNextState); + + NS_IMETHOD OnTransportStatus(nsITransport *transport, nsresult status, int64_t progress, int64_t progressMax) override; + NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports * aContext, nsresult aStatus) override; + NS_IMETHOD Cancel(nsresult status) override; + + static void MarkMsgInHashTable(PLHashTable *hashTable, const Pop3UidlEntry *uidl, + bool *changed); + + static nsresult MarkMsgForHost(const char *hostName, const char *userName, + nsIFile *mailDirectory, + nsTArray<Pop3UidlEntry*> &UIDLArray); +private: + virtual ~nsPop3Protocol(); + nsCString m_ApopTimestamp; + nsCOMPtr<nsIStringBundle> mLocalBundle; + + nsCString m_username; + nsCString m_senderInfo; + nsCString m_commandResponse; + nsCString m_GSSAPICache; + + // Used for asynchronous password prompts to store the password temporarily. + nsCString m_passwordResult; + + // progress state information + void UpdateProgressPercent(int64_t totalDone, int64_t total); + void UpdateStatus(const char16_t *aStatusName); + void UpdateStatusWithString(const char16_t *aString); + nsresult FormatCounterString(const nsString &stringName, + uint32_t count1, + uint32_t count2, + nsString &resultString); + + int32_t m_bytesInMsgReceived; + int64_t m_totalFolderSize; + int64_t m_totalDownloadSize; /* Number of bytes we're going to + download. Might be much less + than the total_folder_size. */ + int64_t m_totalBytesReceived; // total # bytes received for the connection + + virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream, + uint64_t sourceOffset, uint32_t length) override; + virtual int32_t Pop3SendData(const char * dataBuffer, bool aSuppressLogging = false); + + virtual const char* GetType() override {return "pop3";} + + nsCOMPtr<nsIURI> m_url; + nsCOMPtr<nsIPop3Sink> m_nsIPop3Sink; + nsCOMPtr<nsIPop3IncomingServer> m_pop3Server; + + nsMsgLineStreamBuffer * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream + Pop3ConData* m_pop3ConData; + void FreeMsgInfo(); + void Abort(); + + bool m_tlsEnabled; + int32_t m_socketType; + bool m_password_already_sent; + bool m_needToRerunUrl; + + void SetCapFlag(uint32_t flag); + void ClearCapFlag(uint32_t flag); + bool TestCapFlag(uint32_t flag); + uint32_t GetCapFlags(); + + void InitPrefAuthMethods(int32_t authMethodPrefValue); + nsresult ChooseAuthMethod(); + void MarkAuthMethodAsFailed(int32_t failedAuthMethod); + void ResetAuthMethods(); + int32_t m_prefAuthMethods; // set of capability flags for auth methods + int32_t m_failedAuthMethods; // ditto + int32_t m_currentAuthMethod; // exactly one capability flag, or 0 + + int32_t m_listpos; + + nsresult HandleLine(char *line, uint32_t line_length); + + nsresult GetApopTimestamp(); + + ////////////////////////////////////////////////////////////////////////////////////////// + // Begin Pop3 protocol state handlers + ////////////////////////////////////////////////////////////////////////////////////////// + int32_t WaitForStartOfConnectionResponse(nsIInputStream* inputStream, + uint32_t length); + int32_t WaitForResponse(nsIInputStream* inputStream, + uint32_t length); + int32_t Error(const char* err_code, const char16_t **params = nullptr, + uint32_t length = 0); + int32_t SendAuth(); + int32_t AuthResponse(nsIInputStream* inputStream, uint32_t length); + int32_t SendCapa(); + int32_t CapaResponse(nsIInputStream* inputStream, uint32_t length); + int32_t SendTLSResponse(); + int32_t ProcessAuth(); + int32_t NextAuthStep(); + int32_t AuthLogin(); + int32_t AuthLoginResponse(); + int32_t AuthNtlm(); + int32_t AuthNtlmResponse(); + int32_t AuthGSSAPI(); + int32_t AuthGSSAPIResponse(bool first); + int32_t SendUsername(); + int32_t SendPassword(); + int32_t SendStatOrGurl(bool sendStat); + int32_t SendStat(); + int32_t GetStat(); + int32_t SendGurl(); + int32_t GurlResponse(); + int32_t SendList(); + int32_t GetList(nsIInputStream* inputStream, uint32_t length); + int32_t HandleNoUidListAvailable(); + int32_t SendXtndXlstMsgid(); + int32_t GetXtndXlstMsgid(nsIInputStream* inputStream, uint32_t length); + int32_t SendUidlList(); + int32_t GetUidlList(nsIInputStream* inputStream, uint32_t length); + int32_t GetMsg(); + int32_t SendTop(); + int32_t SendXsender(); + int32_t XsenderResponse(); + int32_t SendRetr(); + + int32_t RetrResponse(nsIInputStream* inputStream, uint32_t length); + int32_t TopResponse(nsIInputStream* inputStream, uint32_t length); + int32_t SendDele(); + int32_t DeleResponse(); + int32_t CommitState(bool remove_last_entry); + + Pop3StatesEnum GetNextPasswordObtainState(); + nsresult RerunUrl(); +}; + +#endif /* nsPop3Protocol_h__ */ |