src/org/sonews/util/io/ArticleReader.java
changeset 35 ed84c8bdd87b
parent 16 5a4a41cfc0a3
child 37 74139325d305
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/org/sonews/util/io/ArticleReader.java	Sun Aug 29 17:28:58 2010 +0200
     1.3 @@ -0,0 +1,135 @@
     1.4 +/*
     1.5 + *   SONEWS News Server
     1.6 + *   see AUTHORS for the list of contributors
     1.7 + *
     1.8 + *   This program is free software: you can redistribute it and/or modify
     1.9 + *   it under the terms of the GNU General Public License as published by
    1.10 + *   the Free Software Foundation, either version 3 of the License, or
    1.11 + *   (at your option) any later version.
    1.12 + *
    1.13 + *   This program is distributed in the hope that it will be useful,
    1.14 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 + *   GNU General Public License for more details.
    1.17 + *
    1.18 + *   You should have received a copy of the GNU General Public License
    1.19 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.20 + */
    1.21 +
    1.22 +package org.sonews.util.io;
    1.23 +
    1.24 +import java.io.BufferedInputStream;
    1.25 +import java.io.BufferedOutputStream;
    1.26 +import java.io.ByteArrayOutputStream;
    1.27 +import java.io.IOException;
    1.28 +import java.io.InputStream;
    1.29 +import java.io.UnsupportedEncodingException;
    1.30 +import java.net.Socket;
    1.31 +import java.net.UnknownHostException;
    1.32 +import org.sonews.config.Config;
    1.33 +import org.sonews.util.Log;
    1.34 +
    1.35 +/**
    1.36 + * Reads an news article from a NNTP server.
    1.37 + * @author Christian Lins
    1.38 + * @since sonews/0.5.0
    1.39 + */
    1.40 +public class ArticleReader 
    1.41 +{
    1.42 +
    1.43 +  private BufferedOutputStream out;
    1.44 +  private BufferedInputStream  in;
    1.45 +  private String               messageID;
    1.46 +  
    1.47 +  public ArticleReader(String host, int port, String messageID)
    1.48 +    throws IOException, UnknownHostException
    1.49 +  {
    1.50 +    this.messageID = messageID;
    1.51 +
    1.52 +    // Connect to NNTP server
    1.53 +    Socket socket = new Socket(host, port);
    1.54 +    this.out = new BufferedOutputStream(socket.getOutputStream());
    1.55 +    this.in  = new BufferedInputStream(socket.getInputStream());
    1.56 +    String line = readln(this.in);
    1.57 +    if(!line.startsWith("200 "))
    1.58 +    {
    1.59 +      throw new IOException("Invalid hello from server: " + line);
    1.60 +    }
    1.61 +  }
    1.62 +  
    1.63 +  private boolean eofArticle(byte[] buf)
    1.64 +  {
    1.65 +    if(buf.length < 4)
    1.66 +    {
    1.67 +      return false;
    1.68 +    }
    1.69 +    
    1.70 +    int l = buf.length - 1;
    1.71 +    return buf[l-3] == 10 // '*\n'
    1.72 +        && buf[l-2] == '.'                   // '.'
    1.73 +        && buf[l-1] == 13 && buf[l] == 10;  // '\r\n'
    1.74 +  }
    1.75 +  
    1.76 +  public byte[] getArticleData()
    1.77 +    throws IOException, UnsupportedEncodingException
    1.78 +  {
    1.79 +    long maxSize = Config.inst().get(Config.ARTICLE_MAXSIZE, 1024) * 1024L;
    1.80 +
    1.81 +    try
    1.82 +    {
    1.83 +      this.out.write(("ARTICLE " + this.messageID + "\r\n").getBytes("UTF-8"));
    1.84 +      this.out.flush();
    1.85 +
    1.86 +      String line = readln(this.in);
    1.87 +      if(line.startsWith("220 "))
    1.88 +      {
    1.89 +        ByteArrayOutputStream buf = new ByteArrayOutputStream();
    1.90 +        
    1.91 +        while(!eofArticle(buf.toByteArray()))
    1.92 +        {
    1.93 +          for(int b = in.read(); b != 10; b = in.read())
    1.94 +          {
    1.95 +            buf.write(b);
    1.96 +          }
    1.97 +
    1.98 +          buf.write(10);
    1.99 +          if(buf.size() > maxSize)
   1.100 +          {
   1.101 +            Log.get().warning("Skipping message that is too large: " + buf.size());
   1.102 +            return null;
   1.103 +          }
   1.104 +        }
   1.105 +        
   1.106 +        return buf.toByteArray();
   1.107 +      }
   1.108 +      else
   1.109 +      {
   1.110 +        Log.get().warning("ArticleReader: " + line);
   1.111 +        return null;
   1.112 +      }
   1.113 +    }
   1.114 +    catch(IOException ex)
   1.115 +    {
   1.116 +      throw ex;
   1.117 +    }
   1.118 +    finally
   1.119 +    {
   1.120 +      this.out.write("QUIT\r\n".getBytes("UTF-8"));
   1.121 +      this.out.flush();
   1.122 +      this.out.close();
   1.123 +    }
   1.124 +  }
   1.125 +  
   1.126 +  private String readln(InputStream in)
   1.127 +    throws IOException
   1.128 +  {
   1.129 +    ByteArrayOutputStream buf = new ByteArrayOutputStream();
   1.130 +    for(int b = in.read(); b != 10 /* \n */; b = in.read())
   1.131 +    {
   1.132 +      buf.write(b);
   1.133 +    }
   1.134 +    
   1.135 +    return new String(buf.toByteArray());
   1.136 +  }
   1.137 +
   1.138 +}