001         package com.croftsoft.core.net.news;
002    
003         import java.net.*;
004         import java.io.*;
005         import java.util.*;
006    
007         import com.croftsoft.core.util.log.Log;
008         import com.croftsoft.core.lang.NullArgumentException;
009    
010         /*********************************************************************
011         * Implements NNTP as given by RFC 977.
012         *
013         * @see
014         *   "Common NNTP Extensions (AUTHINFO),
015         *   <a target=&quot;blank&quot;
016         * href=&quot;http://www.mibsoftware.com/userkt/nntpext/0032.htm&quot;>
017         *            http://www.mibsoftware.com/userkt/nntpext/0032.htm</a>"
018         *
019         * @author
020         *   <a href="http://croftsoft.com/">David Wallace Croft</A>
021         * @version
022         *   2001-08-03
023         * @since
024         *   1997-05-10
025         *********************************************************************/
026    
027         public class  NntpSocket extends Socket
028           implements NntpConstants
029         //////////////////////////////////////////////////////////////////////
030         //////////////////////////////////////////////////////////////////////
031         {
032    
033         private BufferedReader  bufferedReader;
034    
035         private PrintStream     printStream;
036    
037         private String          responseCode;
038    
039         private Vector          response_text;
040    
041         private boolean         postingAllowed;
042    
043    //   private Vector          newsgroup_Vector;
044    
045         private Log             log;
046    
047         //////////////////////////////////////////////////////////////////////
048         //////////////////////////////////////////////////////////////////////
049    
050         /*********************************************************************
051         * Be sure to call command_QUIT() when done.
052         *********************************************************************/
053         public  NntpSocket (
054           String  nntpServerHost,
055           Log     log )
056           throws IOException
057         //////////////////////////////////////////////////////////////////////
058         {
059           super ( nntpServerHost, NNTP_PORT );
060    
061           this.log = log;
062    
063           setSoLinger ( true, 30 ); // timeout after 30 seconds
064    
065           bufferedReader = new BufferedReader (
066             new InputStreamReader ( getInputStream ( ) ) );
067    
068           printStream = new PrintStream ( getOutputStream ( ) );
069    
070           responseCode = bufferedReader.readLine ( );
071    
072           record ( responseCode );
073    
074           if ( responseCode.startsWith ( "200" ) )
075           {
076             postingAllowed = true;
077           }
078           else if ( !responseCode.startsWith ( "201" ) )
079           {
080             throw new IOException ( "Connection failed:  " + responseCode );
081           }
082         }
083    
084         //////////////////////////////////////////////////////////////////////
085         //////////////////////////////////////////////////////////////////////
086    
087         public BufferedReader  getBufferedReader ( )
088         //////////////////////////////////////////////////////////////////////
089         {
090           return bufferedReader;
091         }
092    
093         /*********************************************************************
094         * Returns the response code for the last command.
095         *********************************************************************/
096         public String  getResponseCode ( ) { return responseCode; }
097    
098         /*********************************************************************
099         * Returns the response text, a Vector of String, for the last command.
100         *********************************************************************/
101         public Vector  response_text ( ) { return response_text; }
102    
103         /*********************************************************************
104         * Returns true if posting to this server is allowed.
105         *********************************************************************/
106         public boolean  getPostingAllowed ( ) { return postingAllowed; }
107    
108         /*********************************************************************
109         * Returns a Vector of Newsgroup.
110         *********************************************************************/
111    //   public Vector  newsgroup_Vector ( ) { return newsgroup_Vector; }
112    
113         //////////////////////////////////////////////////////////////////////
114         //////////////////////////////////////////////////////////////////////
115    
116         /*********************************************************************
117         * Loads the response_text from the NNTPSocket InputStream.
118         * Decodes it as well.
119         *********************************************************************/
120         public synchronized Vector  load_response_text ( )
121           throws IOException
122         //////////////////////////////////////////////////////////////////////
123         {
124           response_text = new Vector ( );
125    
126           String  line;
127    
128    int  count = 0;
129    
130           while ( ( line = bufferedReader.readLine ( ) ) != null )
131           {
132             if ( line.equals ( "." ) ) break;
133    
134             line = NntpLib.decodeLine ( line );
135    
136             response_text.addElement ( line );
137    
138    if ( ( ++count % 1000 ) == 0 ) System.out.print ( "." );
139    
140           }
141    
142    System.out.println ( "\n" + count + " newsgroups" );
143    
144           return response_text;
145         }
146    
147         /*********************************************************************
148         * Sends command + CR_LF to the server.
149         * Returns the responseCode.
150         *********************************************************************/
151         public synchronized String  command ( String  command )
152           throws IOException
153         //////////////////////////////////////////////////////////////////////
154         {
155           printStream.print ( command + CR_LF );
156    
157           record ( command + CR_LF );
158    
159           responseCode = bufferedReader.readLine ( );
160    
161           record ( responseCode );
162    
163           return responseCode;
164         }
165    
166         /*********************************************************************
167         *********************************************************************/
168    /*
169         public synchronized String  command_GROUP ( String  group_name )
170           throws IOException
171         //////////////////////////////////////////////////////////////////////
172         {
173           responseCode = command ( COMMAND_GROUP + " " + group_name );
174    
175           if ( responseCode.startsWith ( "211" ) )
176           {
177             
178             StringTokenizer  st = new StringTokenizer ( responseCode );
179    
180             try
181             {
182               st.nextToken ( );
183               int  estimated_articles = Integer.parseInt ( st.nextToken ( ) );
184               int  first_article = Integer.parseInt ( st.nextToken ( ) );
185               int  last_article = Integer.parseInt ( st.nextToken ( ) );
186               String  new_group_name = st.nextToken ( );
187    
188               if ( newsgroup_Vector != null )
189               {
190                 Enumeration  e = newsgroup_Vector.elements ( );
191    
192                 while ( e.hasMoreElements ( ) )
193                 {
194                   Newsgroup  newsgroup = ( Newsgroup ) e.nextElement ( );
195    
196                   if ( newsgroup.getGroupName ( ).equals ( new_group_name ) )
197                   {
198                     newsgroup_Vector.removeElement ( newsgroup );
199    
200                     break;
201                   }
202                 }
203               } else newsgroup_Vector = new Vector ( );
204               newsgroup_Vector.insertElementAt ( new Newsgroup (
205                 estimated_articles, first_article, last_article,
206                 new_group_name ), 0 );
207             } catch ( Exception  e ) { e.printStackTrace ( ); }
208           }
209           return responseCode;
210         }
211    */
212    
213         /*********************************************************************
214         * Loads the newsgroup_Vector.  Returns the responseCode.
215         *********************************************************************/
216    /*
217         public synchronized String  command_LIST ( ) throws IOException {
218         //////////////////////////////////////////////////////////////////////
219           newsgroup_Vector = new Vector ( );
220           responseCode = command ( COMMAND_LIST );
221           if ( responseCode.startsWith ( "2" ) ) {
222             try { load_response_text ( ); }
223             catch ( IOException  e ) { e.printStackTrace ( ); }
224             Enumeration  e = response_text.elements ( );
225             while ( e.hasMoreElements ( ) ) {
226               String  line = ( String ) e.nextElement ( );
227               StringTokenizer  st = new StringTokenizer ( line );
228               try {
229                 while ( st.hasMoreTokens ( ) ) {
230                   String  group_name = st.nextToken ( );
231                   int  last_article = Integer.parseInt ( st.nextToken ( ) );
232                   int  first_article = Integer.parseInt ( st.nextToken ( ) );
233                   boolean  posting_ok
234                     = st.nextToken ( ).equalsIgnoreCase ( "y" );
235                   newsgroup_Vector.addElement ( new Newsgroup (
236                     group_name, last_article, first_article, posting_ok ) );
237                 }
238               } catch ( Exception  ex ) { ex.printStackTrace ( ); }
239             }
240           }
241           return responseCode;
242         }
243    */
244    
245         /*********************************************************************
246         * Sends COMMAND_QUIT and then closes the NNTPSocket.
247         *********************************************************************/
248         public synchronized String  command_QUIT ( ) throws IOException {
249         //////////////////////////////////////////////////////////////////////
250           responseCode = command ( COMMAND_QUIT );
251           close ( );
252           return responseCode;
253         }
254    
255         //////////////////////////////////////////////////////////////////////
256         //////////////////////////////////////////////////////////////////////
257    
258         public Log  getLog ( ) { return log; }
259    
260         public void  setLog ( Log  log ) { this.log = log; }
261    
262         //////////////////////////////////////////////////////////////////////
263         //////////////////////////////////////////////////////////////////////
264    
265         private void  record ( String  entry )
266         //////////////////////////////////////////////////////////////////////
267         {
268           Log  log = this.log;
269    
270           if ( log != null )
271           {
272             log.record ( entry );
273           }
274         }
275    
276         //////////////////////////////////////////////////////////////////////
277         //////////////////////////////////////////////////////////////////////
278         }