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 }