/[classpath]/inetlib/source/gnu/inet/nntp/NNTPConnection.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/nntp/NNTPConnection.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by dog, Sun Oct 19 08:51:37 2003 UTC revision 1.2 by dog, Sun Oct 19 16:16:50 2003 UTC
# Line 54  import gnu.inet.util.MessageInputStream; Line 54  import gnu.inet.util.MessageInputStream;
54   * @author <a hef='mailto:dog@gnu.org'>Chris Burdess</a>   * @author <a hef='mailto:dog@gnu.org'>Chris Burdess</a>
55   * @version $Revision$ $Date$   * @version $Revision$ $Date$
56   */   */
57  public class NNTPConnection  public class NNTPConnection implements NNTPConstants
   implements NNTPConstants  
58  {  {
59    
60    /**    /**
61     * The default NNTP port.     * The default NNTP port.
62     */     */
63    public static final int DEFAULT_PORT = 119;    public static final int DEFAULT_PORT = 119;
64      
65    /**    /**
66     * The hostname of the host we are connected to.     * The hostname of the host we are connected to.
67     */     */
# Line 93  public class NNTPConnection Line 92  public class NNTPConnection
92     */     */
93    protected LineInputStream in;    protected LineInputStream in;
94    
95          /**          /**
96           * The socket output stream.           * The socket output stream.
97           */           */
98          protected OutputStream out;    protected OutputStream out;
99    
100    /**    /**
101     * Whether the host permits posting of articles.     * Whether the host permits posting of articles.
# Line 119  public class NNTPConnection Line 118  public class NNTPConnection
118    protected boolean debug;    protected boolean debug;
119    
120    private static final String DOT = ".";    private static final String DOT = ".";
121          private static final String US_ASCII = "US-ASCII";    private static final String US_ASCII = "US-ASCII";
122      
123    /**    /**
124     * Creates a new connection object.     * Creates a new connection object.
125     * @param hostname the hostname or IP address of the news server     * @param hostname the hostname or IP address of the news server
126     */     */
127    public NNTPConnection(String hostname)    public NNTPConnection(String hostname) throws IOException
     throws IOException  
128    {    {
129      this(hostname, DEFAULT_PORT, null, null, false);      this(hostname, DEFAULT_PORT, null, null, false);
130    }    }
131      
132    /**    /**
133     * Creates a new connection object.     * Creates a new connection object.
134     * @param hostname the hostname or IP address of the news server     * @param hostname the hostname or IP address of the news server
135     * @param port the port to connect to     * @param port the port to connect to
136     */     */
137    public NNTPConnection(String hostname,    public NNTPConnection(String hostname, int port) throws IOException
       int port)  
     throws IOException  
138    {    {
139      this(hostname, port, null, null, false);      this(hostname, port, null, null, false);
140    }    }
141      
142    /**    /**
143     * Creates a new connection object.     * Creates a new connection object.
144     * @param hostname the hostname or IP address of the news server     * @param hostname the hostname or IP address of the news server
# Line 150  public class NNTPConnection Line 146  public class NNTPConnection
146     * @param password the password if authentication is required     * @param password the password if authentication is required
147     */     */
148    public NNTPConnection(String hostname,    public NNTPConnection(String hostname,
149        String username,                          String username, String password) throws IOException
       String password)  
     throws IOException  
150    {    {
151      this(hostname, DEFAULT_PORT, username, password, false);      this(hostname, DEFAULT_PORT, username, password, false);
152    }    }
153      
154    /**    /**
155     * Creates a new connection object.     * Creates a new connection object.
156     * @param hostname the hostname or IP address of the news server     * @param hostname the hostname or IP address of the news server
# Line 165  public class NNTPConnection Line 159  public class NNTPConnection
159     * @param password the password if authentication is required     * @param password the password if authentication is required
160     */     */
161    public NNTPConnection(String hostname,    public NNTPConnection(String hostname,
162        int port,                          int port,
163        String username,                          String username, String password) throws IOException
       String password)  
     throws IOException  
164    {    {
165      this(hostname, port, username, password, false);      this(hostname, port, username, password, false);
166    }    }
167      
168    /**    /**
169     * Creates a new connection object.     * Creates a new connection object.
170     * @param hostname the hostname or IP address of the news server     * @param hostname the hostname or IP address of the news server
# Line 182  public class NNTPConnection Line 174  public class NNTPConnection
174     * @param debug whether to use debugging     * @param debug whether to use debugging
175     */     */
176    public NNTPConnection(String hostname,    public NNTPConnection(String hostname,
177        int port,                          int port,
178        String username,                          String username,
179        String password,                          String password, boolean debug) throws IOException
       boolean debug)  
     throws IOException  
180    {    {
181      if (port<0)      if (port < 0)
182        port = DEFAULT_PORT;        port = DEFAULT_PORT;
183        
184      this.hostname = hostname;      this.hostname = hostname;
185      this.port = port;      this.port = port;
186      this.username = username;      this.username = username;
# Line 199  public class NNTPConnection Line 189  public class NNTPConnection
189    
190      // Set up the socket and streams      // Set up the socket and streams
191      socket = new Socket(hostname, port);      socket = new Socket(hostname, port);
192                  InputStream in = socket.getInputStream();      InputStream in = socket.getInputStream();
193                  in = new CRLFInputStream(in);        in = new CRLFInputStream(in);
194                  this.in = new LineInputStream(in);        this.in = new LineInputStream(in);
195                  OutputStream out = socket.getOutputStream();      OutputStream out = socket.getOutputStream();
196                  this.out = new CRLFOutputStream(out);        this.out = new CRLFOutputStream(out);
197    
198      // Read the welcome message (RFC977:2.4.3)      // Read the welcome message (RFC977:2.4.3)
199      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
200      switch (response.status)      switch (response.status)
201      {      {
202        case POSTING_ALLOWED:      case POSTING_ALLOWED:
203          canPost = true;        canPost = true;
204        case NO_POSTING_ALLOWED:        case NO_POSTING_ALLOWED:welcome = response.getMessage();
205          welcome = response.getMessage();        break;
206          break;        default:throw new NNTPException(response);
       default:  
         throw new NNTPException(response);  
207      }      }
208    
209    }    }
# Line 250  public class NNTPConnection Line 238  public class NNTPConnection
238    /*    /*
239     * Parse the specfied NNTP date text.     * Parse the specfied NNTP date text.
240     */     */
241    Date parseDate(String text)    Date parseDate(String text) throws ParseException
     throws ParseException  
242    {    {
243      DateFormat df = new SimpleDateFormat("yyMMdd HHmmss 'GMT'");      DateFormat df = new SimpleDateFormat("yyMMdd HHmmss 'GMT'");
244      return df.parse(text);        return df.parse(text);
245    }    }
246    
247    // RFC977:3.1 The ARTICLE, BODY, HEAD, and STAT commands    // RFC977:3.1 The ARTICLE, BODY, HEAD, and STAT commands
248      
249    /**    /**
250     * Send an article retrieval request to the server.     * Send an article retrieval request to the server.
251     * @param articleNumber the article number of the article to retrieve     * @param articleNumber the article number of the article to retrieve
# Line 266  public class NNTPConnection Line 253  public class NNTPConnection
253     * message-id, and an iterator over the lines of the article header and     * message-id, and an iterator over the lines of the article header and
254     * body, separated by an empty line     * body, separated by an empty line
255     */     */
256    public ArticleResponse article(int articleNumber)    public ArticleResponse article(int articleNumber) throws IOException
     throws IOException  
257    {    {
258      return articleImpl(ARTICLE, Integer.toString(articleNumber));      return articleImpl(ARTICLE, Integer.toString(articleNumber));
259    }    }
# Line 279  public class NNTPConnection Line 265  public class NNTPConnection
265     * message-id, and an iterator over the lines of the article header and     * message-id, and an iterator over the lines of the article header and
266     * body, separated by an empty line     * body, separated by an empty line
267     */     */
268    public ArticleResponse article(String messageId)    public ArticleResponse article(String messageId) throws IOException
     throws IOException  
269    {    {
270      return articleImpl(ARTICLE, messageId);      return articleImpl(ARTICLE, messageId);
271    }    }
272      
273    /**    /**
274     * Send an article head retrieval request to the server.     * Send an article head retrieval request to the server.
275     * @param articleNumber the article number of the article to head     * @param articleNumber the article number of the article to head
276     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
277     * message-id, and an iterator over the lines of the article header     * message-id, and an iterator over the lines of the article header
278     */     */
279    public ArticleResponse head(int articleNumber)    public ArticleResponse head(int articleNumber) throws IOException
     throws IOException  
280    {    {
281      return articleImpl(HEAD, Integer.toString(articleNumber));      return articleImpl(HEAD, Integer.toString(articleNumber));
282    }    }
# Line 303  public class NNTPConnection Line 287  public class NNTPConnection
287     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
288     * message-id, and an iterator over the lines of the article header     * message-id, and an iterator over the lines of the article header
289     */     */
290    public ArticleResponse head(String messageId)    public ArticleResponse head(String messageId) throws IOException
     throws IOException  
291    {    {
292      return articleImpl(HEAD, messageId);      return articleImpl(HEAD, messageId);
293    }    }
# Line 315  public class NNTPConnection Line 298  public class NNTPConnection
298     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
299     * message-id, and an iterator over the lines of the article body     * message-id, and an iterator over the lines of the article body
300     */     */
301    public ArticleResponse body(int articleNumber)    public ArticleResponse body(int articleNumber) throws IOException
     throws IOException  
302    {    {
303      return articleImpl(BODY, Integer.toString(articleNumber));      return articleImpl(BODY, Integer.toString(articleNumber));
304    }    }
# Line 327  public class NNTPConnection Line 309  public class NNTPConnection
309     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
310     * message-id, and an iterator over the lines of the article body     * message-id, and an iterator over the lines of the article body
311     */     */
312    public ArticleResponse body(String messageId)    public ArticleResponse body(String messageId) throws IOException
     throws IOException  
313    {    {
314      return articleImpl(BODY, messageId);      return articleImpl(BODY, messageId);
315    }    }
# Line 339  public class NNTPConnection Line 320  public class NNTPConnection
320     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
321     * message-id     * message-id
322     */     */
323    public ArticleResponse stat(int articleNumber)    public ArticleResponse stat(int articleNumber) throws IOException
     throws IOException  
324    {    {
325      return articleImpl(STAT, Integer.toString(articleNumber));      return articleImpl(STAT, Integer.toString(articleNumber));
326    }    }
# Line 351  public class NNTPConnection Line 331  public class NNTPConnection
331     * @return an article response consisting of the article number and     * @return an article response consisting of the article number and
332     * message-id     * message-id
333     */     */
334    public ArticleResponse stat(String messageId)    public ArticleResponse stat(String messageId) throws IOException
     throws IOException  
335    {    {
336      return articleImpl(STAT, messageId);      return articleImpl(STAT, messageId);
337    }    }
# Line 365  public class NNTPConnection Line 344  public class NNTPConnection
344    protected ArticleResponse articleImpl(String command, String messageId)    protected ArticleResponse articleImpl(String command, String messageId)
345      throws IOException      throws IOException
346    {    {
347      if (messageId!=null)      if (messageId != null)
348      {      {
349        StringBuffer line = new StringBuffer(command);        StringBuffer line = new StringBuffer(command);
350        line.append(' ');          line.append(' ');
351        line.append(messageId);          line.append(messageId);
352        send(line.toString());          send(line.toString());
353      }      }
354      else      else
355        send(command);          send(command);
356      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
357      switch (response.status)      switch (response.status)
358      {      {
359        case ARTICLE_FOLLOWS:      case ARTICLE_FOLLOWS:
360        case HEAD_FOLLOWS:      case HEAD_FOLLOWS:
361        case BODY_FOLLOWS:      case BODY_FOLLOWS:
362          ArticleResponse aresponse = (ArticleResponse)response;        ArticleResponse aresponse = (ArticleResponse) response;
363          ArticleStream astream = new ArticleStream(new MessageInputStream(in));        ArticleStream astream = new ArticleStream(new MessageInputStream(in));
364          pendingData = astream;        pendingData = astream;
365          aresponse.in = astream;        aresponse.in = astream;
366          return aresponse;        return aresponse;
367        case ARTICLE_RETRIEVED:      case ARTICLE_RETRIEVED:
368          return (ArticleResponse)response;        return (ArticleResponse) response;
369        default:      default:
370          // NO_GROUP_SELECTED        // NO_GROUP_SELECTED
371          // NO_ARTICLE_SELECTED        // NO_ARTICLE_SELECTED
372          // NO_SUCH_ARTICLE_NUMBER        // NO_SUCH_ARTICLE_NUMBER
373          // NO_SUCH_ARTICLE        // NO_SUCH_ARTICLE
374          // NO_PREVIOUS_ARTICLE        // NO_PREVIOUS_ARTICLE
375          // NO_NEXT_ARTICLE        // NO_NEXT_ARTICLE
376          throw new NNTPException(response);        throw new NNTPException(response);
377      }      }
378    }    }
379    
380    // RFC977:3.2 The GROUP command    // RFC977:3.2 The GROUP command
381      
382    /**    /**
383     * Send a group selection command to the server.     * Send a group selection command to the server.
384     * Returns a group status response.     * Returns a group status response.
385     * @param name the name of the group to select     * @param name the name of the group to select
386     */     */
387    public GroupResponse group(String name)    public GroupResponse group(String name) throws IOException
     throws IOException  
388    {    {
389      StringBuffer line = new StringBuffer(GROUP);      StringBuffer line = new StringBuffer(GROUP);
390      line.append(' ');        line.append(' ');
391      line.append(name);        line.append(name);
392      send(line.toString());        send(line.toString());
393      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
394      switch (response.status)      switch (response.status)
395      {      {
396        case GROUP_SELECTED:      case GROUP_SELECTED:
397          return (GroupResponse)response;        return (GroupResponse) response;
398        default:        default:
399          // NO_SUCH_GROUP          // NO_SUCH_GROUP
400          throw new NNTPException(response);        throw new NNTPException(response);
401      }      }
402    }    }
403    
404    // RFC977:3.3 The HELP command    // RFC977:3.3 The HELP command
405      
406    /**    /**
407     * Requests a help listing.     * Requests a help listing.
408     * @return an iterator over a collection of help lines.     * @return an iterator over a collection of help lines.
409     */     */
410    public LineIterator help()    public LineIterator help() throws IOException
     throws IOException  
411    {    {
412      send(HELP);      send(HELP);
413      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
414      switch (response.status)      switch (response.status)
415      {      {
416        case HELP_TEXT:      case HELP_TEXT:
417          LineIterator li = new LineIterator(this);        LineIterator li = new LineIterator(this);
418          pendingData = li;        pendingData = li;
419          return li;        return li;
420        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
421      }      }
422    }    }
423    
424    // RFC977:3.4 The IHAVE command    // RFC977:3.4 The IHAVE command
425      
426    /**    /**
427     * Sends an ihave command indicating that the client has an article with     * Sends an ihave command indicating that the client has an article with
428     * the specified message-id.     * the specified message-id.
# Line 454  public class NNTPConnection Line 430  public class NNTPConnection
430     * @return a PostStream if the server wants the specified article, null     * @return a PostStream if the server wants the specified article, null
431     * otherwise     * otherwise
432     */     */
433    public PostStream ihave(String messageId)    public PostStream ihave(String messageId) throws IOException
     throws IOException  
434    {    {
435      send(IHAVE);      send(IHAVE);
436      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
437      switch (response.status)      switch (response.status)
438      {      {
439        case SEND_TRANSFER_ARTICLE:      case SEND_TRANSFER_ARTICLE:
440          return new PostStream(this, false);        return new PostStream(this, false);
441        case ARTICLE_NOT_WANTED:        case ARTICLE_NOT_WANTED:return null;
442          return null;        default:throw new NNTPException(response);
       default:  
         throw new NNTPException(response);  
443      }      }
444    }    }
445      
446    // RFC(77:3.5 The LAST command    // RFC(77:3.5 The LAST command
447    
448    /**    /**
# Line 477  public class NNTPConnection Line 450  public class NNTPConnection
450     * @return the article number/message-id pair associated with the new     * @return the article number/message-id pair associated with the new
451     * article     * article
452     */     */
453    public ArticleResponse last()    public ArticleResponse last() throws IOException
     throws IOException  
454    {    {
455      return articleImpl(LAST, null);      return articleImpl(LAST, null);
456    }    }
457      
458    // RFC977:3.6 The LIST command    // RFC977:3.6 The LIST command
459      
460    /**    /**
461     * Send a group listing command to the server.     * Send a group listing command to the server.
462     * Returns a GroupIterator. This must be read fully before other commands     * Returns a GroupIterator. This must be read fully before other commands
463     * are issued.     * are issued.
464     */     */
465    public GroupIterator list()    public GroupIterator list() throws IOException
     throws IOException  
466    {    {
467      return listImpl(LIST);      return listImpl(LIST);
468    }    }
469    
470    GroupIterator listImpl(String command)    GroupIterator listImpl(String command) throws IOException
     throws IOException  
471    {    {
472      send(command);      send(command);
473      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
474      switch (response.status)      switch (response.status)
475      {      {
476        case LIST_FOLLOWS:      case LIST_FOLLOWS:
477          GroupIterator gi = new GroupIterator(this);        GroupIterator gi = new GroupIterator(this);
478          pendingData = gi;        pendingData = gi;
479          return gi;        return gi;
480        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
481      }      }
482    }    }
483    
# Line 522  public class NNTPConnection Line 491  public class NNTPConnection
491     * @param since the date from which to list new groups     * @param since the date from which to list new groups
492     * @param distributions if non-null, an array of distributions to match     * @param distributions if non-null, an array of distributions to match
493     */     */
494    public LineIterator newGroups(Date since, String[] distributions)    public LineIterator newGroups(Date since, String[]distributions)
495      throws IOException      throws IOException
496    {    {
497      StringBuffer buffer = new StringBuffer(NEWGROUPS);      StringBuffer buffer = new StringBuffer(NEWGROUPS);
498      buffer.append(' ');        buffer.append(' ');
499      buffer.append(formatDate(since));        buffer.append(formatDate(since));
500      if (distributions!=null)      if (distributions != null)
501      {      {
502        buffer.append(' ');        buffer.append(' ');
503        for (int i=0; i<distributions.length; i++)        for (int i = 0; i < distributions.length; i++)
504        {        {
505          if (i>0)          if (i > 0)
506            buffer.append(',');            buffer.append(',');
507          buffer.append(distributions[i]);          buffer.append(distributions[i]);
508        }        }
509      }      }
510      send (buffer.toString());      send(buffer.toString());
511      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
512      switch (response.status)      switch (response.status)
513      {      {
514        case NEWGROUPS_LIST_FOLLOWS:      case NEWGROUPS_LIST_FOLLOWS:
515          LineIterator li = new LineIterator(this);        LineIterator li = new LineIterator(this);
516          pendingData = li;        pendingData = li;
517          return li;        return li;
518        default:      default:
519          throw new NNTPException(response);        throw new NNTPException(response);
520      }      }
521    }    }
522      
523    // RFC977:3.8 The NEWNEWS command    // RFC977:3.8 The NEWNEWS command
524    
525    /**    /**
# Line 563  public class NNTPConnection Line 532  public class NNTPConnection
532     * @param distributions if non-null, a list of distributions to match     * @param distributions if non-null, a list of distributions to match
533     */     */
534    public LineIterator newNews(String newsgroup, Date since,    public LineIterator newNews(String newsgroup, Date since,
535        String[] distributions)                                String[]distributions) throws IOException
     throws IOException  
536    {    {
537      StringBuffer buffer = new StringBuffer(NEWNEWS);      StringBuffer buffer = new StringBuffer(NEWNEWS);
538      buffer.append(' ');        buffer.append(' ');
539      buffer.append(newsgroup);        buffer.append(newsgroup);
540      buffer.append(' ');        buffer.append(' ');
541      buffer.append(formatDate(since));        buffer.append(formatDate(since));
542      if (distributions!=null)      if (distributions != null)
543      {      {
544        buffer.append(' ');        buffer.append(' ');
545        for (int i=0; i<distributions.length; i++)        for (int i = 0; i < distributions.length; i++)
546        {        {
547          if (i>0)          if (i > 0)
548            buffer.append(',');            buffer.append(',');
549          buffer.append(distributions[i]);          buffer.append(distributions[i]);
550        }        }
551      }      }
552      send (buffer.toString());      send(buffer.toString());
553      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
554      switch (response.status)      switch (response.status)
555      {      {
556        case NEWNEWS_LIST_FOLLOWS:      case NEWNEWS_LIST_FOLLOWS:
557          LineIterator li = new LineIterator(this);        LineIterator li = new LineIterator(this);
558          pendingData = li;        pendingData = li;
559          return li;        return li;
560        default:      default:
561          throw new NNTPException(response);        throw new NNTPException(response);
562      }      }
563    }    }
564      
565    // RFC977:3.9 The NEXT command    // RFC977:3.9 The NEXT command
566      
567    /**    /**
568     * Sends a next article positioning command to the server.     * Sends a next article positioning command to the server.
569     * @return the article number/message-id pair associated with the new     * @return the article number/message-id pair associated with the new
570     * article     * article
571     */     */
572    public ArticleResponse next()    public ArticleResponse next() throws IOException
     throws IOException  
573    {    {
574      return articleImpl(NEXT, null);      return articleImpl(NEXT, null);
575    }    }
576      
577    // RFC977:3.10 The POST command    // RFC977:3.10 The POST command
578    
579    /**    /**
# Line 618  public class NNTPConnection Line 585  public class NNTPConnection
585     * No other method should be called in between.     * No other method should be called in between.
586     * @see #postComplete     * @see #postComplete
587     */     */
588    public OutputStream post()    public OutputStream post() throws IOException
     throws IOException  
589    {    {
590      send(POST);      send(POST);
591      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
592      switch (response.status)      switch (response.status)
593      {      {
594        case SEND_ARTICLE:      case SEND_ARTICLE:
595          return new PostStream(this, false);        return new PostStream(this, false);
596        default:        default:
597          // POSTING_NOT_ALLOWED          // POSTING_NOT_ALLOWED
598          throw new NNTPException(response);        throw new NNTPException(response);
599      }      }
600    }    }
601    
# Line 639  public class NNTPConnection Line 605  public class NNTPConnection
605     * Called by the PostStream during <code>close()</code>.     * Called by the PostStream during <code>close()</code>.
606     * @see #post     * @see #post
607     */     */
608    void postComplete()    void postComplete() throws IOException
     throws IOException  
609    {    {
610      send(DOT);      send(DOT);
611      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
612      switch (response.status)      switch (response.status)
613      {      {
614        case ARTICLE_POSTED:      case ARTICLE_POSTED:
615        case ARTICLE_TRANSFERRED:      case ARTICLE_TRANSFERRED:
616          return;        return;
617        default:        default:
618          // POSTING_FAILED          // POSTING_FAILED
619          // TRANSFER_FAILED          // TRANSFER_FAILED
620          // ARTICLE_REJECTED          // ARTICLE_REJECTED
621          throw new NNTPException(response);        throw new NNTPException(response);
622      }      }
623    }    }
624      
625    // RFC977:3.11 The QUIT command    // RFC977:3.11 The QUIT command
626    
627    /**    /**
628     * Close the connection.     * Close the connection.
629     * After calling this method, no further calls on this object are valid.     * After calling this method, no further calls on this object are valid.
630     */     */
631    public void quit()    public void quit() throws IOException
     throws IOException  
632    {    {
633      send(QUIT);      send(QUIT);
634      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
635      switch (response.status)      switch (response.status)
636      {      {
637        case CLOSING_CONNECTION:      case CLOSING_CONNECTION:
638          socket.close();        socket.close();
639          return;        return;
640        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
641      }      }
642    }    }
643    
# Line 683  public class NNTPConnection Line 646  public class NNTPConnection
646    /**    /**
647     * Indicates to the server that this is a slave connection.     * Indicates to the server that this is a slave connection.
648     */     */
649    public void slave()    public void slave() throws IOException
     throws IOException  
650    {    {
651      send(SLAVE);      send(SLAVE);
652      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
653      switch (response.status)      switch (response.status)
654      {      {
655        case SLAVE_ACKNOWLEDGED:      case SLAVE_ACKNOWLEDGED:
656          break;        break;
657        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
658      }      }
659    }    }
660    
661    // RFC2980:1.1 The CHECK command    // RFC2980:1.1 The CHECK command
662    
663    public boolean check(String messageId)    public boolean check(String messageId) throws IOException
     throws IOException  
664    {    {
665      StringBuffer buffer = new StringBuffer(CHECK);      StringBuffer buffer = new StringBuffer(CHECK);
666      buffer.append(' ');        buffer.append(' ');
667      buffer.append(messageId);        buffer.append(messageId);
668      send(buffer.toString());        send(buffer.toString());
669      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
670      switch (response.status)      switch (response.status)
671      {      {
672        case SEND_ARTICLE_VIA_TAKETHIS:      case SEND_ARTICLE_VIA_TAKETHIS:
673          return true;        return true;
674        case ARTICLE_NOT_WANTED_VIA_TAKETHIS:        case ARTICLE_NOT_WANTED_VIA_TAKETHIS:return false;
         return false;  
675        default:        default:
676          // SERVICE_DISCONTINUED          // SERVICE_DISCONTINUED
677          // TRY_AGAIN_LATER          // TRY_AGAIN_LATER
678          // TRANSFER_PERMISSION_DENIED          // TRANSFER_PERMISSION_DENIED
679          // COMMAND_NOT_RECOGNIZED          // COMMAND_NOT_RECOGNIZED
680          throw new NNTPException(response);        throw new NNTPException(response);
681      }      }
682    }    }
683    
# Line 731  public class NNTPConnection Line 690  public class NNTPConnection
690     *     *
691     * @return true if the server supports streaming mode     * @return true if the server supports streaming mode
692     */     */
693    public boolean modeStream()    public boolean modeStream() throws IOException
     throws IOException  
694    {    {
695      send(MODE_STREAM);      send(MODE_STREAM);
696      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
697      switch (response.status)      switch (response.status)
698      {      {
699        case STREAMING_OK:      case STREAMING_OK:
700          return true;        return true;
701        default:        default:
702          // COMMAND_NOT_RECOGNIZED          // COMMAND_NOT_RECOGNIZED
703          return false;        return false;
704      }      }
705    }    }
706    
# Line 755  public class NNTPConnection Line 713  public class NNTPConnection
713     * stream.     * stream.
714     * @see #takethisComplete     * @see #takethisComplete
715     */     */
716    public OutputStream takethis(String messageId)    public OutputStream takethis(String messageId) throws IOException
     throws IOException  
717    {    {
718      send(TAKETHIS);      send(TAKETHIS);
719      return new PostStream(this, true);      return new PostStream(this, true);
# Line 767  public class NNTPConnection Line 724  public class NNTPConnection
724     * Called by PostStream.close().     * Called by PostStream.close().
725     * @see #takethis     * @see #takethis
726     */     */
727    void takethisComplete()    void takethisComplete() throws IOException
     throws IOException  
728    {    {
729      send(DOT);      send(DOT);
730      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
731      switch (response.status)      switch (response.status)
732      {      {
733        case ARTICLE_TRANSFERRED_OK:      case ARTICLE_TRANSFERRED_OK:
734          return;        return;
735        default:        default:
736          // SERVICE_DISCONTINUED          // SERVICE_DISCONTINUED
737          // ARTICLE_TRANSFER_FAILED          // ARTICLE_TRANSFER_FAILED
738          // TRANSFER_PERMISSION_DENIED          // TRANSFER_PERMISSION_DENIED
739          // COMMAND_NOT_RECOGNIZED          // COMMAND_NOT_RECOGNIZED
740          throw new NNTPException(response);        throw new NNTPException(response);
741      }      }
742    }    }
743    
# Line 798  public class NNTPConnection Line 754  public class NNTPConnection
754     * @param wildmat the wildmat pattern. If null, returns all groups. If no     * @param wildmat the wildmat pattern. If null, returns all groups. If no
755     * groups are matched, returns an empty iterator.     * groups are matched, returns an empty iterator.
756     */     */
757    public GroupIterator listActive(String wildmat)    public GroupIterator listActive(String wildmat) throws IOException
     throws IOException  
758    {    {
759      StringBuffer buffer = new StringBuffer(LIST_ACTIVE);      StringBuffer buffer = new StringBuffer(LIST_ACTIVE);
760      if (wildmat!=null)      if (wildmat != null)
761      {      {
762        buffer.append(' ');        buffer.append(' ');
763        buffer.append(wildmat);        buffer.append(wildmat);
# Line 817  public class NNTPConnection Line 772  public class NNTPConnection
772     * Each ActiveTime object returned provides details of who created the     * Each ActiveTime object returned provides details of who created the
773     * newsgroup and when.     * newsgroup and when.
774     */     */
775    public ActiveTimesIterator listActiveTimes()    public ActiveTimesIterator listActiveTimes() throws IOException
     throws IOException  
776    {    {
777      send(LIST_ACTIVE_TIMES);      send(LIST_ACTIVE_TIMES);
778      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
779      switch (response.status)      switch (response.status)
780      {      {
781        case LIST_FOLLOWS:      case LIST_FOLLOWS:
782          return new ActiveTimesIterator(this);        return new ActiveTimesIterator(this);
783        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
784      }      }
785    }    }
786    
# Line 841  public class NNTPConnection Line 794  public class NNTPConnection
794    
795    // RFC2980:2.1.6 The LIST NEWSGROUPS command    // RFC2980:2.1.6 The LIST NEWSGROUPS command
796    
797          /**          /**
798           * Returns an iterator over the group descriptions for the given groups.           * Returns an iterator over the group descriptions for the given groups.
799           * @param wildmat if non-null, limits the groups in the iterator to the           * @param wildmat if non-null, limits the groups in the iterator to the
800           * specified pattern           * specified pattern
801           * @return an iterator over group name/description pairs           * @return an iterator over group name/description pairs
802           * @see #xgtitle           * @see #xgtitle
803           */           */
804    public PairIterator listNewsgroups(String wildmat)    public PairIterator listNewsgroups(String wildmat) throws IOException
805                  throws IOException    {
806          {      StringBuffer buffer = new StringBuffer(LIST_NEWSGROUPS);
807                  StringBuffer buffer = new StringBuffer(LIST_NEWSGROUPS);      if (wildmat != null)
808                  if (wildmat!=null)      {
809                  {        buffer.append(' ');
810                          buffer.append(' ');        buffer.append(wildmat);
811                          buffer.append(wildmat);      }
812                  }      send(buffer.toString());
813                  send(buffer.toString());      StatusResponse response = parseResponse(read());
814                  StatusResponse response = parseResponse(read());      switch (response.status)
815                  switch (response.status)      {
816                  {      case LIST_FOLLOWS:
817                          case LIST_FOLLOWS:        PairIterator pi = new PairIterator(this);
818                                  PairIterator pi = new PairIterator(this);        pendingData = pi;
819                                  pendingData = pi;        return pi;
820                                  return pi;      default:
821                          default:        throw new NNTPException(response);
822                                  throw new NNTPException(response);      }
823                  }    }
         }  
824    
825    // RFC2980:2.1.7 The LIST OVERVIEW.FMT command    // RFC2980:2.1.7 The LIST OVERVIEW.FMT command
826    
# Line 878  public class NNTPConnection Line 830  public class NNTPConnection
830     * Each line returned by the iterator contains one header field.     * Each line returned by the iterator contains one header field.
831     * @see #xover     * @see #xover
832     */     */
833    public LineIterator listOverviewFmt()    public LineIterator listOverviewFmt() throws IOException
     throws IOException  
834    {    {
835      send(LIST_OVERVIEW_FMT);      send(LIST_OVERVIEW_FMT);
836      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
837      switch (response.status)      switch (response.status)
838      {      {
839        case LIST_FOLLOWS:      case LIST_FOLLOWS:
840          LineIterator li = new LineIterator(this);        LineIterator li = new LineIterator(this);
841          pendingData = li;        pendingData = li;
842          return li;        return li;
843        default:        default:throw new NNTPException(response);
         throw new NNTPException(response);  
844      }      }
845    }    }
846    
# Line 899  public class NNTPConnection Line 849  public class NNTPConnection
849    /**    /**
850     * Returns a list of newsgroups suitable for new users of the server.     * Returns a list of newsgroups suitable for new users of the server.
851     */     */
852    public GroupIterator listSubscriptions()    public GroupIterator listSubscriptions() throws IOException
     throws IOException  
853    {    {
854      return listImpl(LIST_SUBSCRIPTIONS);      return listImpl(LIST_SUBSCRIPTIONS);
855    }    }
# Line 913  public class NNTPConnection Line 862  public class NNTPConnection
862           * selected group is assumed.           * selected group is assumed.
863           * @param group the name of the group to list articles for           * @param group the name of the group to list articles for
864           */           */
865    public ArticleNumberIterator listGroup(String group)    public ArticleNumberIterator listGroup(String group) throws IOException
866                  throws IOException    {
867          {      StringBuffer buffer = new StringBuffer(LIST_NEWSGROUPS);
868                  StringBuffer buffer = new StringBuffer(LIST_NEWSGROUPS);      if (group != null)
869                  if (group!=null)      {
870                  {        buffer.append(' ');
871                          buffer.append(' ');        buffer.append(group);
872                          buffer.append(group);      }
873                  }      send(buffer.toString());
874                  send(buffer.toString());      StatusResponse response = parseResponse(read());
875                  StatusResponse response = parseResponse(read());      switch (response.status)
876                  switch (response.status)      {
877                  {      case GROUP_SELECTED:
878                          case GROUP_SELECTED:        ArticleNumberIterator ani = new ArticleNumberIterator(this);
879                                  ArticleNumberIterator ani = new ArticleNumberIterator(this);        pendingData = ani;
880                                  pendingData = ani;        return ani;
881                                  return ani;      default:
882                          default:        throw new NNTPException(response);
883                                  throw new NNTPException(response);      }
884                  }    }
         }  
885    
886    
887    // RFC2980:2.3 The MODE READER command    // RFC2980:2.3 The MODE READER command
# Line 942  public class NNTPConnection Line 890  public class NNTPConnection
890     * Indicates to the server that this is a user-agent.     * Indicates to the server that this is a user-agent.
891     * @return true if posting is allowed, false otherwise.     * @return true if posting is allowed, false otherwise.
892     */     */
893    public boolean modeReader()    public boolean modeReader() throws IOException
     throws IOException  
894    {    {
895      send(MODE_READER);      send(MODE_READER);
896      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
897      switch (response.status)      switch (response.status)
898      {      {
899        case POSTING_ALLOWED:      case POSTING_ALLOWED:
900          canPost = true;        canPost = true;
901          return canPost;        return canPost;
902        case POSTING_NOT_ALLOWED:        case POSTING_NOT_ALLOWED:canPost = false;
903          canPost = false;        return canPost;
904          return canPost;        default:throw new NNTPException(response);
       default:  
         throw new NNTPException(response);  
905      }      }
906    }    }
907    
# Line 966  public class NNTPConnection Line 911  public class NNTPConnection
911     * Returns an iterator over the list of newsgroup descriptions.     * Returns an iterator over the list of newsgroup descriptions.
912     * @param wildmat if non-null, the newsgroups to match     * @param wildmat if non-null, the newsgroups to match
913     */     */
914    public PairIterator xgtitle(String wildmat)    public PairIterator xgtitle(String wildmat) throws IOException
     throws IOException  
915    {    {
916      StringBuffer buffer = new StringBuffer(XGTITLE);      StringBuffer buffer = new StringBuffer(XGTITLE);
917      if (wildmat!=null)      if (wildmat != null)
918      {      {
919        buffer.append(' ');        buffer.append(' ');
920        buffer.append(wildmat);        buffer.append(wildmat);
# Line 979  public class NNTPConnection Line 923  public class NNTPConnection
923      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
924      switch (response.status)      switch (response.status)
925      {      {
926        case XGTITLE_LIST_FOLLOWS:      case XGTITLE_LIST_FOLLOWS:
927          PairIterator pi = new PairIterator(this);        PairIterator pi = new PairIterator(this);
928          pendingData = pi;        pendingData = pi;
929          return pi;        return pi;
930        default:      default:
931          throw new NNTPException(response);        throw new NNTPException(response);
932      }      }
933    }    }
934    
935    // RFC2980:2.6 The XHDR command    // RFC2980:2.6 The XHDR command
936    
937    public HeaderIterator xhdr(String header, String range)    public HeaderIterator xhdr(String header, String range) throws IOException
     throws IOException  
938    {    {
939      StringBuffer buffer = new StringBuffer(XHDR);      StringBuffer buffer = new StringBuffer(XHDR);
940      buffer.append(' ');        buffer.append(' ');
941      buffer.append(header);        buffer.append(header);
942      if (range!=null)      if (range != null)
943      {      {
944        buffer.append(' ');        buffer.append(' ');
945        buffer.append(range);        buffer.append(range);
# Line 1005  public class NNTPConnection Line 948  public class NNTPConnection
948      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
949      switch (response.status)      switch (response.status)
950      {      {
951        case HEAD_FOLLOWS:      case HEAD_FOLLOWS:
952          HeaderIterator hi = new HeaderIterator(this);        HeaderIterator hi = new HeaderIterator(this);
953          pendingData = hi;        pendingData = hi;
954          return hi;        return hi;
955        default:      default:
956          // NO_GROUP_SELECTED        // NO_GROUP_SELECTED
957          // NO_SUCH_ARTICLE        // NO_SUCH_ARTICLE
958          throw new NNTPException(response);        throw new NNTPException(response);
959      }      }
960    }    }
961    
# Line 1022  public class NNTPConnection Line 965  public class NNTPConnection
965    
966    // RFC2980:2.8 The XOVER command    // RFC2980:2.8 The XOVER command
967    
968    public OverviewIterator xover(Range range)    public OverviewIterator xover(Range range) throws IOException
     throws IOException  
969    {    {
970      StringBuffer buffer = new StringBuffer(XOVER);      StringBuffer buffer = new StringBuffer(XOVER);
971      if (range!=null)      if (range != null)
972      {      {
973        buffer.append(' ');        buffer.append(' ');
974        buffer.append(range.toString());        buffer.append(range.toString());
975      }      }
976      send (buffer.toString());      send(buffer.toString());
977      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
978      switch (response.status)      switch (response.status)
979      {      {
980        case OVERVIEW_FOLLOWS:      case OVERVIEW_FOLLOWS:
981          OverviewIterator oi = new OverviewIterator(this);        OverviewIterator oi = new OverviewIterator(this);
982          pendingData = oi;        pendingData = oi;
983          return oi;        return oi;
984        default:      default:
985          // NO_GROUP_SELECTED        // NO_GROUP_SELECTED
986          // PERMISSION_DENIED        // PERMISSION_DENIED
987          throw new NNTPException(response);        throw new NNTPException(response);
988      }      }
989    }    }
990    
# Line 1070  public class NNTPConnection Line 1012  public class NNTPConnection
1012     * @param password the (cleartext) password     * @param password the (cleartext) password
1013     * @return true on success, false on failure     * @return true on success, false on failure
1014     */     */
1015    public boolean authinfo(String username, String password)    public boolean authinfo(String username, String password) throws IOException
     throws IOException  
1016    {    {
1017      StringBuffer buffer = new StringBuffer(AUTHINFO_USER);      StringBuffer buffer = new StringBuffer(AUTHINFO_USER);
1018      buffer.append(' ');        buffer.append(' ');
1019      buffer.append(username);        buffer.append(username);
1020      send(buffer.toString());        send(buffer.toString());
1021      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
1022      switch (response.status)      switch (response.status)
1023      {      {
1024        case AUTHINFO_OK:
1025          return true;
1026          case SEND_AUTHINFOPASS:buffer.setLength(0);
1027          buffer.append(AUTHINFO_PASS);
1028          buffer.append(' ');
1029          buffer.append(password);
1030          send(buffer.toString());
1031          response = parseResponse(read());
1032          switch (response.status)
1033          {
1034        case AUTHINFO_OK:        case AUTHINFO_OK:
1035          return true;          return true;
1036        case SEND_AUTHINFOPASS:          case PERMISSION_DENIED:return false;
1037          buffer.setLength(0);          default:throw new NNTPException(response);
1038          buffer.append(AUTHINFO_PASS);        }
         buffer.append(' ');  
         buffer.append(password);  
         send(buffer.toString());  
         response = parseResponse(read());  
         switch (response.status)  
         {  
           case AUTHINFO_OK:  
             return true;  
           case PERMISSION_DENIED:  
             return false;  
           default:  
             throw new NNTPException(response);  
         }  
1039        default:        default:
1040          // AUTHINFO_REJECTED          // AUTHINFO_REJECTED
1041          throw new NNTPException(response);          throw new NNTPException(response);
# Line 1118  public class NNTPConnection Line 1056  public class NNTPConnection
1056      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
1057      switch (response.status)      switch (response.status)
1058      {      {
1059        case SEND_AUTHINFO_SIMPLE:      case SEND_AUTHINFO_SIMPLE:
1060          StringBuffer buffer = new StringBuffer(username);        StringBuffer buffer = new StringBuffer(username);
1061          buffer.append(' ');        buffer.append(' ');
1062          buffer.append(password);        buffer.append(password);
1063          send(buffer.toString());        send(buffer.toString());
1064          response = parseResponse(read());        response = parseResponse(read());
1065          switch (response.status)        switch (response.status)
1066          {        {
1067            case AUTHINFO_SIMPLE_OK:        case AUTHINFO_SIMPLE_OK:
1068              return true;          return true;
1069            case AUTHINFO_SIMPLE_DENIED:          case AUTHINFO_SIMPLE_DENIED:return false;
1070              return false;          default:throw new NNTPException(response);
1071            default:        }
1072              throw new NNTPException(response);        default:throw new NNTPException(response);
         }  
       default:  
         throw new NNTPException(response);  
1073      }      }
1074    }    }
1075    
# Line 1149  public class NNTPConnection Line 1084  public class NNTPConnection
1084      throws IOException      throws IOException
1085    {    {
1086      StringBuffer buffer = new StringBuffer(AUTHINFO_GENERIC);      StringBuffer buffer = new StringBuffer(AUTHINFO_GENERIC);
1087      buffer.append(' ');        buffer.append(' ');
1088      buffer.append(authenticator);        buffer.append(authenticator);
1089      buffer.append(' ');        buffer.append(' ');
1090      buffer.append(args);        buffer.append(args);
1091      send(buffer.toString());        send(buffer.toString());
1092      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
1093      switch (response.status)      switch (response.status)
1094      {      {
1095        case COMMAND_NOT_RECOGNIZED:      case COMMAND_NOT_RECOGNIZED:
1096        case SYNTAX_ERROR:      case SYNTAX_ERROR:
1097        case INTERNAL_ERROR:      case INTERNAL_ERROR:
1098          throw new NNTPException(response);        throw new NNTPException(response);
1099        default:        default:
1100          // TODO attempt to connect authenticator          // TODO attempt to connect authenticator
1101          // ... do stuff ...          // ... do stuff ...
# Line 1175  public class NNTPConnection Line 1110  public class NNTPConnection
1110    /**    /**
1111     * Returns the date on the server.     * Returns the date on the server.
1112     */     */
1113    public Date date()    public Date date() throws IOException
     throws IOException  
1114    {    {
1115      send(DATE);      send(DATE);
1116      StatusResponse response = parseResponse(read());      StatusResponse response = parseResponse(read());
1117      switch (response.status)      switch (response.status)
1118      {      {
1119        case DATE_OK:      case DATE_OK:
1120          String message = response.getMessage();        String message = response.getMessage();
1121          try        try
1122          {        {
1123            DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");          DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
1124            return df.parse(message);            return df.parse(message);
1125          }        }
1126          catch (ParseException e)        catch(ParseException e)
1127          {        {
1128            throw new IOException("Invalid date: "+message);          throw new IOException("Invalid date: " + message);
1129          }        }
1130        default:      default:
1131          throw new NNTPException(response);        throw new NNTPException(response);
1132      }      }
1133    }    }
1134    
# Line 1209  public class NNTPConnection Line 1143  public class NNTPConnection
1143      String statusText = line;      String statusText = line;
1144      String message = null;      String message = null;
1145      end = line.indexOf(' ', start);      end = line.indexOf(' ', start);
1146      if (end>start)      if (end > start)
1147      {      {
1148        statusText = line.substring(start, end);        statusText = line.substring(start, end);
1149        message = line.substring(end+1);        message = line.substring(end + 1);
1150      }      }
1151      short status = Short.parseShort(statusText);      short status = Short.parseShort(statusText);
1152      StatusResponse response;      StatusResponse response;
1153      switch (status)      switch (status)
1154      {      {
1155        case ARTICLE_FOLLOWS:      case ARTICLE_FOLLOWS:
1156        case HEAD_FOLLOWS:      case HEAD_FOLLOWS:
1157        case BODY_FOLLOWS:      case BODY_FOLLOWS:
1158        case ARTICLE_RETRIEVED:      case ARTICLE_RETRIEVED:
1159          try        try
1160          {        {
1161            ArticleResponse aresponse = new ArticleResponse(status, message);          ArticleResponse aresponse = new ArticleResponse(status, message);
1162            // article number          // article number
1163            start = end+1;          start = end + 1;
           end = line.indexOf(' ', start);  
           if (end>start)  
             aresponse.articleNumber =  
               Integer.parseInt(line.substring(start, end));  
           // message-id  
           start = end+1;  
           end = line.indexOf(' ', start);  
           if (end>start)  
             aresponse.messageId = line.substring(start, end);  
           else  
             aresponse.messageId = line.substring(start);  
           response = aresponse;  
         }  
         catch (NumberFormatException e)  
         {  
           // This will happen for XHDR  
           response = new StatusResponse(status, message);  
         }  
         break;  
       case GROUP_SELECTED:  
         GroupResponse gresponse = new GroupResponse(status, message);  
         // count  
         start = end+1;  
         end = line.indexOf(' ', start);  
         if (end>start)  
           gresponse.count = Integer.parseInt(line.substring(start, end));  
         // first  
         start = end+1;  
         end = line.indexOf(' ', start);  
         if (end>start)  
           gresponse.first = Integer.parseInt(line.substring(start, end));  
         // last  
         start = end+1;  
1164          end = line.indexOf(' ', start);          end = line.indexOf(' ', start);
1165          if (end>start)          if (end > start)
1166            gresponse.last = Integer.parseInt(line.substring(start, end));            aresponse.articleNumber =
1167          // group              Integer.parseInt(line.substring(start, end));
1168          start = end+1;          // message-id
1169            start = end + 1;
1170          end = line.indexOf(' ', start);          end = line.indexOf(' ', start);
1171          if (end>start)          if (end > start)
1172            gresponse.group = line.substring(start, end);            aresponse.messageId = line.substring(start, end);
1173          else          else
1174            gresponse.group = line.substring(start);            aresponse.messageId = line.substring(start);
1175          response = gresponse;          response = aresponse;
1176          break;        }
1177        default:        catch(NumberFormatException e)
1178          {
1179            // This will happen for XHDR
1180          response = new StatusResponse(status, message);          response = new StatusResponse(status, message);
1181          }
1182          break;
1183        case GROUP_SELECTED:
1184          GroupResponse gresponse = new GroupResponse(status, message);
1185          // count
1186          start = end + 1;
1187          end = line.indexOf(' ', start);
1188          if (end > start)
1189            gresponse.count = Integer.parseInt(line.substring(start, end));
1190          // first
1191          start = end + 1;
1192          end = line.indexOf(' ', start);
1193          if (end > start)
1194            gresponse.first = Integer.parseInt(line.substring(start, end));
1195          // last
1196          start = end + 1;
1197          end = line.indexOf(' ', start);
1198          if (end > start)
1199            gresponse.last = Integer.parseInt(line.substring(start, end));
1200          // group
1201          start = end + 1;
1202          end = line.indexOf(' ', start);
1203          if (end > start)
1204            gresponse.group = line.substring(start, end);
1205          else
1206            gresponse.group = line.substring(start);
1207          response = gresponse;
1208          break;
1209        default:
1210          response = new StatusResponse(status, message);
1211      }      }
1212      return response;      return response;
1213    }    }
# Line 1282  public class NNTPConnection Line 1216  public class NNTPConnection
1216     * Send a single line to the server.     * Send a single line to the server.
1217     * @param line the line to send     * @param line the line to send
1218     */     */
1219    protected void send(String line)    protected void send(String line) throws IOException
     throws IOException  
1220    {    {
1221      if (pendingData!=null)      if (pendingData != null)
1222      {      {
1223        // Clear pending data        // Clear pending data
1224                          pendingData.readToEOF();        pendingData.readToEOF();
1225        pendingData = null;        pendingData = null;
1226      }      }
1227      if (debug)      if (debug)
1228                  {      {
1229                          Logger logger = Logger.getInstance();        Logger logger = Logger.getInstance();
1230        logger.log("nntp", ">"+line);        logger.log("nntp", ">" + line);
1231                  }      }
1232      byte[] data = line.getBytes(US_ASCII);      byte[]data = line.getBytes(US_ASCII);
1233                  out.write(data);      out.write(data);
1234                  out.write('\n');      out.write('\n');
1235                  out.flush();      out.flush();
1236    }    }
1237    
1238    /**    /**
1239     * Read a single line from the server.     * Read a single line from the server.
1240     * @return a line of text     * @return a line of text
1241     */     */
1242    protected String read()    protected String read() throws IOException
     throws IOException  
1243    {    {
1244      String line = in.readLine();      String line = in.readLine();
1245      if (debug)      if (debug)
1246                  {      {
1247                          Logger logger = Logger.getInstance();        Logger logger = Logger.getInstance();
1248                          if (line==null)        if (line == null)
1249                                  logger.log("nntp", "<EOF");          logger.log("nntp", "<EOF");
1250                          else        else
1251                                  logger.log("nntp", "<"+line);            logger.log("nntp", "<" + line);
1252                  }      }
1253      return line;      return line;
1254    }    }
1255    

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26