chris@0: /*
chris@0: * StarOffice News Server
chris@0: * see AUTHORS for the list of contributors
chris@0: *
chris@0: * This program is free software: you can redistribute it and/or modify
chris@0: * it under the terms of the GNU General Public License as published by
chris@0: * the Free Software Foundation, either version 3 of the License, or
chris@0: * (at your option) any later version.
chris@0: *
chris@0: * This program is distributed in the hope that it will be useful,
chris@0: * but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
chris@0: * GNU General Public License for more details.
chris@0: *
chris@0: * You should have received a copy of the GNU General Public License
chris@0: * along with this program. If not, see .
chris@0: */
chris@0:
chris@0: package com.so.news.command;
chris@0:
chris@0: import java.io.IOException;
chris@0: import java.sql.SQLException;
chris@0: import java.util.Date;
chris@0: import java.text.SimpleDateFormat;
chris@0: import java.util.HashMap;
chris@0: import java.util.Locale;
chris@0:
chris@0: import com.so.news.Config;
chris@0: import com.so.news.Debug;
chris@0: import com.so.news.NNTPConnection;
chris@0: import com.so.news.storage.Article;
chris@0: import com.so.news.storage.Database;
chris@0:
chris@0: /**
chris@0: * Contains the code for the POST command.
chris@0: * @author Christian Lins
chris@0: * @author Dennis Schwerdel
chris@0: */
chris@0: public class PostCommand extends Command
chris@0: {
chris@0: public PostCommand(NNTPConnection conn)
chris@0: {
chris@0: super(conn);
chris@0: }
chris@0:
chris@0: public boolean process(String[] command) throws IOException
chris@0: {
chris@0: printStatus(340, "send article to be posted. End with .");
chris@0:
chris@0: // some initialization
chris@0: Article article = new Article();
chris@0: int lineCount = 0;
chris@0: long bodySize = 0;
chris@0: long maxBodySize = Config.getInstance().get("n3tpd.article.maxsize", 1024) * 1024; // Size in bytes
chris@0:
chris@0: // begin with a stringbuilder body
chris@0: StringBuilder body = new StringBuilder();
chris@0: HashMap header = new HashMap();
chris@0:
chris@0: boolean isHeader = true; // are we in the header part
chris@0:
chris@0: String line = readTextLine();
chris@0: while(line != null)
chris@0: {
chris@0: bodySize += line.length();
chris@0: if(bodySize > maxBodySize)
chris@0: {
chris@0: printStatus(500, "article is too long");
chris@0: return false;
chris@0: }
chris@0:
chris@0: if(!isHeader)
chris@0: { // body
chris@0: if(line.trim().equals("."))
chris@0: break;
chris@0:
chris@0: bodySize += line.length() + 1;
chris@0: lineCount++;
chris@0: body.append(line + NEWLINE);
chris@0: }
chris@0:
chris@0: if(line.equals(""))
chris@0: {
chris@0: isHeader = false; // we finally met the blank line
chris@0: // separating headers from body
chris@0: }
chris@0:
chris@0: if(isHeader)
chris@0: { // header
chris@0: // split name and value and add the header to the map
chris@0: int colon = line.indexOf(':');
chris@0: String fieldName = line.substring(0, colon).trim();
chris@0: String fieldValue = line.substring(colon + 1).trim();
chris@0: header.put(fieldName, fieldValue);
chris@0: }
chris@0: line = readTextLine(); // read a new line
chris@0: } // end of input reading
chris@0:
chris@0: article.setBody(body.toString()); // set the article body
chris@0: article.setHeader(header); // add the header entries for the article
chris@0:
chris@0: // Read the date header and fall back to the current date if it is not set
chris@0: try
chris@0: {
chris@0: SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
chris@0: String date = header.get("DATE");
chris@0: if(date == null)
chris@0: article.setDate(new Date());
chris@0: else
chris@0: article.setDate(new Date(sdf.parse(date).getTime())) ;
chris@0: }
chris@0: catch (Exception e)
chris@0: {
chris@0: e.printStackTrace(Debug.getInstance().getStream());
chris@0: printStatus(541, "posting failed - invalid date format");
chris@0: return true;
chris@0: }
chris@0:
chris@0: // check for a cancel command
chris@0: if ( header.containsKey("Control") )
chris@0: {
chris@0: String[] control = header.get("Control").split(" ") ;
chris@0: if ( control.length >= 2 && control[0].equalsIgnoreCase("cancel") )
chris@0: {
chris@0: // this article is a cancel-article, try to delete the old article
chris@0: try
chris@0: {
chris@0: Article.getByMessageID(control[1]).delete();
chris@0: printStatus(240, "article posted ok - original article canceled"); // quite
chris@0: return true; // quit, do not actually post this article since it
chris@0: }
chris@0: catch (Exception e)
chris@0: {
chris@0: e.printStackTrace();
chris@0: printStatus(441, "posting failed - original posting not found");
chris@0: return true;
chris@0: }
chris@0: }
chris@0: }
chris@0:
chris@0: // set some headers
chris@0: header.put("Message-ID", article.getMessageID());
chris@0: header.put("Lines", "" + lineCount);
chris@0: header.put("Bytes", "" + bodySize);
chris@0:
chris@0: // if needed, set an empty references header, that means this is
chris@0: // a initial posting
chris@0: if (!header.containsKey("References"))
chris@0: header.put("References", "");
chris@0:
chris@0: // try to create the article in the database
chris@0: try
chris@0: {
chris@0: Database.getInstance().addArticle(article);
chris@0: printStatus(240, "article posted ok");
chris@0: }
chris@0: catch(SQLException ex)
chris@0: {
chris@0: System.err.println(ex.getLocalizedMessage());
chris@0: ex.printStackTrace(Debug.getInstance().getStream());
chris@0: printStatus(500, "internal server error");
chris@0: }
chris@0:
chris@0: return true;
chris@0: }
chris@0: }