Back to index

lightning-sunbird  0.9+nobinonly
nsNNTPProtocol.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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-2000
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 nsNNTPProtocol_h___
00039 #define nsNNTPProtocol_h___
00040 
00041 #include "nsMsgProtocol.h"
00042 
00043 #include "nsCOMPtr.h"
00044 #include "nsIInputStream.h"
00045 #include "nsIOutputStream.h"
00046 #include "nsIInputStream.h"
00047 #include "nsIOutputStream.h"
00048 #include "nsINntpUrl.h"
00049 #include "nsINntpIncomingServer.h"
00050 #include "nsINNTPProtocol.h"
00051 
00052 #include "nsINNTPNewsgroupList.h"
00053 #include "nsINNTPArticleList.h"
00054 #include "nsIMsgNewsFolder.h"
00055 #include "nsIMsgWindow.h"
00056 
00057 #include "nsMsgLineBuffer.h"
00058 #include "nsSpecialSystemDirectory.h"
00059 #include "nsXPIDLString.h"
00060 #include "nsIStringBundle.h"
00061 #include "nsITimer.h"
00062 #include "nsICacheListener.h"
00063 
00064 // this is only needed as long as our libmime hack is in place
00065 #include "prio.h"
00066 
00067 // State Flags (Note, I use the word state in terms of storing 
00068 // state information about the connection (authentication, have we sent
00069 // commands, etc. I do not intend it to refer to protocol state)
00070 
00071 #define NNTP_PAUSE_FOR_READ               0x00000001  /* should we pause for the next read */
00072 #define NNTP_PROXY_AUTH_REQUIRED    0x00000002  /* is auth required */
00073 #define NNTP_SENT_PROXY_AUTH        0x00000004  /* have we sent a proxy auth? */
00074 #define NNTP_NEWSRC_PERFORMED       0x00000008  /* have we done a newsrc update? */
00075 #define NNTP_READER_PERFORMED       0x00000010  /* have we sent any cmds to the server yet? */
00076 #define NNTP_USE_FANCY_NEWSGROUP    0x00000020   /* use LIST XACTIVE or LIST */
00077 #define NNTP_DESTROY_PROGRESS_GRAPH 0x00000040  /* do we need to destroy graph progress */  
00078 #define NNTP_SOME_PROTOCOL_SUCCEEDED 0x0000080  /* some protocol has suceeded so don't kill the connection */
00079 #define NNTP_NO_XOVER_SUPPORT       0x00000100  /* xover command is not supported here */
00080 
00081 /* states of the machine
00082  */
00083 typedef enum _StatesEnum {
00084 NNTP_RESPONSE,
00085 #ifdef BLOCK_UNTIL_AVAILABLE_CONNECTION
00086 NNTP_BLOCK_UNTIL_CONNECTIONS_ARE_AVAILABLE,
00087 NNTP_CONNECTIONS_ARE_AVAILABLE,
00088 #endif
00089 NNTP_CONNECT,
00090 NNTP_CONNECT_WAIT,
00091 NNTP_LOGIN_RESPONSE,
00092 NNTP_SEND_MODE_READER,
00093 NNTP_SEND_MODE_READER_RESPONSE,
00094 SEND_LIST_EXTENSIONS,
00095 SEND_LIST_EXTENSIONS_RESPONSE,
00096 SEND_LIST_SEARCHES,
00097 SEND_LIST_SEARCHES_RESPONSE,
00098 NNTP_LIST_SEARCH_HEADERS,
00099 NNTP_LIST_SEARCH_HEADERS_RESPONSE,
00100 NNTP_GET_PROPERTIES,
00101 NNTP_GET_PROPERTIES_RESPONSE,
00102 SEND_LIST_SUBSCRIPTIONS,
00103 SEND_LIST_SUBSCRIPTIONS_RESPONSE,
00104 SEND_FIRST_NNTP_COMMAND,
00105 SEND_FIRST_NNTP_COMMAND_RESPONSE,
00106 SETUP_NEWS_STREAM,
00107 NNTP_BEGIN_AUTHORIZE,
00108 NNTP_AUTHORIZE_RESPONSE,
00109 NNTP_PASSWORD_RESPONSE,
00110 NNTP_READ_LIST_BEGIN,
00111 NNTP_READ_LIST,
00112 DISPLAY_NEWSGROUPS,
00113 NNTP_NEWGROUPS_BEGIN,
00114 NNTP_NEWGROUPS,
00115 NNTP_BEGIN_ARTICLE,
00116 NNTP_READ_ARTICLE,
00117 NNTP_XOVER_BEGIN,
00118 NNTP_FIGURE_NEXT_CHUNK,
00119 NNTP_XOVER_SEND,
00120 NNTP_XOVER_RESPONSE,
00121 NNTP_XOVER,
00122 NEWS_PROCESS_XOVER,
00123 NNTP_READ_GROUP,
00124 NNTP_READ_GROUP_RESPONSE,
00125 NNTP_READ_GROUP_BODY,
00126 NNTP_SEND_GROUP_FOR_ARTICLE,
00127 NNTP_SEND_GROUP_FOR_ARTICLE_RESPONSE,
00128 NNTP_PROFILE_ADD,
00129 NNTP_PROFILE_ADD_RESPONSE,
00130 NNTP_PROFILE_DELETE,
00131 NNTP_PROFILE_DELETE_RESPONSE,
00132 NNTP_SEND_ARTICLE_NUMBER,
00133 NEWS_PROCESS_BODIES,
00134 NNTP_PRINT_ARTICLE_HEADERS,
00135 NNTP_SEND_POST_DATA,
00136 NNTP_SEND_POST_DATA_RESPONSE,
00137 NNTP_CHECK_FOR_MESSAGE,
00138 NEWS_NEWS_RC_POST,
00139 NEWS_DISPLAY_NEWS_RC,
00140 NEWS_DISPLAY_NEWS_RC_RESPONSE,
00141 NEWS_START_CANCEL,
00142 NEWS_DO_CANCEL,
00143 NNTP_XPAT_SEND,
00144 NNTP_XPAT_RESPONSE,
00145 NNTP_SEARCH,
00146 NNTP_SEARCH_RESPONSE,
00147 NNTP_SEARCH_RESULTS,
00148 NNTP_LIST_PRETTY_NAMES,
00149 NNTP_LIST_PRETTY_NAMES_RESPONSE,
00150 NNTP_LIST_XACTIVE,
00151 NNTP_LIST_XACTIVE_RESPONSE,
00152 NNTP_LIST_GROUP,
00153 NNTP_LIST_GROUP_RESPONSE,
00154 NEWS_DONE,
00155 NEWS_POST_DONE,
00156 NEWS_ERROR,
00157 NNTP_ERROR,
00158 NEWS_FREE,
00159 NEWS_FINISHED
00160 } StatesEnum;
00161 
00162 class nsICacheEntryDescriptor;
00163 
00164 class nsNNTPProtocol : public nsINNTPProtocol, public nsITimerCallback, public nsICacheListener, public nsMsgProtocol
00165 {
00166 public:
00167   NS_DECL_ISUPPORTS_INHERITED
00168   NS_DECL_NSINNTPPROTOCOL
00169   NS_DECL_NSICACHELISTENER
00170 
00171   // nsITimerCallback interfaces
00172   NS_DECL_NSITIMERCALLBACK
00173   
00174   // Creating a protocol instance requires the URL 
00175   // need to call Initialize after we do a new of nsNNTPProtocol
00176   nsNNTPProtocol(nsIURI * aURL, nsIMsgWindow *aMsgWindow);     
00177   virtual ~nsNNTPProtocol();
00178   
00179   // stop binding is a "notification" informing us that the stream associated with aURL is going away. 
00180   NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports * aCtxt, nsresult aStatus);
00181   
00182   char * m_ProxyServer;            /* proxy server hostname */
00183   
00184   NS_IMETHOD Cancel(nsresult status);  // handle stop button
00185   NS_IMETHOD GetContentType(nsACString &aContentType);
00186   NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt);
00187   NS_IMETHOD GetOriginalURI(nsIURI* *aURI);
00188   NS_IMETHOD SetOriginalURI(nsIURI* aURI);
00189 
00190   nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer);
00191 
00192 private:
00193        // over-rides from nsMsgProtocol
00194        virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream, 
00195                                                                      PRUint32 sourceOffset, PRUint32 length);
00196        virtual nsresult CloseSocket();
00197 
00198        // we have our own implementation of SendData which writes to the nntp log
00199        // and then calls the base class to transmit the data
00200        PRInt32 SendData(nsIURI * aURL, const char * dataBuffer, PRBool aSuppressLogging = PR_FALSE);
00201 
00202   nsresult CleanupAfterRunningUrl();
00203   void Cleanup(); //free char* member variables
00204 
00205   void ParseHeaderForCancel(char *buf);
00206 
00207   static PRBool CheckIfAuthor(nsISupports *aElement, void *data);
00208 
00209   nsCOMPtr <nsINNTPNewsgroupList> m_newsgroupList;
00210   nsCOMPtr <nsINNTPArticleList> m_articleList;
00211 
00212   nsCOMPtr <nsIMsgNewsFolder> m_newsFolder;
00213   nsCOMPtr <nsIMsgWindow> m_msgWindow;
00214 
00215        nsCOMPtr<nsIInputStream> mDisplayInputStream;
00216        nsCOMPtr<nsIOutputStream> mDisplayOutputStream;
00217        nsMsgLineStreamBuffer   * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
00218        // the nsINntpURL that is currently running
00219        nsCOMPtr<nsINntpUrl> m_runningURL;
00220   PRBool      m_connectionBusy;
00221   PRBool      m_fromCache;  // is this connection from the cache?
00222   PRTime      m_lastActiveTimeStamp;
00223        nsNewsAction m_newsAction;
00224 
00225        // Generic state information -- What state are we in? What state do we want to go to
00226        // after the next response? What was the last response code? etc. 
00227        StatesEnum  m_nextState;
00228   StatesEnum  m_nextStateAfterResponse;
00229        PRInt32     m_typeWanted;     /* Article, List, or Group */
00230   PRInt32     m_responseCode;    /* code returned from NNTP server */
00231        PRInt32       m_previousResponseCode; 
00232   char       *m_responseText;   /* text returned from NNTP server */
00233     
00234   char        *m_dataBuf;
00235   PRUint32     m_dataBufSize;
00236 
00237        /* for group command */
00238   char     *m_path;                  /* message id */
00239   nsCString m_currentGroup;     /* current group */
00240 
00241   PRInt32   m_firstArticle;
00242   PRInt32   m_lastArticle;
00243   PRInt32   m_firstPossibleArticle;
00244   PRInt32   m_lastPossibleArticle;
00245 
00246        PRInt32         m_numArticlesLoaded;      /* How many articles we got XOVER lines for. */
00247        PRInt32         m_numArticlesWanted; /* How many articles we wanted to get XOVER lines for. */
00248     PRInt32   m_maxArticles;        /* max articles to get during an XOVER */
00249 
00250        // Cancelation specific state. In particular, the headers that should be 
00251        // used for the cancelation message. 
00252        // mscott: we can probably replace this stuff with nsString
00253   char  *m_cancelFromHdr;
00254   char     *m_cancelNewsgroups;
00255   char     *m_cancelDistribution;
00256   char     *m_cancelID;
00257   PRInt32       m_cancelStatus;
00258 
00259        // variables for ReadNewsRC
00260        PRInt32   m_newsRCListIndex;
00261        PRInt32   m_RCIndexToResumeAfterAuthRequest;
00262        PRInt32   m_newsRCListCount;
00263 
00264        // variable for ReadNewsList
00265        PRInt32   m_readNewsListCount;
00266 
00267        // Per news article state information. (article number, author, subject, id, etc
00268        char    *m_messageID;
00269     PRInt32   m_articleNumber;   /* current article number */
00270        char    *m_commandSpecificData;
00271        char    *m_searchData;
00272 
00273        PRInt32   m_originalContentLength; /* the content length at the time of calling graph progress */
00274 
00275        
00276        nsCOMPtr<nsIStringBundle> m_stringBundle;
00277 
00278   nsCOMPtr<nsINntpIncomingServer> m_nntpServer;
00279 
00280        nsresult GetNewsStringByName(const char *aName, PRUnichar **aString);
00281        nsresult GetNewsStringByID(PRInt32 stringID, PRUnichar **aString);
00282 
00283   PRInt32 PostMessageInFile(nsIFileSpec * filePath);
00284 
00286        // Communication methods --> Reading and writing protocol
00288 
00289        PRInt32 ReadLine(nsIInputStream * inputStream, PRUint32 length, char ** line);
00290 
00292        // Protocol Methods --> This protocol is state driven so each protocol method is 
00293        //                                        designed to re-act to the current "state". I've attempted to 
00294        //                                        group them together based on functionality. 
00296 
00297        // gets the response code from the nntp server and the response line. Returns the TCP return code 
00298        // from the read.
00299        PRInt32 NewsResponse(nsIInputStream * inputStream, PRUint32 length); 
00300 
00301        // Interpret the server response after the connect. 
00302        // Returns negative if the server responds unexpectedly
00303        PRInt32 LoginResponse(); 
00304        PRInt32 SendModeReader();
00305        PRInt32 SendModeReaderResponse();
00306 
00307        PRInt32 SendListExtensions();
00308        PRInt32 SendListExtensionsResponse(nsIInputStream * inputStream, PRUint32 length);
00309        
00310        PRInt32 SendListSearches();
00311        PRInt32 SendListSearchesResponse(nsIInputStream * inputStream, PRUint32 length);
00312 
00313        PRInt32 SendListSearchHeaders();
00314        PRInt32 SendListSearchHeadersResponse(nsIInputStream * inputStream, PRUint32 length);
00315 
00316        PRInt32 GetProperties();
00317        PRInt32 GetPropertiesResponse(nsIInputStream * inputStream, PRUint32 length);
00318 
00319        PRInt32 SendListSubscriptions();
00320        PRInt32 SendListSubscriptionsResponse(nsIInputStream * inputStream, PRUint32 length);
00321 
00322        // Figure out what the first command is and send it. 
00323        // Returns the status from the NETWrite.
00324        PRInt32 SendFirstNNTPCommand(nsIURI * url);
00325 
00326        // Interprets the server response from the first command sent.
00327        // returns negative if the server responds unexpectedly.
00328        PRInt32 SendFirstNNTPCommandResponse();
00329 
00330        PRInt32 SetupForTransfer();
00331 
00332        PRInt32 SendGroupForArticle();
00333        PRInt32 SendGroupForArticleResponse();
00334 
00335        PRInt32 SendArticleNumber();
00336        PRInt32 BeginArticle();
00337        PRInt32 ReadArticle(nsIInputStream * inputStream, PRUint32 length);
00338        PRInt32 DisplayArticle(nsIInputStream * inputStream, PRUint32 length);
00339 
00340        PRInt32 BeginAuthorization();
00341        PRInt32 AuthorizationResponse();
00342 
00343        PRInt32 PasswordResponse();
00344 
00345        PRInt32 BeginReadNewsList();
00346        PRInt32 ReadNewsList(nsIInputStream * inputStream, PRUint32 length);
00347 
00348        // Newsgroup specific protocol handlers
00349        PRInt32 DisplayNewsgroups();
00350        PRInt32 BeginNewsgroups();
00351        PRInt32 ProcessNewsgroups(nsIInputStream * inputStream, PRUint32 length);
00352 
00353        PRInt32 ReadNewsgroup();
00354        PRInt32 ReadNewsgroupResponse();
00355 
00356        PRInt32 ReadNewsgroupBody(nsIInputStream * inputStream, PRUint32 length);
00357 
00358        // Protocol handlers used for posting data 
00359        PRInt32 PostData();
00360        PRInt32 PostDataResponse();
00361 
00362        PRInt32 CheckForArticle();
00363 
00364        // NewsRC specific
00365        PRInt32 DisplayNewsRC();
00366        PRInt32 DisplayNewsRCResponse();
00367 
00368        // start off the xover command 
00369        PRInt32 BeginReadXover();
00370 
00371        // process the xover list as it comes from the server and load it into the sort list.  
00372        PRInt32 ReadXover(nsIInputStream * inputStream, PRUint32 length);
00373        // See if the xover response is going to return us data. If the proper code isn't returned then 
00374        // assume xover isn't supported and use normal read_group.
00375        PRInt32 ReadXoverResponse();
00376 
00377        PRInt32 XoverSend();
00378        PRInt32 ProcessXover();
00379 
00380        PRInt32 FigureNextChunk();
00381 
00382        // Canceling
00383        PRInt32 StartCancel();
00384        PRInt32 DoCancel();
00385 
00386        // XPAT 
00387        PRInt32 XPATSend();
00388        PRInt32 XPATResponse(nsIInputStream * inputStream, PRUint32 length);
00389        PRInt32 ListPrettyNames();
00390        PRInt32 ListPrettyNamesResponse(nsIInputStream * inputStream, PRUint32 length);
00391 
00392        PRInt32 ListXActive();
00393        PRInt32 ListXActiveResponse(nsIInputStream * inputStream, PRUint32 length);
00394 
00395     // for "?list-ids"
00396        PRInt32 SendListGroup();
00397        PRInt32 SendListGroupResponse(nsIInputStream * inputStream, PRUint32 length);
00398 
00399        // Searching Protocol....
00400        PRInt32 Search();
00401        PRInt32 SearchResponse();
00402        PRInt32 SearchResults(nsIInputStream *inputStream, PRUint32 length);
00403 
00405        // End of Protocol Methods
00407 
00408        nsresult ParseURL(nsIURI * aURL, char ** aGroup, char ** aMessageID, char ** aCommandSpecificData);
00409 
00410        void SetProgressBarPercent(PRUint32 aProgress, PRUint32 aProgressMax);
00411        nsresult SetProgressStatus(const PRUnichar *aMessage);
00412   nsresult SetCheckingForNewNewsStatus(PRInt32 current, PRInt32 total);
00413        nsresult InitializeNewsFolderFromUri(const char *uri);
00414        void TimerCallback();
00415 
00416   void HandleAuthenticationFailure();
00417        nsCOMPtr <nsIInputStream> mInputStream;
00418   nsCOMPtr <nsITimer> mUpdateTimer; 
00419        nsresult AlertError(PRInt32 errorCode, const char *text);
00420        PRInt32 mBytesReceived;
00421   PRInt32 mBytesReceivedSinceLastStatusUpdate;
00422   PRTime m_startTime;
00423   PRInt32 mNumGroupsListed;
00424   nsMsgKey m_key;
00425 
00426   nsresult SetCurrentGroup(); /* sets m_currentGroup.  should be called after doing a successful GROUP command */
00427   nsresult CleanupNewsgroupList(); /* cleans up m_newsgroupList, and set it to null */
00428 
00429   void    GotAuthorizationRequest(); /* called when we got an authorization request, which potentially disrupted something */
00430   PRInt32 GetNextGroupNeedingCounts( nsISupports** pNextGroup, PRInt32* returnStatus );
00431 
00432     // cache related helper methods
00433   void FinishMemCacheEntry(PRBool valid); // either mark it valid, or doom it
00434   nsresult OpenCacheEntry(); // makes a request to the cache service for a cache entry for a url
00435   PRBool ReadFromLocalCache(); // attempts to read the url out of our local (offline) cache....
00436   nsresult ReadFromNewsConnection(); // creates a new news connection to read the url 
00437   nsresult ReadFromMemCache(nsICacheEntryDescriptor *entry); // attempts to read the url out of our memory cache
00438   nsresult SetupPartExtractorListener(nsIStreamListener * aConsumer);
00439 };
00440 
00441 
00442 #endif  // nsNNTPProtocol_h___