Back to index

lightning-sunbird  0.9+nobinonly
nsMsgProtocol.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 nsMsgProtocol_h__
00039 #define nsMsgProtocol_h__
00040 
00041 #include "nsIStreamListener.h"
00042 #include "nsIInputStream.h"
00043 #include "nsIOutputStream.h"
00044 #include "nsIChannel.h"
00045 #include "nsIURL.h"
00046 #include "nsILoadGroup.h"
00047 #include "nsCOMPtr.h"
00048 #include "nsIFileSpec.h"
00049 #include "nsIInterfaceRequestor.h"
00050 #include "nsIInterfaceRequestorUtils.h"
00051 #include "nsIProgressEventSink.h"
00052 #include "nsITransport.h"
00053 #include "nsIAsyncOutputStream.h"
00054 #include "nsIEventQueue.h"
00055 #include "nsIAuthModule.h"
00056 
00057 #define UNKNOWN_ERROR             101
00058 #define UNKNOWN_HOST_ERROR        102
00059 #define CONNECTION_REFUSED_ERROR  103
00060 #define NET_TIMEOUT_ERROR         104
00061 
00062 class nsIPrompt;
00063 class nsIMsgMailNewsUrl;
00064 class nsMsgFilePostHelper;
00065 class nsIProxyInfo;
00066 
00067 #undef  IMETHOD_VISIBILITY
00068 #define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
00069 
00070 // This is a helper class used to encapsulate code shared between all of the
00071 // mailnews protocol objects (imap, news, pop, smtp, etc.) In particular,
00072 // it unifies the core networking code for the protocols. My hope is that
00073 // this will make unification with Necko easier as we'll only have to change
00074 // this class and not all of the mailnews protocols.
00075 class NS_MSG_BASE nsMsgProtocol : public nsIStreamListener
00076                                 , public nsIChannel
00077                                 , public nsITransportEventSink
00078 {
00079 public:
00080   nsMsgProtocol(nsIURI * aURL);
00081   virtual ~nsMsgProtocol();
00082 
00083   NS_DECL_ISUPPORTS
00084   // nsIChannel support
00085   NS_DECL_NSICHANNEL
00086   NS_DECL_NSIREQUEST
00087   
00088   NS_DECL_NSISTREAMLISTENER
00089   NS_DECL_NSIREQUESTOBSERVER
00090   NS_DECL_NSITRANSPORTEVENTSINK
00091 
00092   // LoadUrl -- A protocol typically overrides this function, sets up any local state for the url and
00093   // then calls the base class which opens the socket if it needs opened. If the socket is 
00094   // already opened then we just call ProcessProtocolState to start the churning process.
00095   // aConsumer is the consumer for the url. It can be null if this argument is not appropriate
00096   virtual nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer = nsnull);
00097 
00098   virtual nsresult SetUrl(nsIURI * aURL); // sometimes we want to set the url before we load it
00099 
00100   // Flag manipulators
00101   virtual PRBool TestFlag  (PRUint32 flag) {return flag & m_flags;}
00102   virtual void   SetFlag   (PRUint32 flag) { m_flags |= flag; }
00103   virtual void   ClearFlag (PRUint32 flag) { m_flags &= ~flag; }
00104 
00105 protected:
00106   // methods for opening and closing a socket with core netlib....
00107   // mscott -okay this is lame. I should break this up into a file protocol and a socket based
00108   // protocool class instead of cheating and putting both methods here...
00109 
00110   // open a connection on this url
00111   virtual nsresult OpenNetworkSocket(nsIURI * aURL,
00112                                      const char *connectionType,
00113                                      nsIInterfaceRequestor* callbacks);
00114 
00115   // open a connection with a specific host and port
00116   // aHostName must be UTF-8 encoded.
00117   virtual nsresult OpenNetworkSocketWithInfo(const char * aHostName,
00118                                              PRInt32 aGetPort,
00119                                              const char *connectionType,
00120                                              nsIProxyInfo *aProxyInfo,
00121                                              nsIInterfaceRequestor* callbacks);
00122   // helper routine
00123   nsresult GetFileFromURL(nsIURI * aURL, nsIFile **aResult);
00124   virtual nsresult OpenFileSocket(nsIURI * aURL, PRUint32 aStartPosition, PRInt32 aReadCount); // used to open a file socket connection
00125 
00126   // a Protocol typically overrides this method. They free any of their own connection state and then
00127   // they call up into the base class to free the generic connection objects
00128   virtual nsresult CloseSocket(); 
00129 
00130   virtual nsresult SetupTransportState(); // private method used by OpenNetworkSocket and OpenFileSocket
00131 
00132   // ProcessProtocolState - This is the function that gets churned by calls to OnDataAvailable. 
00133   // As data arrives on the socket, OnDataAvailable calls ProcessProtocolState.
00134   
00135   virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream, 
00136                                                                PRUint32 sourceOffset, PRUint32 length) = 0;
00137 
00138   // SendData -- Writes the data contained in dataBuffer into the current output stream. 
00139   // It also informs the transport layer that this data is now available for transmission.
00140   // Returns a positive number for success, 0 for failure (not all the bytes were written to the
00141   // stream, etc). 
00142     // aSuppressLogging is a hint that sensitive data is being sent and should not be logged
00143   virtual PRInt32 SendData(nsIURI * aURL, const char * dataBuffer, PRBool aSuppressLogging = PR_FALSE);
00144 
00145   virtual nsresult PostMessage(nsIURI* url, nsIFileSpec * fileSpec);
00146 
00147   virtual nsresult InitFromURI(nsIURI *aUrl);
00148 
00149   nsresult DoNtlmStep1(const char *username, const char *password, nsCString &response);
00150   nsresult DoNtlmStep2(nsCString &commandResponse, nsCString &response);
00151 
00152   nsresult DoGSSAPIStep1(const char *service, const char *username, nsCString &response);
00153   nsresult DoGSSAPIStep2(nsCString &commandResponse, nsCString &response);
00154   // Ouput stream for writing commands to the socket    
00155   nsCOMPtr<nsIOutputStream>   m_outputStream;   // this will be obtained from the transport interface
00156   nsCOMPtr<nsIInputStream>    m_inputStream;
00157 
00158   // Ouput stream for writing commands to the socket
00159   nsCOMPtr<nsITransport>  m_transport; 
00160   nsCOMPtr<nsIRequest>    m_request;
00161 
00162   PRBool        m_socketIsOpen; // mscott: we should look into keeping this state in the nsSocketTransport...
00163                                   // I'm using it to make sure I open the socket the first time a URL is loaded into the connection
00164   PRUint32      m_flags; // used to store flag information
00165   //PRUint32  m_startPosition;
00166   PRInt32       m_readCount;
00167 
00168   nsFileSpec  m_tempMsgFileSpec;  // we currently have a hack where displaying a msg involves writing it to a temp file first
00169 
00170   // auth module for access to NTLM functions
00171   nsCOMPtr<nsIAuthModule> m_authModule;
00172 
00173   // the following is a catch all for nsIChannel related data
00174   nsCOMPtr<nsIURI>            m_originalUrl;  // the original url
00175   nsCOMPtr<nsIURI>            m_url;          // the running url
00176   nsCOMPtr<nsIStreamListener> m_channelListener;
00177   nsCOMPtr<nsISupports>           m_channelContext;
00178   nsCOMPtr<nsILoadGroup>      m_loadGroup;
00179   nsLoadFlags                 mLoadFlags;
00180   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
00181   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
00182   nsCOMPtr<nsISupports>       mOwner;
00183   nsCString                   m_ContentType;
00184 
00185   nsCString m_lastPasswordSent; // used to prefill the password prompt
00186 
00187   // private helper routine used by subclasses to quickly get a reference to the correct prompt dialog
00188   // for a mailnews url. 
00189   nsresult GetPromptDialogFromUrl(nsIMsgMailNewsUrl * aMsgUrl, nsIPrompt ** aPromptDialog);
00190 
00191   // if a url isn't going to result in any content then we want to suppress calls to
00192   // OnStartRequest, OnDataAvailable and OnStopRequest
00193   PRBool mSuppressListenerNotifications;
00194 };
00195 
00196 
00197 // This is is a subclass of nsMsgProtocol extends the parent class with AsyncWrite support. Protocols like smtp
00198 // and news want to leverage aysnc write. We don't want everyone who inherits from nsMsgProtocol to have to
00199 // pick up the extra overhead.
00200 class NS_MSG_BASE nsMsgAsyncWriteProtocol : public nsMsgProtocol
00201 {
00202 public:
00203   NS_DECL_ISUPPORTS_INHERITED
00204 
00205   NS_IMETHOD Cancel(nsresult status);
00206 
00207   nsMsgAsyncWriteProtocol(nsIURI * aURL);
00208   virtual ~nsMsgAsyncWriteProtocol(); 
00209   
00210   // temporary over ride...
00211   virtual nsresult PostMessage(nsIURI* url, nsIFileSpec *fileSpec);
00212   
00213   // over ride the following methods from the base class
00214   virtual nsresult SetupTransportState();
00215   virtual PRInt32 SendData(nsIURI * aURL, const char * dataBuffer, PRBool aSuppressLogging = PR_FALSE);
00216    
00217   // if we suspended the asynch write while waiting for more data to write then this will be TRUE
00218   PRBool mSuspendedWrite;
00219   nsCOMPtr<nsIRequest>     m_WriteRequest;
00220   nsCOMPtr<nsIAsyncOutputStream>    mAsyncOutStream;
00221   nsCOMPtr<nsIOutputStreamCallback> mProvider;
00222   nsCOMPtr<nsIEventQueue>           mProviderEventQ;
00223 
00224   // because we are reading the post data in asychronously, it's possible that we aren't sending it 
00225   // out fast enough and the reading gets blocked. The following set of state variables are used to 
00226   // track this.
00227   PRBool  mSuspendedRead;
00228   PRBool  mInsertPeriodRequired; // do we need to insert a '.' as part of the unblocking process
00229    
00230   nsresult ProcessIncomingPostData(nsIInputStream *inStr, PRUint32 count);
00231   nsresult UnblockPostReader();
00232   nsresult UpdateSuspendedReadBytes(PRUint32 aNewBytes, PRBool aAddToPostPeriodByteCount);
00233   nsresult PostDataFinished(); // this is so we'll send out a closing '.' and release any state related to the post
00234 
00235 
00236   // these two routines are used to pause and resume our loading of the file containing the contents
00237   // we are trying to post. We call these routines when we aren't sending the bits out fast enough
00238   // to keep up with the file read. 
00239   nsresult SuspendPostFileRead();
00240   nsresult ResumePostFileRead(); 
00241   nsresult UpdateSuspendedReadBytes(PRUint32 aNewBytes); 
00242   void UpdateProgress(PRUint32 aNewBytes);
00243   nsMsgFilePostHelper * mFilePostHelper; // needs to be a weak reference
00244 protected:
00245   // the streams for the pipe used to queue up data for the async write calls to the server.
00246   // we actually re-use the same mOutStream variable in our parent class for the output
00247   // stream to the socket channel. So no need for a new variable here.
00248   nsCOMPtr<nsIInputStream>  mInStream;    
00249   nsCOMPtr<nsIInputStream>  mPostDataStream;
00250   PRUint32                  mSuspendedReadBytes;   // remaining # of bytes we need to read before   
00251                                                    // the input stream becomes unblocked
00252   PRUint32                  mSuspendedReadBytesPostPeriod; // # of bytes which need processed after we insert a '.' before 
00253                                                            // the input stream becomes unblocked.
00254   PRUint32  mFilePostSize; // used for determining progress on posting files.
00255   PRUint32  mNumBytesPosted; // used for deterimining progress on posting files 
00256   PRBool    mGenerateProgressNotifications; // set during a post operation after we've started sending the post data...
00257 
00258   virtual nsresult CloseSocket(); 
00259 };
00260 
00261 #undef  IMETHOD_VISIBILITY
00262 #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
00263 
00264 #endif /* nsMsgProtocol_h__ */