001         package com.croftsoft.core.net.news;
002    
003         import java.io.*;
004         import java.net.*;
005         import java.util.*;
006    
007         import com.croftsoft.core.lang.Pair;
008         import com.croftsoft.core.lang.StringLib;
009         import com.croftsoft.core.security.Authentication;
010         import com.croftsoft.core.security.Identifier;
011         import com.croftsoft.core.security.PreIdentifier;
012         import com.croftsoft.core.util.log.Log;
013         import com.croftsoft.core.util.log.PrintStreamLog;
014    
015         /*********************************************************************
016         * Static library methods for NNTP (RFC 977).
017         *
018         * @author
019         *   <a href="https://www.croftsoft.com/">David Wallace Croft</A>
020         * @version
021         *   2001-08-03
022         * @since
023         *   2001-07-23
024         *********************************************************************/
025    
026         public final class  NntpLib
027           implements NntpConstants
028         //////////////////////////////////////////////////////////////////////
029         //////////////////////////////////////////////////////////////////////
030         {
031    
032         /*********************************************************************
033         * Posts a test message to a test newsgroup.
034         *********************************************************************/
035         public static void  main ( String [ ]  args )
036           throws IOException
037         //////////////////////////////////////////////////////////////////////
038         {
039           String  nntpServer = args [ 0 ];
040    
041           String  username   = args [ 1 ];
042    
043           String  password   = args [ 2 ];
044    
045           UsenetMessage  usenetMessage = new UsenetMessage (
046             args [ 3 ],          // from
047             "alt.test",          // newsgroup
048             "test",              // subject
049             "This is a test." ); // body
050    
051           post (
052             nntpServer,
053             new PreIdentifier ( username, password ),
054             usenetMessage,
055             new PrintStreamLog ( System.out ) );
056         }
057    
058         //////////////////////////////////////////////////////////////////////
059         //////////////////////////////////////////////////////////////////////
060    
061         /*********************************************************************
062         * Sends username and password.
063         *
064         * Synchronizes on the NntpSocket.
065         *********************************************************************/
066         public static String  authenticate (
067           NntpSocket  nntpSocket,
068           String      username,
069           String      password )
070           throws IOException, SecurityException
071         //////////////////////////////////////////////////////////////////////
072         {
073           synchronized ( nntpSocket )
074           {
075    
076           String  responseCode
077             = nntpSocket.command ( COMMAND_AUTHINFO + " USER " + username );
078    
079           if ( responseCode.startsWith ( "502" ) )
080           {
081             // 502 Authentication Failed
082    
083             throw new SecurityException ( responseCode );
084           }
085    
086           // 381 More Authentication Required
087    
088           Log  log = nntpSocket.getLog ( );
089    
090           nntpSocket.setLog ( null );
091    
092           responseCode
093             = nntpSocket.command ( COMMAND_AUTHINFO + " PASS " + password );
094    
095           nntpSocket.setLog ( log );
096    
097           if ( responseCode.startsWith ( "502" ) )
098           {
099             // 502 Authentication Failed
100    
101             throw new SecurityException ( responseCode );
102           }
103    
104           // 281 Authentication Accepted
105    
106           return responseCode;
107    
108           }
109         }
110    
111         /*********************************************************************
112         * Replaces lines that start with "." with "..",
113         * appends CR_LF to each line, then
114         * adds a final line of "." + CR_LF.
115         *********************************************************************/
116         public static StringBuffer  encodeLines ( String [ ]  lines )
117         //////////////////////////////////////////////////////////////////////
118         {
119           StringBuffer  stringBuffer = new StringBuffer ( );
120    
121           for ( int  i = 0; i < lines.length; i++ )
122           {
123             String  line = lines [ i ];
124    
125             if ( line.startsWith ( "." ) )
126             {
127               stringBuffer.append ( "." );
128             }
129    
130             stringBuffer.append ( line );
131    
132             stringBuffer.append ( CR_LF );
133           }
134    
135           stringBuffer.append ( "." + CR_LF );
136    
137           return stringBuffer;
138         }
139    
140         /*********************************************************************
141         * Encodes a message body in preparation for an NNTP POST transmission.
142         *
143         * <pre>
144         * return encodeLines (
145         *   StringLib.toStringArray ( messageBody ) ).toString ( );
146         * </pre>
147         *********************************************************************/
148         public static String  encode ( String  messageBody )
149         //////////////////////////////////////////////////////////////////////
150         {
151           return encodeLines (
152             StringLib.toStringArray ( messageBody ) ).toString ( );
153         }
154    
155         /*********************************************************************
156         * Replaces lines that start with ".." with ".".
157         *********************************************************************/
158         public static void  decodeLines ( String [ ]  lines )
159         //////////////////////////////////////////////////////////////////////
160         {
161           for ( int  i = 0; i < lines.length; i++ )
162           {
163             lines [ i ] = decodeLine ( lines [ i ] );
164           }
165         }
166    
167         /*********************************************************************
168         * Replaces starting ".." with ".".
169         *********************************************************************/
170         public static String  decodeLine ( String  line )
171         //////////////////////////////////////////////////////////////////////
172         {
173           if ( line.startsWith ( ".." ) )
174           {
175             return line.substring ( 1 );
176           }
177    
178           return new String ( line );
179         }
180    
181         public static String  post (
182           String         nntpServer,
183           Identifier     identifier,
184           UsenetMessage  usenetMessage,
185           Log            log )
186           throws IOException
187         //////////////////////////////////////////////////////////////////////
188         {
189           String  responseCode = null;
190    
191           NntpSocket  nntpSocket = null;
192    
193           try
194           {
195             nntpSocket = new NntpSocket ( nntpServer, log );
196    
197             nntpSocket.setSoLinger ( true, 30 ); // timeout after 30 seconds
198    
199             responseCode = nntpSocket.getResponseCode ( );
200    
201             if ( !nntpSocket.getPostingAllowed ( ) )
202             {
203               throw new IOException ( responseCode );
204             }
205    
206             responseCode = nntpSocket.command ( NntpConstants.COMMAND_POST );
207    
208             if ( responseCode.startsWith ( "480" )
209               && ( identifier != null ) )
210             {
211               // 480 Authentication Required
212    
213               Authentication  authentication
214                 = identifier.getAuthentication ( );
215    
216               if ( authentication != null )
217               {
218                 responseCode = authenticate (
219                   nntpSocket,
220                   authentication.getUsername ( ),
221                   authentication.getPassword ( ) );
222    
223                 responseCode
224                   = nntpSocket.command ( NntpConstants.COMMAND_POST );
225               }
226             }
227    
228             if ( !responseCode.startsWith ( "340" ) )
229             {
230               throw new IOException ( responseCode );
231             }
232    
233             responseCode = nntpSocket.command ( usenetMessage.toString ( ) );
234    
235             if ( !responseCode.startsWith ( "240" ) )
236             {
237               throw new IOException ( responseCode );
238             }
239    
240             responseCode = nntpSocket.command_QUIT ( );
241           }
242           finally
243           {
244             if ( nntpSocket != null )
245             {
246               nntpSocket.close ( );
247             }
248           }
249    
250           return responseCode;
251         }
252    
253    /*
254         public static String  post (
255           String      nntpServer,
256           Identifier  identifier,
257           Pair [ ]    messageHeaderPairs,
258           String      messageBody,
259           Log         log ) 
260           throws IOException
261         //////////////////////////////////////////////////////////////////////
262         {
263           UsenetMessage  usenetMessage = new UsenetMessage ( );
264    
265           for ( int  i = 0; i < messageHeaderPairs.length; i++ )
266           {
267             Pair  headerPair = messageHeaderPairs [ i ];
268    
269             usenetMessage.setHeader ( headerPair.name, headerPair.value );
270           }
271    
272           usenetMessage.setBody ( messageBody );
273    
274           return NntpLib.post (
275             nntpServer, username, password, usenetMessage, log );
276         }
277    */
278    
279         //////////////////////////////////////////////////////////////////////
280         //////////////////////////////////////////////////////////////////////
281    
282         private  NntpLib ( ) { }
283    
284         //////////////////////////////////////////////////////////////////////
285         //////////////////////////////////////////////////////////////////////
286         }