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 -}