trunk/com/so/news/command/PostCommand.java
author chris <chris@marvin>
Tue Jan 20 10:21:03 2009 +0100 (2009-01-20)
changeset 0 f907866f0e4b
permissions -rw-r--r--
Initial import.
     1 /*
     2  *   StarOffice News Server
     3  *   see AUTHORS for the list of contributors
     4  *
     5  *   This program is free software: you can redistribute it and/or modify
     6  *   it under the terms of the GNU General Public License as published by
     7  *   the Free Software Foundation, either version 3 of the License, or
     8  *   (at your option) any later version.
     9  *
    10  *   This program is distributed in the hope that it will be useful,
    11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *   GNU General Public License for more details.
    14  *
    15  *   You should have received a copy of the GNU General Public License
    16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 
    19 package com.so.news.command;
    20 
    21 import java.io.IOException;
    22 import java.sql.SQLException;
    23 import java.util.Date;
    24 import java.text.SimpleDateFormat;
    25 import java.util.HashMap;
    26 import java.util.Locale;
    27 
    28 import com.so.news.Config;
    29 import com.so.news.Debug;
    30 import com.so.news.NNTPConnection;
    31 import com.so.news.storage.Article;
    32 import com.so.news.storage.Database;
    33 
    34 /**
    35  * Contains the code for the POST command.
    36  * @author Christian Lins
    37  * @author Dennis Schwerdel
    38  */
    39 public class PostCommand extends Command
    40 {
    41   public PostCommand(NNTPConnection conn)
    42   {
    43     super(conn);
    44   }
    45 
    46   public boolean process(String[] command) throws IOException
    47   {
    48     printStatus(340, "send article to be posted. End with <CR-LF>.<CR-LF>");
    49 
    50     // some initialization
    51     Article article = new Article();
    52     int lineCount     = 0;
    53     long bodySize     = 0;
    54     long maxBodySize  = Config.getInstance().get("n3tpd.article.maxsize", 1024) * 1024; // Size in bytes
    55 
    56     // begin with a stringbuilder body
    57     StringBuilder body = new StringBuilder();
    58     HashMap<String, String> header = new HashMap<String, String>();
    59 
    60     boolean isHeader = true; // are we in the header part
    61 
    62     String line = readTextLine();
    63     while(line != null)
    64     {
    65       bodySize += line.length();
    66       if(bodySize > maxBodySize)
    67       {
    68         printStatus(500, "article is too long");
    69         return false;
    70       }
    71 
    72       if(!isHeader)
    73       { // body
    74         if(line.trim().equals("."))
    75           break;
    76         
    77         bodySize += line.length() + 1;
    78         lineCount++;
    79         body.append(line + NEWLINE);
    80       }
    81       
    82       if(line.equals(""))
    83       {
    84         isHeader = false; // we finally met the blank line
    85                           // separating headers from body
    86       }
    87 
    88       if(isHeader)
    89       { // header
    90         // split name and value and add the header to the map
    91         int colon = line.indexOf(':');
    92         String fieldName = line.substring(0, colon).trim();
    93         String fieldValue = line.substring(colon + 1).trim();
    94         header.put(fieldName, fieldValue);
    95       }
    96       line = readTextLine(); // read a new line
    97     } // end of input reading
    98 
    99     article.setBody(body.toString()); // set the article body
   100     article.setHeader(header);     // add the header entries for the article
   101     
   102     // Read the date header and fall back to the current date if it is not set
   103     try
   104     {
   105       SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
   106       String date = header.get("DATE");
   107       if(date == null)
   108         article.setDate(new Date());
   109       else
   110         article.setDate(new Date(sdf.parse(date).getTime())) ;
   111     }
   112     catch (Exception e)
   113     {
   114       e.printStackTrace(Debug.getInstance().getStream());
   115       printStatus(541, "posting failed - invalid date format");
   116       return true;
   117     }
   118 
   119     // check for a cancel command
   120     if ( header.containsKey("Control") ) 
   121     {
   122       String[] control = header.get("Control").split(" ") ;
   123       if ( control.length >= 2 && control[0].equalsIgnoreCase("cancel") ) 
   124       {
   125         // this article is a cancel-article, try to delete the old article
   126         try
   127         {
   128           Article.getByMessageID(control[1]).delete();
   129           printStatus(240, "article posted ok - original article canceled"); // quite
   130           return true; // quit, do not actually post this article since it
   131         }
   132         catch (Exception e)
   133         {
   134           e.printStackTrace();
   135           printStatus(441, "posting failed - original posting not found");
   136           return true;
   137         }
   138       }
   139     }
   140 
   141     // set some headers
   142     header.put("Message-ID", article.getMessageID());
   143     header.put("Lines", "" + lineCount);
   144     header.put("Bytes", "" + bodySize);
   145 
   146     // if needed, set an empty references header, that means this is
   147     // a initial posting
   148     if (!header.containsKey("References"))
   149       header.put("References", "");
   150 
   151     // try to create the article in the database
   152     try
   153     {
   154       Database.getInstance().addArticle(article);
   155       printStatus(240, "article posted ok");
   156     }
   157     catch(SQLException ex)
   158     {
   159       System.err.println(ex.getLocalizedMessage());
   160       ex.printStackTrace(Debug.getInstance().getStream());
   161       printStatus(500, "internal server error");
   162     }
   163 
   164     return true;
   165   }
   166 }