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