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 nsMsgProtocol_h__ 7 #define nsMsgProtocol_h__ 8 9 #include "mozilla/Attributes.h" 10 #include "nsIStreamListener.h" 11 #include "nsIInputStream.h" 12 #include "nsIOutputStream.h" 13 #include "nsIChannel.h" 14 #include "nsIURL.h" 15 #include "nsIThread.h" 16 #include "nsILoadGroup.h" 17 #include "nsIFile.h" 18 #include "nsCOMPtr.h" 19 #include "nsIInterfaceRequestor.h" 20 #include "nsIInterfaceRequestorUtils.h" 21 #include "nsIProgressEventSink.h" 22 #include "nsITransport.h" 23 #include "nsIAsyncOutputStream.h" 24 #include "nsIAuthModule.h" 25 #include "nsString.h" 26 #include "nsWeakReference.h" 27 #include "nsHashPropertyBag.h" 28 29 class nsIMsgWindow; 30 class nsIPrompt; 31 class nsIMsgMailNewsUrl; 32 class nsMsgFilePostHelper; 33 class nsIProxyInfo; 34 class nsICancelable; 35 36 // This is a helper class used to encapsulate code shared between all of the 37 // mailnews protocol objects (imap, news, pop, smtp, etc.) In particular, 38 // it unifies the core networking code for the protocols. My hope is that 39 // this will make unification with Necko easier as we'll only have to change 40 // this class and not all of the mailnews protocols. 41 class nsMsgProtocol : public nsIStreamListener, 42 public nsIChannel, 43 public nsITransportEventSink, 44 public nsHashPropertyBag { 45 public: 46 nsMsgProtocol(nsIURI* aURL); 47 48 NS_DECL_ISUPPORTS_INHERITED 49 // nsIChannel support 50 NS_DECL_NSICHANNEL 51 NS_DECL_NSIREQUEST 52 53 NS_DECL_NSISTREAMLISTENER 54 NS_DECL_NSIREQUESTOBSERVER 55 NS_DECL_NSITRANSPORTEVENTSINK 56 57 // LoadUrl -- A protocol typically overrides this function, sets up any local 58 // state for the url and then calls the base class which opens the socket if 59 // it needs opened. If the socket is already opened then we just call 60 // ProcessProtocolState to start the churning process. aConsumer is the 61 // consumer for the url. It can be null if this argument is not appropriate 62 virtual nsresult LoadUrl(nsIURI* aURL, nsISupports* aConsumer = nullptr); 63 64 virtual nsresult SetUrl( 65 nsIURI* aURL); // sometimes we want to set the url before we load it 66 void ShowAlertMessage(nsIMsgMailNewsUrl* aMsgUrl, nsresult aStatus); 67 68 // Flag manipulators TestFlag(uint32_t flag)69 virtual bool TestFlag(uint32_t flag) { return flag & m_flags; } SetFlag(uint32_t flag)70 virtual void SetFlag(uint32_t flag) { m_flags |= flag; } ClearFlag(uint32_t flag)71 virtual void ClearFlag(uint32_t flag) { m_flags &= ~flag; } 72 73 protected: 74 virtual ~nsMsgProtocol(); 75 76 // methods for opening and closing a socket with core netlib.... 77 // mscott -okay this is lame. I should break this up into a file protocol and 78 // a socket based protocool class instead of cheating and putting both methods 79 // here... 80 81 // open a connection with a specific host and port 82 // aHostName must be UTF-8 encoded. 83 virtual nsresult OpenNetworkSocketWithInfo(const char* aHostName, 84 int32_t aGetPort, 85 const char* connectionType, 86 nsIProxyInfo* aProxyInfo, 87 nsIInterfaceRequestor* callbacks); 88 // helper routine 89 nsresult GetFileFromURL(nsIURI* aURL, nsIFile** aResult); 90 virtual nsresult OpenFileSocket( 91 nsIURI* aURL, uint64_t aStartPosition, 92 int64_t aReadCount); // used to open a file socket connection 93 94 nsresult GetTopmostMsgWindow(nsIMsgWindow** aWindow); 95 GetType()96 virtual const char* GetType() { return nullptr; } 97 nsresult GetQoSBits(uint8_t* aQoSBits); 98 99 // a Protocol typically overrides this method. They free any of their own 100 // connection state and then they call up into the base class to free the 101 // generic connection objects 102 virtual nsresult CloseSocket(); 103 104 virtual nsresult 105 SetupTransportState(); // private method used by OpenNetworkSocket and 106 // OpenFileSocket 107 108 // ProcessProtocolState - This is the function that gets churned by calls to 109 // OnDataAvailable. As data arrives on the socket, OnDataAvailable calls 110 // ProcessProtocolState. 111 112 virtual nsresult ProcessProtocolState(nsIURI* url, 113 nsIInputStream* inputStream, 114 uint64_t sourceOffset, 115 uint32_t length) = 0; 116 117 // SendData -- Writes the data contained in dataBuffer into the current output 118 // stream. It also informs the transport layer that this data is now available 119 // for transmission. Returns a positive number for success, 0 for failure (not 120 // all the bytes were written to the stream, etc). aSuppressLogging is a hint 121 // that sensitive data is being sent and should not be logged 122 virtual nsresult SendData(const char* dataBuffer, 123 bool aSuppressLogging = false); 124 125 virtual nsresult PostMessage(nsIURI* url, nsIFile* aPostFile); 126 127 virtual nsresult InitFromURI(nsIURI* aUrl); 128 129 nsresult DoNtlmStep1(const nsACString& username, const nsAString& password, 130 nsCString& response); 131 nsresult DoNtlmStep2(nsCString& commandResponse, nsCString& response); 132 133 nsresult DoGSSAPIStep1(const char* service, const char* username, 134 nsCString& response); 135 nsresult DoGSSAPIStep2(nsCString& commandResponse, nsCString& response); 136 // Output stream for writing commands to the socket 137 nsCOMPtr<nsIOutputStream> 138 m_outputStream; // this will be obtained from the transport interface 139 140 // Output stream for writing commands to the socket 141 nsCOMPtr<nsITransport> m_transport; 142 nsCOMPtr<nsIRequest> m_request; 143 nsCOMPtr<nsICancelable> m_proxyRequest; 144 145 bool m_socketIsOpen; // mscott: we should look into keeping this state in the 146 // nsSocketTransport... I'm using it to make sure I open 147 // the socket the first time a URL is loaded into the 148 // connection 149 uint32_t m_flags; // used to store flag information 150 // uint32_t m_startPosition; 151 int64_t m_readCount; 152 153 nsCOMPtr<nsIFile> 154 m_tempMsgFile; // we currently have a hack where displaying a msg 155 // involves writing it to a temp file first 156 157 // auth module for access to NTLM functions 158 nsCOMPtr<nsIAuthModule> m_authModule; 159 160 // the following is a catch all for nsIChannel related data 161 nsCOMPtr<nsIURI> m_originalUrl; // the original url 162 nsCOMPtr<nsIURI> m_url; // the running url 163 nsCOMPtr<nsISupports> m_consumer; 164 nsCOMPtr<nsIStreamListener> m_channelListener; 165 bool m_isChannel; 166 nsCOMPtr<nsILoadGroup> m_loadGroup; 167 nsLoadFlags mLoadFlags; 168 nsCOMPtr<nsIProgressEventSink> mProgressEventSink; 169 nsCOMPtr<nsIInterfaceRequestor> mCallbacks; 170 nsCOMPtr<nsISupports> mOwner; 171 nsCString mContentType; 172 nsCString mCharset; 173 int64_t mContentLength; 174 nsCOMPtr<nsILoadInfo> m_loadInfo; 175 176 nsString m_lastPasswordSent; // used to prefill the password prompt 177 178 // private helper routine used by subclasses to quickly get a reference to the 179 // correct prompt dialog for a mailnews url. 180 nsresult GetPromptDialogFromUrl(nsIMsgMailNewsUrl* aMsgUrl, 181 nsIPrompt** aPromptDialog); 182 183 // if a url isn't going to result in any content then we want to suppress 184 // calls to OnStartRequest, OnDataAvailable and OnStopRequest 185 bool mSuppressListenerNotifications; 186 187 uint32_t mContentDisposition; 188 }; 189 190 // This is is a subclass of nsMsgProtocol extends the parent class with 191 // AsyncWrite support. Protocols like smtp and news want to leverage async 192 // write. We don't want everyone who inherits from nsMsgProtocol to have to pick 193 // up the extra overhead. 194 class nsMsgAsyncWriteProtocol : public nsMsgProtocol, 195 public nsSupportsWeakReference { 196 public: 197 NS_DECL_ISUPPORTS_INHERITED 198 199 NS_IMETHOD Cancel(nsresult status) override; 200 201 nsMsgAsyncWriteProtocol(nsIURI* aURL); 202 203 // temporary over ride... 204 virtual nsresult PostMessage(nsIURI* url, nsIFile* postFile) override; 205 206 // over ride the following methods from the base class 207 virtual nsresult SetupTransportState() override; 208 virtual nsresult SendData(const char* dataBuffer, 209 bool aSuppressLogging = false) override; 210 nsCString mAsyncBuffer; 211 212 // if we suspended the asynch write while waiting for more data to write then 213 // this will be TRUE 214 bool mSuspendedWrite; 215 nsCOMPtr<nsIRequest> m_WriteRequest; 216 nsCOMPtr<nsIAsyncOutputStream> mAsyncOutStream; 217 nsCOMPtr<nsIOutputStreamCallback> mProvider; 218 nsCOMPtr<nsIThread> mProviderThread; 219 220 // because we are reading the post data in asynchronously, it's possible that 221 // we aren't sending it out fast enough and the reading gets blocked. The 222 // following set of state variables are used to track this. 223 bool mSuspendedRead; 224 bool mInsertPeriodRequired; // do we need to insert a '.' as part of the 225 // unblocking process 226 227 nsresult ProcessIncomingPostData(nsIInputStream* inStr, uint32_t count); 228 nsresult UnblockPostReader(); 229 nsresult UpdateSuspendedReadBytes(uint32_t aNewBytes, 230 bool aAddToPostPeriodByteCount); 231 nsresult PostDataFinished(); // this is so we'll send out a closing '.' and 232 // release any state related to the post 233 234 // these two routines are used to pause and resume our loading of the file 235 // containing the contents we are trying to post. We call these routines when 236 // we aren't sending the bits out fast enough to keep up with the file read. 237 nsresult SuspendPostFileRead(); 238 nsresult ResumePostFileRead(); 239 nsresult UpdateSuspendedReadBytes(uint32_t aNewBytes); 240 void UpdateProgress(uint32_t aNewBytes); 241 nsMsgFilePostHelper* mFilePostHelper; // needs to be a weak reference 242 protected: 243 virtual ~nsMsgAsyncWriteProtocol(); 244 245 // the streams for the pipe used to queue up data for the async write calls to 246 // the server. we actually re-use the same mOutStream variable in our parent 247 // class for the output stream to the socket channel. So no need for a new 248 // variable here. 249 nsCOMPtr<nsIInputStream> mInStream; 250 nsCOMPtr<nsIInputStream> mPostDataStream; 251 uint32_t mSuspendedReadBytes; // remaining # of bytes we need to read before 252 // the input stream becomes unblocked 253 uint32_t mSuspendedReadBytesPostPeriod; // # of bytes which need processed 254 // after we insert a '.' before the 255 // input stream becomes unblocked. 256 int64_t 257 mFilePostSize; // used for file size, we post a single message in a file 258 uint32_t mNumBytesPosted; // used for determining progress on posting files 259 bool 260 mGenerateProgressNotifications; // set during a post operation after 261 // we've started sending the post data... 262 263 virtual nsresult CloseSocket() override; 264 }; 265 266 #endif /* nsMsgProtocol_h__ */ 267