1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/trunk/com/so/news/command/PostCommand.java Tue Jan 20 10:21:03 2009 +0100
1.3 @@ -0,0 +1,166 @@
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.command;
1.23 +
1.24 +import java.io.IOException;
1.25 +import java.sql.SQLException;
1.26 +import java.util.Date;
1.27 +import java.text.SimpleDateFormat;
1.28 +import java.util.HashMap;
1.29 +import java.util.Locale;
1.30 +
1.31 +import com.so.news.Config;
1.32 +import com.so.news.Debug;
1.33 +import com.so.news.NNTPConnection;
1.34 +import com.so.news.storage.Article;
1.35 +import com.so.news.storage.Database;
1.36 +
1.37 +/**
1.38 + * Contains the code for the POST command.
1.39 + * @author Christian Lins
1.40 + * @author Dennis Schwerdel
1.41 + */
1.42 +public class PostCommand extends Command
1.43 +{
1.44 + public PostCommand(NNTPConnection conn)
1.45 + {
1.46 + super(conn);
1.47 + }
1.48 +
1.49 + public boolean process(String[] command) throws IOException
1.50 + {
1.51 + printStatus(340, "send article to be posted. End with <CR-LF>.<CR-LF>");
1.52 +
1.53 + // some initialization
1.54 + Article article = new Article();
1.55 + int lineCount = 0;
1.56 + long bodySize = 0;
1.57 + long maxBodySize = Config.getInstance().get("n3tpd.article.maxsize", 1024) * 1024; // Size in bytes
1.58 +
1.59 + // begin with a stringbuilder body
1.60 + StringBuilder body = new StringBuilder();
1.61 + HashMap<String, String> header = new HashMap<String, String>();
1.62 +
1.63 + boolean isHeader = true; // are we in the header part
1.64 +
1.65 + String line = readTextLine();
1.66 + while(line != null)
1.67 + {
1.68 + bodySize += line.length();
1.69 + if(bodySize > maxBodySize)
1.70 + {
1.71 + printStatus(500, "article is too long");
1.72 + return false;
1.73 + }
1.74 +
1.75 + if(!isHeader)
1.76 + { // body
1.77 + if(line.trim().equals("."))
1.78 + break;
1.79 +
1.80 + bodySize += line.length() + 1;
1.81 + lineCount++;
1.82 + body.append(line + NEWLINE);
1.83 + }
1.84 +
1.85 + if(line.equals(""))
1.86 + {
1.87 + isHeader = false; // we finally met the blank line
1.88 + // separating headers from body
1.89 + }
1.90 +
1.91 + if(isHeader)
1.92 + { // header
1.93 + // split name and value and add the header to the map
1.94 + int colon = line.indexOf(':');
1.95 + String fieldName = line.substring(0, colon).trim();
1.96 + String fieldValue = line.substring(colon + 1).trim();
1.97 + header.put(fieldName, fieldValue);
1.98 + }
1.99 + line = readTextLine(); // read a new line
1.100 + } // end of input reading
1.101 +
1.102 + article.setBody(body.toString()); // set the article body
1.103 + article.setHeader(header); // add the header entries for the article
1.104 +
1.105 + // Read the date header and fall back to the current date if it is not set
1.106 + try
1.107 + {
1.108 + SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
1.109 + String date = header.get("DATE");
1.110 + if(date == null)
1.111 + article.setDate(new Date());
1.112 + else
1.113 + article.setDate(new Date(sdf.parse(date).getTime())) ;
1.114 + }
1.115 + catch (Exception e)
1.116 + {
1.117 + e.printStackTrace(Debug.getInstance().getStream());
1.118 + printStatus(541, "posting failed - invalid date format");
1.119 + return true;
1.120 + }
1.121 +
1.122 + // check for a cancel command
1.123 + if ( header.containsKey("Control") )
1.124 + {
1.125 + String[] control = header.get("Control").split(" ") ;
1.126 + if ( control.length >= 2 && control[0].equalsIgnoreCase("cancel") )
1.127 + {
1.128 + // this article is a cancel-article, try to delete the old article
1.129 + try
1.130 + {
1.131 + Article.getByMessageID(control[1]).delete();
1.132 + printStatus(240, "article posted ok - original article canceled"); // quite
1.133 + return true; // quit, do not actually post this article since it
1.134 + }
1.135 + catch (Exception e)
1.136 + {
1.137 + e.printStackTrace();
1.138 + printStatus(441, "posting failed - original posting not found");
1.139 + return true;
1.140 + }
1.141 + }
1.142 + }
1.143 +
1.144 + // set some headers
1.145 + header.put("Message-ID", article.getMessageID());
1.146 + header.put("Lines", "" + lineCount);
1.147 + header.put("Bytes", "" + bodySize);
1.148 +
1.149 + // if needed, set an empty references header, that means this is
1.150 + // a initial posting
1.151 + if (!header.containsKey("References"))
1.152 + header.put("References", "");
1.153 +
1.154 + // try to create the article in the database
1.155 + try
1.156 + {
1.157 + Database.getInstance().addArticle(article);
1.158 + printStatus(240, "article posted ok");
1.159 + }
1.160 + catch(SQLException ex)
1.161 + {
1.162 + System.err.println(ex.getLocalizedMessage());
1.163 + ex.printStackTrace(Debug.getInstance().getStream());
1.164 + printStatus(500, "internal server error");
1.165 + }
1.166 +
1.167 + return true;
1.168 + }
1.169 +}