org/sonews/daemon/command/XPatCommand.java
changeset 12 bb6990c0dd1a
parent 1 6fceb66e1ad7
child 20 6ae5e4f8329b
     1.1 --- a/org/sonews/daemon/command/XPatCommand.java	Fri Jun 26 16:48:50 2009 +0200
     1.2 +++ b/org/sonews/daemon/command/XPatCommand.java	Thu Aug 20 14:31:19 2009 +0200
     1.3 @@ -19,8 +19,13 @@
     1.4  package org.sonews.daemon.command;
     1.5  
     1.6  import java.io.IOException;
     1.7 -import java.sql.SQLException;
     1.8 +import java.util.List;
     1.9 +import java.util.Locale;
    1.10 +import java.util.regex.PatternSyntaxException;
    1.11  import org.sonews.daemon.NNTPConnection;
    1.12 +import org.sonews.storage.StorageBackendException;
    1.13 +import org.sonews.storage.StorageManager;
    1.14 +import org.sonews.util.Pair;
    1.15  
    1.16  /**
    1.17   * <pre>
    1.18 @@ -59,18 +64,24 @@
    1.19   *       221 Header follows
    1.20   *       430 no such article
    1.21   *       502 no permission
    1.22 + *
    1.23 + *   Response Data:
    1.24 + *
    1.25 + *       art_nr fitting_header_value
    1.26 + * 
    1.27   * </pre>
    1.28   * [Source:"draft-ietf-nntp-imp-02.txt"] [Copyright: 1998 S. Barber]
    1.29   * 
    1.30   * @author Christian Lins
    1.31   * @since sonews/0.5.0
    1.32   */
    1.33 -public class XPatCommand extends AbstractCommand
    1.34 +public class XPatCommand implements Command
    1.35  {
    1.36  
    1.37 -  public XPatCommand(final NNTPConnection conn)
    1.38 +  @Override
    1.39 +  public String[] getSupportedCommandStrings()
    1.40    {
    1.41 -    super(conn);
    1.42 +    return new String[]{"XPAT"};
    1.43    }
    1.44    
    1.45    @Override
    1.46 @@ -80,10 +91,74 @@
    1.47    }
    1.48  
    1.49    @Override
    1.50 -  public void processLine(final String line) 
    1.51 -    throws IOException, SQLException
    1.52 +  public boolean isStateful()
    1.53    {
    1.54 -    printStatus(500, "not (yet) supported");
    1.55 +    return false;
    1.56 +  }
    1.57 +
    1.58 +  @Override
    1.59 +  public void processLine(NNTPConnection conn, final String line, byte[] raw)
    1.60 +    throws IOException, StorageBackendException
    1.61 +  {
    1.62 +    if(conn.getCurrentChannel() == null)
    1.63 +    {
    1.64 +      conn.println("430 no group selected");
    1.65 +      return;
    1.66 +    }
    1.67 +
    1.68 +    String[] command = line.split("\\p{Space}+");
    1.69 +
    1.70 +    // There may be multiple patterns and Thunderbird produces
    1.71 +    // additional spaces between range and pattern
    1.72 +    if(command.length >= 4)
    1.73 +    {
    1.74 +      String header  = command[1].toLowerCase(Locale.US);
    1.75 +      String range   = command[2];
    1.76 +      String pattern = command[3];
    1.77 +
    1.78 +      long start = -1;
    1.79 +      long end   = -1;
    1.80 +      if(range.contains("-"))
    1.81 +      {
    1.82 +        String[] rsplit = range.split("-", 2);
    1.83 +        start = Long.parseLong(rsplit[0]);
    1.84 +        if(rsplit[1].length() > 0)
    1.85 +        {
    1.86 +          end = Long.parseLong(rsplit[1]);
    1.87 +        }
    1.88 +      }
    1.89 +      else // TODO: Handle Message-IDs
    1.90 +      {
    1.91 +        start = Long.parseLong(range);
    1.92 +      }
    1.93 +
    1.94 +      try
    1.95 +      {
    1.96 +        List<Pair<Long, String>> heads = StorageManager.current().
    1.97 +          getArticleHeaders(conn.getCurrentChannel(), start, end, header, pattern);
    1.98 +        
    1.99 +        conn.println("221 header follows");
   1.100 +        for(Pair<Long, String> head : heads)
   1.101 +        {
   1.102 +          conn.println(head.getA() + " " + head.getB());
   1.103 +        }
   1.104 +        conn.println(".");
   1.105 +      }
   1.106 +      catch(PatternSyntaxException ex)
   1.107 +      {
   1.108 +        ex.printStackTrace();
   1.109 +        conn.println("500 invalid pattern syntax");
   1.110 +      }
   1.111 +      catch(StorageBackendException ex)
   1.112 +      {
   1.113 +        ex.printStackTrace();
   1.114 +        conn.println("500 internal server error");
   1.115 +      }
   1.116 +    }
   1.117 +    else
   1.118 +    {
   1.119 +      conn.println("430 invalid command usage");
   1.120 +    }
   1.121    }
   1.122  
   1.123  }