trunk/com/so/news/command/PostCommand.java
changeset 0 f907866f0e4b
     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 +}