trunk/com/so/news/NNTPConnection.java
changeset 1 6fceb66e1ad7
parent 0 f907866f0e4b
child 2 1090e2141798
     1.1 --- a/trunk/com/so/news/NNTPConnection.java	Tue Jan 20 10:21:03 2009 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,395 +0,0 @@
     1.4 -/*
     1.5 - *   StarOffice 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 com.so.news;
    1.23 -
    1.24 -import java.io.BufferedReader;
    1.25 -import java.io.BufferedWriter;
    1.26 -import java.io.File;
    1.27 -import java.io.InputStreamReader;
    1.28 -import java.io.IOException;
    1.29 -import java.io.OutputStreamWriter;
    1.30 -import java.net.Socket;
    1.31 -import java.net.SocketException;
    1.32 -import java.text.SimpleDateFormat;
    1.33 -import java.util.Date;
    1.34 -import java.util.LinkedList;
    1.35 -import java.util.List;
    1.36 -import com.so.news.command.ArticleCommand;
    1.37 -import com.so.news.command.GroupCommand;
    1.38 -import com.so.news.command.ListCommand;
    1.39 -import com.so.news.command.PostCommand;
    1.40 -import com.so.news.command.OverCommand;
    1.41 -import com.so.news.storage.Article;
    1.42 -import com.so.news.storage.Group;
    1.43 -
    1.44 -/**
    1.45 - * Represents the connection between the server and one client.
    1.46 - * @author Christian Lins (christian.lins@web.de)
    1.47 - */
    1.48 -public class NNTPConnection extends Thread
    1.49 -{
    1.50 -  public static final String NEWLINE            = "\r\n";
    1.51 -  public static final String MESSAGE_ID_PATTERN = "<[^>]+>";
    1.52 -  
    1.53 -  private boolean            debug              
    1.54 -    = Boolean.parseBoolean(Config.getInstance().get("n3tpd.debug", "false"));
    1.55 -  private Socket             socket;
    1.56 -  private boolean            exit               = false;
    1.57 -  private BufferedWriter     out;
    1.58 -  private BufferedReader     in;
    1.59 -  private Article            currentArticle     = null;
    1.60 -  private Group              currentGroup       = null;
    1.61 -
    1.62 -  /**
    1.63 -   * Creates a new NNTPConnection instance using the given connected Socket.
    1.64 -   * @param socket
    1.65 -   * @throws java.io.IOException
    1.66 -   */
    1.67 -  public NNTPConnection(Socket socket) 
    1.68 -    throws IOException
    1.69 -  {
    1.70 -    this.socket = socket;
    1.71 -    this.in     = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    1.72 -    this.out    = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    1.73 -    // TODO: The output stream should be of type PrintStream so that many
    1.74 -    // of the printX() methods of this class can go to trash
    1.75 -    
    1.76 -    setDaemon(true); // Exits if the main thread is killed
    1.77 -  }
    1.78 -
    1.79 -  /**
    1.80 -   * Closes the associated socket end exits the Thread.
    1.81 -   */
    1.82 -  public void exit()
    1.83 -  {
    1.84 -    try
    1.85 -    {
    1.86 -      exit = true;
    1.87 -      socket.close();
    1.88 -    }
    1.89 -    catch (Exception e)
    1.90 -    {
    1.91 -      e.printStackTrace();
    1.92 -    }
    1.93 -  }
    1.94 -
    1.95 -  /**
    1.96 -   * Prints a CharSequence to the sockets output stream.
    1.97 -   */
    1.98 -  public void print(CharSequence s) throws IOException
    1.99 -  {
   1.100 -    out.append(s);
   1.101 -  }
   1.102 -
   1.103 -  public void println(CharSequence s) throws IOException
   1.104 -  {
   1.105 -    print(s);
   1.106 -    print(NEWLINE);
   1.107 -    if (debug)
   1.108 -      System.out.println("<<< " + s);
   1.109 -  }
   1.110 -
   1.111 -  public void printStatus(int code, String description) throws IOException
   1.112 -  {
   1.113 -    println("" + code + " " + description);
   1.114 -    flush();
   1.115 -  }
   1.116 -
   1.117 -  public void printTextLine(CharSequence line) throws IOException
   1.118 -  {
   1.119 -    if (line.length() > 0 && line.charAt(0) == '.')
   1.120 -      print("..");
   1.121 -    println(line);
   1.122 -  }
   1.123 -
   1.124 -  public void printTextPart(CharSequence text) throws IOException
   1.125 -  {
   1.126 -    String[] lines = text.toString().split(NEWLINE);
   1.127 -    for (String line : lines)
   1.128 -      printTextLine(line);
   1.129 -  }
   1.130 -
   1.131 -  public void printText(CharSequence text) throws IOException
   1.132 -  {
   1.133 -    printTextPart(text);
   1.134 -    println(".");
   1.135 -    flush();
   1.136 -  }
   1.137 -
   1.138 -  public void flush() throws IOException
   1.139 -  {
   1.140 -    out.flush();
   1.141 -  }
   1.142 -
   1.143 -  public String readln() throws IOException
   1.144 -  {
   1.145 -    String s = in.readLine();
   1.146 -    if (s == null)
   1.147 -      throw new IOException("Socket closed");
   1.148 -    if (debug)
   1.149 -      System.out.println(">>> " + s);
   1.150 -    return s;
   1.151 -  }
   1.152 -
   1.153 -  public String[] readCommand() throws IOException
   1.154 -  {
   1.155 -    return readln().split("[ ]+");
   1.156 -  }
   1.157 -
   1.158 -  public List<String> readText() throws IOException
   1.159 -  {
   1.160 -    List<String> l = new LinkedList<String>();
   1.161 -    String s;
   1.162 -    do
   1.163 -    {
   1.164 -      s = readln();
   1.165 -      if (!s.equals("."))
   1.166 -      {
   1.167 -        if (s.startsWith(".."))
   1.168 -          s = s.substring(1);
   1.169 -        l.add(s);
   1.170 -      }
   1.171 -    }
   1.172 -    while (!s.equals("."));
   1.173 -    return l;
   1.174 -  }
   1.175 -
   1.176 -  public String readTextLine() throws IOException
   1.177 -  {
   1.178 -    String s = null;
   1.179 -    do
   1.180 -    {
   1.181 -      s = readln();
   1.182 -    }
   1.183 -    while (s == null);
   1.184 -    if (s.equals("."))
   1.185 -      return null;
   1.186 -    if (s.startsWith(".."))
   1.187 -      s = s.substring(1);
   1.188 -    return s;
   1.189 -  }
   1.190 -
   1.191 -  public void setCurrentArticle(Article current)
   1.192 -  {
   1.193 -    currentArticle = current;
   1.194 -  }
   1.195 -
   1.196 -  public Article getCurrentArticle()
   1.197 -  {
   1.198 -    return currentArticle;
   1.199 -  }
   1.200 -
   1.201 -  public void setCurrentGroup(Group current)
   1.202 -  {
   1.203 -    currentGroup = current;
   1.204 -  }
   1.205 -
   1.206 -  public Group getCurrentGroup()
   1.207 -  {
   1.208 -    return currentGroup;
   1.209 -  }
   1.210 -
   1.211 -  private void processCommand(String[] command) 
   1.212 -    throws Exception
   1.213 -  {
   1.214 -    if (command.length == 0)
   1.215 -      return; // TODO Error
   1.216 -
   1.217 -    String commandName = command[0];
   1.218 -
   1.219 -    // RFC977
   1.220 -    // TODO HELP command
   1.221 -    // TODO NEWGROUPS command
   1.222 -    // TODO NEWNEWS command
   1.223 -
   1.224 -    // RFC2980
   1.225 -    // TODO LIST ACTIVE command
   1.226 -    // TODO LIST ACTIVE.TIMES command
   1.227 -    // TODO LIST DISTRIBUTIONS command
   1.228 -    // TODO LIST DISTRIB.PATS command
   1.229 -    // TODO XGTITLE command
   1.230 -    // TODO XHDR command
   1.231 -    // TODO XPAT command
   1.232 -    // TODO XPATH command
   1.233 -    // TODO XROVER command
   1.234 -    // TODO XTHREAD command
   1.235 -    // TODO AUTHINFO command
   1.236 -
   1.237 -    // STANDARD COMMANDS
   1.238 -    if (commandName.equalsIgnoreCase("ARTICLE")
   1.239 -        || commandName.equalsIgnoreCase("STAT")
   1.240 -        || commandName.equalsIgnoreCase("HEAD") 
   1.241 -        || commandName.equalsIgnoreCase("BODY"))
   1.242 -    {
   1.243 -      ArticleCommand cmd = new ArticleCommand(this);
   1.244 -      cmd.process(command);
   1.245 -    }
   1.246 -    
   1.247 -    else if (commandName.equalsIgnoreCase("LIST"))
   1.248 -    {
   1.249 -      ListCommand cmd = new ListCommand(this);
   1.250 -      cmd.process(command);
   1.251 -    }
   1.252 -
   1.253 -    else if (commandName.equalsIgnoreCase("GROUP"))
   1.254 -    {
   1.255 -      GroupCommand cmd = new GroupCommand(this);
   1.256 -      cmd.process(command);
   1.257 -    }
   1.258 -    
   1.259 -    else if(commandName.equalsIgnoreCase("POST"))
   1.260 -    {
   1.261 -      PostCommand cmd = new PostCommand(this);
   1.262 -      cmd.process(command);
   1.263 -    }
   1.264 -
   1.265 -    else if (commandName.equalsIgnoreCase("CHECK")
   1.266 -        || commandName.equalsIgnoreCase("TAKETHIS"))
   1.267 -    {
   1.268 -      // untested, RFC2980 compliant
   1.269 -      printStatus(400, "not accepting articles");
   1.270 -      return;
   1.271 -    }
   1.272 -
   1.273 -    else if (commandName.equalsIgnoreCase("IHAVE")
   1.274 -        || commandName.equalsIgnoreCase("XREPLIC"))
   1.275 -    {
   1.276 -      // untested, RFC977 compliant
   1.277 -      printStatus(435, "article not wanted - do not send it");
   1.278 -      return;
   1.279 -    }
   1.280 -
   1.281 -    else if (commandName.equalsIgnoreCase("XCREATEGROUP"))
   1.282 -    {
   1.283 -      return;
   1.284 -    }
   1.285 -
   1.286 -    else if (commandName.equalsIgnoreCase("SLAVE"))
   1.287 -    {
   1.288 -      // untested, RFC977 compliant
   1.289 -      printStatus(202, "slave status noted");
   1.290 -      return;
   1.291 -    }
   1.292 -
   1.293 -    else if (commandName.equalsIgnoreCase("XINDEX"))
   1.294 -    {
   1.295 -      // untested, RFC2980 compliant
   1.296 -      printStatus(418, "no tin-style index is available for this news group");
   1.297 -      return;
   1.298 -    }
   1.299 -
   1.300 -    else if (commandName.equalsIgnoreCase("DATE"))
   1.301 -    {
   1.302 -      printStatus(111, new SimpleDateFormat("yyyyMMddHHmmss")
   1.303 -          .format(new Date()));
   1.304 -      return;
   1.305 -    }
   1.306 -
   1.307 -    else if (commandName.equalsIgnoreCase("MODE"))
   1.308 -    {
   1.309 -      if (command[1].equalsIgnoreCase("READER"))
   1.310 -      {
   1.311 -        // untested, RFC2980 compliant
   1.312 -        printStatus(200, "Hello, you can post");
   1.313 -      }
   1.314 -      else if (command[1].equalsIgnoreCase("STREAM"))
   1.315 -      {
   1.316 -        printStatus(203, "Streaming is OK");
   1.317 -      }
   1.318 -      else
   1.319 -        printStatus(501, "Command not supported");
   1.320 -    }
   1.321 -
   1.322 -    else if (commandName.equalsIgnoreCase("QUIT"))
   1.323 -    {
   1.324 -      // untested, RFC977 compliant
   1.325 -      printStatus(205, "closing connection - goodbye!");
   1.326 -      exit();
   1.327 -      return;
   1.328 -    }  
   1.329 -    
   1.330 -    else if (commandName.equalsIgnoreCase("XSHUTDOWN"))
   1.331 -    {
   1.332 -      printStatus(205, "closing connection - goodbye!");
   1.333 -      exit();
   1.334 -      return;
   1.335 -    }
   1.336 -
   1.337 -    // X COMMANDS
   1.338 -    else if(commandName.equalsIgnoreCase("XOVER")
   1.339 -       || commandName.equalsIgnoreCase("OVER"))
   1.340 -    {
   1.341 -      OverCommand cmd = new OverCommand(this);
   1.342 -      cmd.process(command);
   1.343 -    }
   1.344 -
   1.345 -    else
   1.346 -      printStatus(501, "Command not supported");
   1.347 -  }
   1.348 -
   1.349 -  /**
   1.350 -   * Runloop of this Thread.
   1.351 -   * @throws RuntimeException if this method is called directly.
   1.352 -   */
   1.353 -  @Override
   1.354 -  public void run()
   1.355 -  {
   1.356 -    assert !this.equals(Thread.currentThread());
   1.357 -
   1.358 -    try
   1.359 -    {
   1.360 -      printStatus(200, Config.getInstance().get("n3tpd.hostname", "localhost")
   1.361 -          + " " + Main.VERSION + " news server ready - (posting ok).");
   1.362 -    }
   1.363 -    catch (IOException e1)
   1.364 -    {
   1.365 -      exit();
   1.366 -    }
   1.367 -    
   1.368 -    while (!exit)
   1.369 -    {
   1.370 -      try
   1.371 -      {
   1.372 -        processCommand(readCommand());
   1.373 -      }
   1.374 -      catch (SocketException e)
   1.375 -      {
   1.376 -        if (exit)
   1.377 -          return;
   1.378 -        exit();
   1.379 -        e.printStackTrace();
   1.380 -      }
   1.381 -      catch (IOException e)
   1.382 -      {
   1.383 -        if (exit)
   1.384 -          return;
   1.385 -        exit();
   1.386 -        e.printStackTrace();
   1.387 -      }
   1.388 -      catch (Throwable e)
   1.389 -      {
   1.390 -        if (exit)
   1.391 -          return;
   1.392 -        e.printStackTrace();
   1.393 -        // silently ignore
   1.394 -      }
   1.395 -    }
   1.396 -  }
   1.397 -
   1.398 -}