trunk/com/so/news/command/OverCommand.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.
chris@0
     1
/*
chris@0
     2
 *   StarOffice News Server
chris@0
     3
 *   see AUTHORS for the list of contributors
chris@0
     4
 *
chris@0
     5
 *   This program is free software: you can redistribute it and/or modify
chris@0
     6
 *   it under the terms of the GNU General Public License as published by
chris@0
     7
 *   the Free Software Foundation, either version 3 of the License, or
chris@0
     8
 *   (at your option) any later version.
chris@0
     9
 *
chris@0
    10
 *   This program is distributed in the hope that it will be useful,
chris@0
    11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@0
    12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
chris@0
    13
 *   GNU General Public License for more details.
chris@0
    14
 *
chris@0
    15
 *   You should have received a copy of the GNU General Public License
chris@0
    16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
chris@0
    17
 */
chris@0
    18
chris@0
    19
package com.so.news.command;
chris@0
    20
chris@0
    21
import java.text.SimpleDateFormat;
chris@0
    22
import java.util.Locale;
chris@0
    23
chris@0
    24
import com.so.news.Debug;
chris@0
    25
import com.so.news.NNTPConnection;
chris@0
    26
import com.so.news.storage.Article;
chris@0
    27
chris@0
    28
/**
chris@0
    29
 * Class handling the OVER/XOVER command.
chris@0
    30
 * 
chris@0
    31
 * Description of the XOVER command:
chris@0
    32
 * 
chris@0
    33
 * XOVER [range]
chris@0
    34
 *
chris@0
    35
 * The XOVER command returns information from the overview
chris@0
    36
 * database for the article(s) specified.
chris@0
    37
 *
chris@0
    38
 * The optional range argument may be any of the following:
chris@0
    39
 *              an article number
chris@0
    40
 *              an article number followed by a dash to indicate
chris@0
    41
 *                 all following
chris@0
    42
 *              an article number followed by a dash followed by
chris@0
    43
 *                 another article number
chris@0
    44
 *
chris@0
    45
 * If no argument is specified, then information from the
chris@0
    46
 * current article is displayed. Successful responses start
chris@0
    47
 * with a 224 response followed by the overview information
chris@0
    48
 * for all matched messages. Once the output is complete, a
chris@0
    49
 * period is sent on a line by itself. If no argument is
chris@0
    50
 * specified, the information for the current article is
chris@0
    51
 * returned.  A news group must have been selected earlier,
chris@0
    52
 * else a 412 error response is returned. If no articles are
chris@0
    53
 * in the range specified, a 420 error response is returned
chris@0
    54
 * by the server. A 502 response will be returned if the
chris@0
    55
 * client only has permission to transfer articles.
chris@0
    56
 *
chris@0
    57
 * Each line of output will be formatted with the article number,
chris@0
    58
 * followed by each of the headers in the overview database or the
chris@0
    59
 * article itself (when the data is not available in the overview
chris@0
    60
 * database) for that article separated by a tab character.  The
chris@0
    61
 * sequence of fields must be in this order: subject, author,
chris@0
    62
 * date, message-id, references, byte count, and line count. Other
chris@0
    63
 * optional fields may follow line count. Other optional fields may
chris@0
    64
 * follow line count. These fields are specified by examining the
chris@0
    65
 * response to the LIST OVERVIEW.FMT command. Where no data exists,
chris@0
    66
 * a null field must be provided (i.e. the output will have two tab
chris@0
    67
 * characters adjacent to each other). Servers should not output
chris@0
    68
 * fields for articles that have been removed since the XOVER database
chris@0
    69
 * was created.
chris@0
    70
 *
chris@0
    71
 * The LIST OVERVIEW.FMT command should be implemented if XOVER
chris@0
    72
 * is implemented. A client can use LIST OVERVIEW.FMT to determine
chris@0
    73
 * what optional fields  and in which order all fields will be
chris@0
    74
 * supplied by the XOVER command. 
chris@0
    75
 *
chris@0
    76
 * Note that any tab and end-of-line characters in any header
chris@0
    77
 * data that is returned will be converted to a space character.
chris@0
    78
 *
chris@0
    79
 * Responses:
chris@0
    80
 *
chris@0
    81
 *   224 Overview information follows
chris@0
    82
 *   412 No news group current selected
chris@0
    83
 *   420 No article(s) selected
chris@0
    84
 *   502 no permission
chris@0
    85
 * 
chris@0
    86
 * @author Christian Lins
chris@0
    87
 */
chris@0
    88
public class OverCommand extends Command
chris@0
    89
{
chris@0
    90
  public OverCommand(NNTPConnection conn)
chris@0
    91
  {
chris@0
    92
    super(conn);
chris@0
    93
  }
chris@0
    94
  
chris@0
    95
  public boolean process(String[] command)
chris@0
    96
    throws Exception
chris@0
    97
  {
chris@0
    98
    if(getCurrentGroup() == null)
chris@0
    99
    {
chris@0
   100
      printStatus(412, "No news group current selected");
chris@0
   101
      return false;
chris@0
   102
    }
chris@0
   103
    
chris@0
   104
    // If no parameter was specified, show information about
chris@0
   105
    // the currently selected article(s)
chris@0
   106
    if(command.length == 1)
chris@0
   107
    {
chris@0
   108
      Article art = getCurrentArticle();
chris@0
   109
      if(art == null)
chris@0
   110
      {
chris@0
   111
        printStatus(420, "No article(s) selected");
chris@0
   112
        return false;
chris@0
   113
      }
chris@0
   114
      
chris@0
   115
      String o = buildOverview(art, -1);
chris@0
   116
      printText(o);
chris@0
   117
    }
chris@0
   118
    // otherwise print information about the specified range
chris@0
   119
    else
chris@0
   120
    {
chris@0
   121
      int artStart = -1;
chris@0
   122
      int artEnd   = -1;
chris@0
   123
      String[] nums = command[1].split("-");
chris@0
   124
      if(nums.length > 1)
chris@0
   125
      {
chris@0
   126
        try
chris@0
   127
        {
chris@0
   128
          artStart = Integer.parseInt(nums[0]);
chris@0
   129
        }
chris@0
   130
        catch(Exception e) 
chris@0
   131
        {
chris@0
   132
          artStart = Integer.parseInt(command[1]);
chris@0
   133
        }
chris@0
   134
        try
chris@0
   135
        {
chris@0
   136
          artEnd = Integer.parseInt(nums[1]);
chris@0
   137
        }
chris@0
   138
        catch(Exception e) {}
chris@0
   139
      }
chris@0
   140
chris@0
   141
      printStatus(224, "Overview information follows");
chris@0
   142
      for(int n = artStart; n <= artEnd; n++)
chris@0
   143
      {
chris@0
   144
        Article art = Article.getByNumberInGroup(getCurrentGroup(), n);
chris@0
   145
        if(art == null)
chris@0
   146
        {
chris@0
   147
          Debug.getInstance().log("Article (gid=" + getCurrentGroup() + ", art=" + n + " is null!");
chris@0
   148
        }
chris@0
   149
        else
chris@0
   150
        {
chris@0
   151
          printTextPart(buildOverview(art, n) + NEWLINE);
chris@0
   152
        }
chris@0
   153
      }
chris@0
   154
      println(".");
chris@0
   155
      flush();
chris@0
   156
    }
chris@0
   157
    
chris@0
   158
    return true;
chris@0
   159
  }
chris@0
   160
  
chris@0
   161
  private String buildOverview(Article art, int nr)
chris@0
   162
  {
chris@0
   163
    SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
chris@0
   164
    StringBuilder overview = new StringBuilder();
chris@0
   165
    overview.append(nr);
chris@0
   166
    overview.append('\t');
chris@0
   167
    overview.append(art.getHeader().get("Subject"));
chris@0
   168
    overview.append('\t');
chris@0
   169
    overview.append(art.getHeader().get("From"));
chris@0
   170
    overview.append('\t');
chris@0
   171
    overview.append(sdf.format(art.getDate()));
chris@0
   172
    overview.append('\t');
chris@0
   173
    overview.append(art.getHeader().get("Message-ID"));
chris@0
   174
    overview.append('\t');
chris@0
   175
    overview.append(art.getHeader().get("References"));
chris@0
   176
    overview.append('\t');
chris@0
   177
    overview.append(art.getHeader().get("Bytes"));
chris@0
   178
    overview.append('\t');
chris@0
   179
    overview.append(art.getHeader().get("Lines"));
chris@0
   180
    
chris@0
   181
    return overview.toString();
chris@0
   182
  }
chris@0
   183
}