summaryrefslogtreecommitdiff
path: root/mailnews/local/src/nsPop3Protocol.h
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/local/src/nsPop3Protocol.h')
-rw-r--r--mailnews/local/src/nsPop3Protocol.h402
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 0000000000..a937427d1e
--- /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__ */