Back to index

lightning-sunbird  0.9+nobinonly
nsPop3Protocol.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef nsPop3Protocol_h__
00039 #define nsPop3Protocol_h__
00040 
00041 #include "nsIStreamListener.h"
00042 #include "nsIOutputStream.h"
00043 #include "nsIInputStream.h"
00044 #include "nsIPop3URL.h"
00045 #include "nsIPop3Sink.h"
00046 #include "nsMsgLineBuffer.h"
00047 #include "nsMsgProtocol.h"
00048 #include "nsIPop3Protocol.h"
00049 #include "MailNewsTypes.h"
00050 #include "nsLocalStringBundle.h"
00051 #include "nsIMsgStatusFeedback.h"
00052 #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
00053 #include "nsIAuthModule.h"
00054 #include "nsITimer.h"
00055 
00056 #include "prerror.h"
00057 #include "plhash.h"
00058 #include "nsCOMPtr.h"
00059 
00060 /* A more guaranteed way of making sure that we never get duplicate messages
00061 is to always get each message's UIDL (if the server supports it)
00062 and use these for storing up deletes which were not committed on the
00063 server.  Based on our experience, it looks like we do NOT need to
00064 do this (it has performance tradeoffs, etc.).  To turn it on, three
00065 things need to happen: #define POP_ALWAYS_USE_UIDL_FOR_DUPLICATES, verify that
00066 the uidl's are correctly getting added when the delete response is received,
00067 and change the POP3_QUIT_RESPONSE state to flush the newly committed deletes. */
00068 
00069 /* 
00070  * Cannot have the following line uncommented. It is defined.
00071  * #ifdef POP_ALWAYS_USE_UIDL_FOR_DUPLICATES will always be evaluated
00072  * as PR_TRUE.
00073  *
00074 #define POP_ALWAYS_USE_UIDL_FOR_DUPLICATES 0
00075  *
00076  */
00077 
00078 #define MK_OUT_OF_MEMORY -207
00079 #define MK_POP3_OUT_OF_DISK_SPACE -321
00080 #define MK_POP3_PASSWORD_UNDEFINED -313
00081 #define XP_NO_ANSWER 14401
00082 #define XP_THE_PREVIOUSLY_ENTERED_PASSWORD_IS_INVALID_ETC 14405
00083 #define XP_PASSWORD_FOR_POP3_USER 14590
00084 
00085 #define OUTPUT_BUFFER_SIZE 8192 // maximum size of command string
00086 
00087 /* structure to hold data pertaining to the active state of
00088  * a transfer in progress.
00089  *
00090  */
00091 
00092 enum Pop3CapabilityEnum {
00093     POP3_CAPABILITY_UNDEFINED   = 0x00000000,
00094     POP3_HAS_XSENDER            = 0x00000001,
00095     POP3_GURL_UNDEFINED         = 0x00000002,
00096     POP3_HAS_GURL               = 0x00000004,
00097     POP3_UIDL_UNDEFINED         = 0x00000008,
00098     POP3_HAS_UIDL               = 0x00000010,
00099     POP3_XTND_XLST_UNDEFINED    = 0x00000020,
00100     POP3_HAS_XTND_XLST          = 0x00000040,
00101     POP3_TOP_UNDEFINED          = 0x00000080,
00102     POP3_HAS_TOP                = 0x00000100,
00103     POP3_AUTH_MECH_UNDEFINED    = 0x00000200,
00104     POP3_HAS_AUTH_USER          = 0x00000400,
00105     POP3_HAS_AUTH_LOGIN         = 0x00000800,
00106     POP3_HAS_AUTH_PLAIN         = 0x00001000,
00107     POP3_HAS_AUTH_CRAM_MD5      = 0x00002000,
00108     POP3_HAS_AUTH_APOP          = 0x00004000,
00109     POP3_HAS_AUTH_NTLM          = 0x00008000,
00110     POP3_HAS_AUTH_MSN           = 0x00010000,
00111     POP3_HAS_RESP_CODES         = 0x00020000,
00112     POP3_HAS_AUTH_RESP_CODE     = 0x00040000,
00113     POP3_HAS_STLS               = 0x00080000,
00114     POP3_HAS_AUTH_GSSAPI        = 0x00100000
00115 };
00116 
00117 #define POP3_HAS_AUTH_ANY         0x00001C00
00118 #define POP3_HAS_AUTH_ANY_SEC     0x0011E000
00119 
00120 enum Pop3StatesEnum {
00121     POP3_READ_PASSWORD,                         // 0
00122                                                 // 
00123     POP3_START_CONNECT,                         // 1
00124     POP3_FINISH_CONNECT,                        // 2
00125     POP3_WAIT_FOR_RESPONSE,                     // 3
00126     POP3_WAIT_FOR_START_OF_CONNECTION_RESPONSE, // 4
00127     POP3_SEND_USERNAME,                         // 5
00128 
00129     POP3_SEND_PASSWORD,                         // 6
00130     POP3_SEND_STAT,                             // 7
00131     POP3_GET_STAT,                              // 8
00132     POP3_SEND_LIST,                             // 9
00133     POP3_GET_LIST,                              // 10
00134 
00135     POP3_SEND_UIDL_LIST,                        // 11
00136     POP3_GET_UIDL_LIST,                         // 12
00137     POP3_SEND_XTND_XLST_MSGID,                  // 13
00138     POP3_GET_XTND_XLST_MSGID,                   // 14
00139     POP3_GET_MSG,                               // 15
00140 
00141     POP3_SEND_TOP,                              // 16
00142     POP3_TOP_RESPONSE,                          // 17
00143     POP3_SEND_RETR,                             // 18
00144     POP3_RETR_RESPONSE,                         // 19
00145     POP3_SEND_DELE,                             // 20
00146 
00147     POP3_DELE_RESPONSE,                         // 21
00148     POP3_SEND_QUIT,                             // 22
00149     POP3_DONE,                                  // 23
00150     POP3_ERROR_DONE,                            // 24
00151     POP3_FREE,                                  // 25
00152     /* The following 3 states support the use of the 'TOP' command instead of UIDL
00153        for leaving mail on the pop server -km */
00154     POP3_START_USE_TOP_FOR_FAKE_UIDL,           // 26
00155     POP3_SEND_FAKE_UIDL_TOP,                    // 27
00156     POP3_GET_FAKE_UIDL_TOP,                     // 28
00157     POP3_SEND_AUTH,                             // 29
00158     POP3_AUTH_RESPONSE,                         // 30
00159     POP3_SEND_CAPA,                             // 31
00160     POP3_CAPA_RESPONSE,                         // 32
00161     POP3_PROCESS_AUTH,                          // 33
00162     POP3_AUTH_FALLBACK,                         // 34
00163 
00164     POP3_AUTH_LOGIN,                            // 35
00165     POP3_AUTH_LOGIN_RESPONSE,                   // 36
00166     POP3_AUTH_NTLM,                             // 37
00167     POP3_AUTH_NTLM_RESPONSE,                    // 38
00168     POP3_SEND_XSENDER,                          // 39
00169     POP3_XSENDER_RESPONSE,                      // 40
00170     POP3_SEND_GURL,                             // 41
00171 
00172     POP3_GURL_RESPONSE,                         // 42
00173     POP3_QUIT_RESPONSE,                         // 43
00174     POP3_INTERRUPTED,                           // 44
00175     POP3_TLS_RESPONSE,                          // 45
00176     
00177     POP3_AUTH_GSSAPI,                           // 46
00178     POP3_AUTH_GSSAPI_FIRST,                     // 47
00179     POP3_AUTH_GSSAPI_STEP                       // 48
00180 };
00181 
00182 
00183 #define KEEP        'k'         /* If we want to keep this item on server. */
00184 #define DELETE_CHAR 'd'         /* If we want to delete this item. */
00185 #define TOO_BIG     'b'         /* item left on server because it was too big */
00186 #define FETCH_BODY  'f'         /* Fetch full body of a partial msg */
00187 
00188 typedef struct Pop3UidlEntry { /* information about this message */
00189     char* uidl;
00190     char  status; // KEEP=='k', DELETE='d' TOO_BIG='b' FETCH_BODY='f'
00191     PRInt32 dateReceived; // time message received, used for aging
00192 } Pop3UidlEntry;
00193 
00194 typedef struct Pop3UidlHost {
00195     char* host;
00196     char* user;
00197     PLHashTable * hash;
00198     Pop3UidlEntry* uidlEntries;
00199     struct Pop3UidlHost* next;
00200 } Pop3UidlHost;
00201 
00202 typedef struct Pop3MsgInfo {
00203     PRInt32 msgnum;
00204     PRInt32 size;
00205     char* uidl;
00206 } Pop3MsgInfo;
00207 
00208 typedef struct _Pop3ConData {
00209     PRBool leave_on_server;     /* Whether we're supposed to leave messages
00210                                    on server. */
00211     PRBool headers_only;        /* Whether to just fetch headers on initial
00212                                    downloads. */
00213     PRInt32 size_limit;         /* Leave messages bigger than this on the
00214                                    server and only download a partial
00215                                    message. */
00216     PRUint32 capability_flags; /* What capability this server has? */
00217     
00218     Pop3StatesEnum next_state;  /* the next state or action to be taken */
00219     Pop3StatesEnum next_state_after_response;  
00220     PRBool pause_for_read;                /* Pause now for next read? */
00221     
00222     PRBool command_succeeded;   /* did the last command succeed? */
00223     PRBool list_done;              /* did we get the complete list of msgIDs? */
00224     PRInt32 first_msg;
00225 
00226     PRUint32 obuffer_size;
00227     PRUint32 obuffer_fp;
00228     
00229     PRInt32   really_new_messages;
00230     PRInt32   real_new_counter;
00231     PRInt32 number_of_messages;
00232     Pop3MsgInfo      *msg_info;      /* Message sizes and uidls (used only if we
00233                                    are playing games that involve leaving
00234                                    messages on the server). */
00235     PRInt32 last_accessed_msg;
00236     PRInt32 cur_msg_size;
00237     PRBool truncating_cur_msg;  /* are we using top and uidl? */
00238     PRBool msg_del_started;     /* True if MSG_BeginMailDel...
00239                                  * called
00240                                  */
00241     PRBool only_check_for_new_mail;
00242     nsMsgBiffState biffstate;     /* If just checking for, what the answer is. */
00243     
00244     void *msg_closure;
00245     
00246     PRBool graph_progress_bytes_p; /* whether we should display info about
00247                                       the bytes transferred (usually we
00248                                       display info about the number of
00249                                       messages instead.) */
00250     
00251     Pop3UidlHost *uidlinfo;
00252     PLHashTable *newuidl;
00253     char *only_uidl;            /* If non-NULL, then load only this UIDL. */
00254     
00255     /* the following three fields support the 
00256        use of the 'TOP' command instead of UIDL
00257        for leaving mail on the pop server -km */
00258     
00259     /* the current message that we are retrieving 
00260        with the TOP command */
00261     PRInt32 current_msg_to_top;    
00262 
00263     /* we will download this many in 
00264        POP3_GET_MSG */
00265     PRInt32 number_of_messages_not_seen_before;
00266     /* reached when we have TOPped 
00267        all of the new messages */
00268     PRBool found_new_message_boundary; 
00269     
00270     /* if this is true then we don't stop 
00271        at new message boundary, we have to 
00272        TOP em all to delete some */
00273     PRBool delete_server_message_during_top_traversal;
00274     PRBool get_url;
00275     PRBool seenFromHeader;
00276     PRInt32 parsed_bytes;
00277     PRInt32 pop3_size;
00278     PRBool dot_fix;
00279     PRBool assumed_end;
00280     PRInt32 logonFailureCount;
00281 } Pop3ConData;
00282 
00283 // State Flags (Note, I use the word state in terms of storing 
00284 // state information about the connection (authentication, have we sent
00285 // commands, etc. I do not intend it to refer to protocol state)
00286 #define POP3_PAUSE_FOR_READ               0x00000001  /* should we pause for the next read */
00287 #define POP3_PASSWORD_FAILED              0x00000002
00288 #define POP3_STOPLOGIN              0x00000004  /* error loging in, so stop here */
00289 #define POP3_AUTH_FAILURE           0x00000008  /* extended code said authentication failed */
00290 
00291 
00292 class nsPop3Protocol : public nsMsgProtocol, public nsIPop3Protocol
00293 {
00294 public:
00295   nsPop3Protocol(nsIURI* aURL);  
00296   virtual ~nsPop3Protocol();
00297   
00298   NS_DECL_ISUPPORTS_INHERITED
00299   NS_DECL_NSIPOP3PROTOCOL
00300 
00301   nsresult Initialize(nsIURI * aURL);
00302   virtual nsresult LoadUrl(nsIURI *aURL, nsISupports * aConsumer = nsnull);
00303 
00304   const char* GetUsername() { return m_username.get(); };
00305   void SetUsername(const char* name);
00306 
00307   nsresult GetPassword(char ** aPassword, PRBool *okayValue);
00308 
00309   NS_IMETHOD OnTransportStatus(nsITransport *transport, nsresult status, PRUint32 progress, PRUint32 progressMax);
00310   NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports * aContext, nsresult aStatus);
00311   NS_IMETHOD Cancel(nsresult status);
00312 
00313   static void MarkMsgInHashTable(PLHashTable *hashTable, const Pop3UidlEntry *uidl, 
00314                                   PRBool *changed);
00315 
00316   static nsresult MarkMsgForHost(const char *hostName, const char *userName,
00317                                       nsIFileSpec *mailDirectory, 
00318                                       nsVoidArray  &UIDLArray);
00319 private:
00320   nsCString m_ApopTimestamp;
00321   nsCOMPtr<nsIMsgStringService> mStringService;
00322 
00323   nsCString m_username;
00324   nsCString m_senderInfo;
00325   nsCString m_commandResponse;
00326   nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
00327   nsCString m_GSSAPICache;
00328 
00329   // progress state information
00330   void UpdateProgressPercent (PRUint32 totalDone, PRUint32 total);
00331   void UpdateStatus(PRInt32 aStatusID);
00332   void UpdateStatusWithString(const PRUnichar * aString);
00333 
00334   PRInt32     m_bytesInMsgReceived; 
00335   PRInt32     m_totalFolderSize;    
00336   PRInt32     m_totalDownloadSize; /* Number of bytes we're going to
00337                                     download.  Might be much less
00338                                     than the total_folder_size. */
00339   PRInt32 m_totalBytesReceived; // total # bytes received for the connection
00340 
00341   virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream, 
00342                                         PRUint32 sourceOffset, PRUint32 length);
00343   virtual nsresult CloseSocket();
00344   virtual PRInt32 SendData(nsIURI * aURL, const char * dataBuffer, PRBool aSuppressLogging = PR_FALSE);
00345 
00346   nsCOMPtr<nsIURI> m_url;
00347   nsCOMPtr<nsIPop3Sink> m_nsIPop3Sink;
00348   nsCOMPtr<nsIPop3IncomingServer> m_pop3Server;
00349 
00350   nsMsgLineStreamBuffer   * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
00351   Pop3ConData* m_pop3ConData;
00352   void FreeMsgInfo();
00353   void Abort();
00354 
00355   PRBool m_parsingMultiLineMessageId;
00356 
00357   PRBool m_tlsEnabled;
00358   PRInt32 m_socketType;
00359   PRBool m_useSecAuth;
00360   PRBool m_password_already_sent;
00361 
00362   void SetCapFlag(PRUint32 flag);
00363   void ClearCapFlag(PRUint32 flag);
00364   PRBool TestCapFlag(PRUint32 flag);
00365 
00366   void BackupAuthFlags();
00367   void RestoreAuthFlags();
00368   PRInt32 m_origAuthFlags;
00369   PRInt32 m_listpos;
00370 
00371   nsresult HandleLine(char *line, PRUint32 line_length);
00372 
00373   nsresult GetApopTimestamp();
00374 
00376       // Begin Pop3 protocol state handlers
00378   PRInt32 WaitForStartOfConnectionResponse(nsIInputStream* inputStream, 
00379                                            PRUint32 length);
00380   PRInt32 WaitForResponse(nsIInputStream* inputStream, 
00381                           PRUint32 length);
00382   PRInt32 Error(PRInt32 err_code);
00383   PRInt32 SendAuth();
00384   PRInt32 AuthResponse(nsIInputStream* inputStream, PRUint32 length);
00385   PRInt32 SendCapa();
00386   PRInt32 CapaResponse(nsIInputStream* inputStream, PRUint32 length);
00387   PRInt32 SendTLSResponse();
00388   PRInt32 ProcessAuth();
00389   PRInt32 AuthFallback();
00390   PRInt32 AuthLogin();
00391   PRInt32 AuthLoginResponse();
00392   PRInt32 AuthNtlm();
00393   PRInt32 AuthNtlmResponse();
00394   PRInt32 AuthGSSAPI();
00395   PRInt32 AuthGSSAPIResponse(PRBool first);
00396   PRInt32 SendUsername();
00397   PRInt32 SendPassword();
00398   PRInt32 SendStatOrGurl(PRBool sendStat);
00399   PRInt32 SendStat();
00400   PRInt32 GetStat();
00401   PRInt32 SendGurl();
00402   PRInt32 GurlResponse();
00403   PRInt32 SendList();
00404   PRInt32 GetList(nsIInputStream* inputStream, PRUint32 length);
00405   PRInt32 SendFakeUidlTop();
00406   PRInt32 StartUseTopForFakeUidl();
00407   PRInt32 GetFakeUidlTop(nsIInputStream* inputStream, PRUint32 length);
00408   PRInt32 SendXtndXlstMsgid();
00409   PRInt32 GetXtndXlstMsgid(nsIInputStream* inputStream, PRUint32 length);
00410   PRInt32 SendUidlList();
00411   PRInt32 GetUidlList(nsIInputStream* inputStream, PRUint32 length);
00412   PRInt32 GetMsg();
00413   PRInt32 SendTop();
00414   PRInt32 SendXsender();
00415   PRInt32 XsenderResponse();
00416   PRInt32 SendRetr();
00417 
00418   PRInt32 RetrResponse(nsIInputStream* inputStream, PRUint32 length);
00419   PRInt32 TopResponse(nsIInputStream* inputStream, PRUint32 length);
00420   PRInt32 SendDele();
00421   PRInt32 DeleResponse();
00422   PRInt32 CommitState(PRBool remove_last_entry);
00423 };
00424 
00425 #endif /* nsPop3Protocol_h__ */