All pastes #367115 Raw Edit

Something

public text v1 · immutable
#367115 ·published 2007-02-22 03:39 UTC
rendered paste body
Index: conf/ftpcommands.conf.dist
===================================================================
--- conf/ftpcommands.conf.dist	(revision 1638)
+++ conf/ftpcommands.conf.dist	(working copy)
@@ -22,3 +22,5 @@
 USER=org.drftpd.commands.login.LoginHandler.doUSER
 PASS=org.drftpd.commands.login.LoginHandler.doPASS
 QUIT=org.drftpd.commands.login.LoginHandler.doQUIT
+
+LIST=org.drftpd.commands.list.LIST.doLIST
Index: src/plugins/org.drftpd.commands.list/src/org/drftpd/commands/list/LIST.java
===================================================================
--- src/plugins/org.drftpd.commands.list/src/org/drftpd/commands/list/LIST.java	(revision 0)
+++ src/plugins/org.drftpd.commands.list/src/org/drftpd/commands/list/LIST.java	(revision 0)
@@ -0,0 +1,402 @@
+/*
+ * This file is part of DrFTPD, Distributed FTP Daemon.
+ *
+ * DrFTPD is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * DrFTPD is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrFTPD; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package org.drftpd.commands.list;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.net.Socket;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Logger;
+import org.drftpd.commandmanager.CommandInterface;
+import org.drftpd.commandmanager.CommandRequest;
+import org.drftpd.commandmanager.CommandResponse;
+import org.drftpd.commandmanager.Reply;
+import org.drftpd.commandmanager.StandardCommandManager;
+import org.drftpd.master.BaseFtpConnection;
+import org.drftpd.master.TransferState;
+import org.drftpd.vfs.DirectoryHandle;
+import org.drftpd.vfs.FileHandle;
+import org.drftpd.vfs.InodeHandleInterface;
+import org.drftpd.vfs.LinkHandle;
+import org.drftpd.vfs.ListUtils;
+import org.drftpd.vfs.ObjectNotValidException;
+
+/**
+ * @author mog
+ * 
+ * @version $Id: LIST.java 1621 2007-02-13 20:41:31Z djb61 $
+ */
+public class LIST extends CommandInterface {
+	private final static DateFormat AFTER_SIX = new SimpleDateFormat(" yyyy");
+
+	private final static DateFormat BEFORE_SIX = new SimpleDateFormat("HH:mm");
+
+	private final static String DELIM = " ";
+
+	private final static DateFormat FULL = new SimpleDateFormat("HH:mm:ss yyyy");
+
+	private static final Logger logger = Logger.getLogger(LIST.class);
+
+	private final static String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May",
+			"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+	private final static String NEWLINE = "\r\n";
+
+	/*    */
+
+	/**
+	 * Get file name.
+	 */
+
+	/*
+	 * private static String getName(LinkedRemoteFileInterface fl) { String
+	 * flName = fl.getName();
+	 * 
+	 * int lastIndex = flName.lastIndexOf("/");
+	 * 
+	 * if (lastIndex == -1) { return flName; } else { return
+	 * flName.substring(lastIndex + 1); } }
+	 */
+
+	/**
+	 * Get permission string.
+	 */
+	private static String getPermission(InodeHandleInterface fl)
+			throws FileNotFoundException {
+		StringBuffer sb = new StringBuffer(13);
+
+		if (fl.isLink()) {
+			sb.append("l");
+		} else if (fl.isDirectory()) {
+			sb.append("d");
+		} else {
+			sb.append("-");
+		}
+		sb.append("rw");
+		sb.append(fl.isDirectory() ? "x" : "-");
+
+		sb.append("rw");
+		sb.append(fl.isDirectory() ? "x" : "-");
+
+		sb.append("rw");
+		sb.append(fl.isDirectory() ? "x" : "-");
+
+		return sb.toString();
+	}
+
+	public static String getUnixDate(long date, boolean fulldate) {
+		Date date1 = new Date(date);
+		long dateTime = date1.getTime();
+
+		if (dateTime < 0) {
+			return "------------";
+		}
+
+		Calendar cal = new GregorianCalendar();
+		cal.setTime(date1);
+
+		String firstPart = MONTHS[cal.get(Calendar.MONTH)] + ' ';
+
+		String dateStr = String.valueOf(cal.get(Calendar.DATE));
+
+		if (dateStr.length() == 1) {
+			dateStr = ' ' + dateStr;
+		}
+
+		firstPart += (dateStr + ' ');
+
+		long nowTime = System.currentTimeMillis();
+
+		if (fulldate) {
+			return firstPart + FULL.format(date1);
+		} else if (Math.abs(nowTime - dateTime) > (183L * 24L * 60L * 60L * 1000L)) {
+			return firstPart + AFTER_SIX.format(date1);
+		} else {
+			return firstPart + BEFORE_SIX.format(date1);
+		}
+	}
+
+	/**
+	 * Get each directory line.
+	 */
+	private static void printLine(InodeHandleInterface fl, Writer out,
+			boolean fulldate) throws IOException {
+		StringBuffer line = new StringBuffer();
+
+		if (fl instanceof FileHandle
+				&& !((FileHandle) fl).isAvailable()) {
+			line.append("----------");
+		} else {
+			line.append(getPermission(fl));
+		}
+
+		line.append(DELIM);
+		line.append((fl.isDirectory() ? "3" : "1"));
+		line.append(DELIM);
+		line.append(ListUtils.padToLength(fl.getUsername(), 8));
+		line.append(DELIM);
+		line.append(ListUtils.padToLength(fl.getGroup(), 8));
+		line.append(DELIM);
+		line.append(fl.getSize());
+		line.append(DELIM);
+		line.append(getUnixDate(fl.lastModified(), fulldate));
+		line.append(DELIM);
+		line.append(fl.getName());
+		if (fl.isLink()) {
+			line.append(DELIM + "->" + DELIM + ((LinkHandle)fl).getTargetString());
+		}
+		line.append(NEWLINE);
+		out.write(line.toString());
+	}
+
+	/**
+	 * Print file list. Detail listing.
+	 * 
+	 * <pre>
+	 *    -a : display all (including hidden files)
+	 * </pre>
+	 * 
+	 * @return true if success
+	 */
+	private static void printList(Collection<InodeHandleInterface> files, Writer os, boolean fulldate)
+			throws IOException {
+		// out = new BufferedWriter(out);
+		os.write("total 0" + NEWLINE);
+
+		// print file list
+		for (Iterator<InodeHandleInterface> iter = files.iterator(); iter.hasNext();) {
+			InodeHandleInterface file = iter.next();
+			LIST.printLine(file, os, fulldate);
+		}
+	}
+
+	/**
+	 * Print file list.
+	 * 
+	 * <pre>
+	 *    -l : detail listing
+	 *    -a : display all (including hidden files)
+	 * </pre>
+	 * 
+	 * @return true if success
+	 */
+	private static void printNList(Collection<InodeHandleInterface> fileList, boolean bDetail,
+			Writer out) throws IOException {
+		for (Iterator<InodeHandleInterface> iter = fileList.iterator(); iter.hasNext();) {
+			InodeHandleInterface file = iter.next();
+
+			if (bDetail) {
+				printLine(file, out, false);
+			} else {
+				out.write(file.getName() + NEWLINE);
+			}
+		}
+	}
+
+	/**
+	 * <code>NLST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
+	 * 
+	 * This command causes a directory listing to be sent from server to user
+	 * site. The pathname should specify a directory or other system-specific
+	 * file group descriptor; a null argument implies the current directory. The
+	 * server will return a stream of names of files and no other information.
+	 * 
+	 * 
+	 * <code>LIST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
+	 * 
+	 * This command causes a list to be sent from the server to the passive DTP.
+	 * If the pathname specifies a directory or other group of files, the server
+	 * should transfer a list of files in the specified directory. If the
+	 * pathname specifies a file then the server should send current information
+	 * on the file. A null argument implies the user's current working or
+	 * default directory. The data transfer is over the data connection
+	 * 
+	 * LIST 125, 150 226, 250 425, 426, 451 450 500, 501, 502, 421, 530
+	 */
+	public CommandResponse doLIST(CommandRequest request) {
+		try {
+			String directoryName = null;
+			String options = "";
+			BaseFtpConnection conn = request.getConnection();
+			TransferState ts = conn.getTransferState();
+
+			// String pattern = "*";
+			// get options, directory name and pattern
+			// argument == null if there was no argument for LIST
+			if (request.hasArgument()) {
+				// argument = argument.trim();
+				StringBuffer optionsSb = new StringBuffer(4);
+				StringTokenizer st = new StringTokenizer(request.getArgument(),
+						" ");
+
+				while (st.hasMoreTokens()) {
+					String token = st.nextToken();
+
+					if (token.charAt(0) == '-') {
+						if (token.length() > 1) {
+							optionsSb.append(token.substring(1));
+						}
+					} else {
+						directoryName = token;
+					}
+				}
+
+				options = optionsSb.toString();
+			}
+
+			// check options
+			// boolean allOption = options.indexOf('a') != -1;
+			boolean fulldate = options.indexOf('T') != -1;
+			boolean detailOption = request.getCommand().equals("LIST")
+					|| (options.indexOf('l') != -1);
+
+			// boolean directoryOption = options.indexOf("d") != -1;
+
+			if (!ts.isPasv() && !ts.isPort()) {
+					ts.reset();
+					return StandardCommandManager.genericResponse("RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS");
+			}
+
+			DirectoryHandle directoryFile;
+
+			if (directoryName != null) {
+				try {
+					directoryFile = conn.getCurrentDirectory().getDirectory(
+							directoryName);
+				} catch (FileNotFoundException ex) {
+					return StandardCommandManager.genericResponse("RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN");
+				} catch (ObjectNotValidException e) {
+					return StandardCommandManager.genericResponse("RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM");
+				}
+
+				if (!conn.getGlobalContext().getConfig().checkPathPermission(
+						"privpath", conn.getUserNull(),
+						directoryFile.getParent(), true)) {
+					return StandardCommandManager.genericResponse("RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN");
+				}
+			} else {
+				directoryFile = conn.getCurrentDirectory();
+			}
+
+			PrintWriter out = conn.getControlWriter();
+			Socket dataSocket = null;
+			Writer os;
+
+
+				if (!ts.getSendFilesEncrypted()
+						&& conn.getGlobalContext().getConfig().checkPermission(
+								"denydiruncrypted", conn.getUserNull())) {
+					return new CommandResponse(550, "Secure Listing Required");
+				}
+
+				out.write(Reply.RESPONSE_150_OK);
+				out.flush();
+
+				try {
+					dataSocket = ts.getDataSocketForLIST();
+					os = new PrintWriter(new OutputStreamWriter(dataSocket
+							.getOutputStream()));
+
+					// out2 = dataSocket.getChannel();
+				} catch (IOException ex) {
+					logger.warn("from master", ex);
+
+					return new CommandResponse(425, ex.getMessage());
+				}
+
+			// //////////////
+			logger.debug("Listing directoryFile - " + directoryFile);
+			List<InodeHandleInterface> listFiles = ListUtils.list(
+					directoryFile, conn);
+
+			// //////////////
+			try {
+				if (request.getCommand().equals("LIST")
+						|| request.getCommand().equals("STAT")) {
+					printList(listFiles, os, fulldate);
+				} else if (request.getCommand().equals("NLST")) {
+					printNList(listFiles, detailOption, os);
+				}
+
+				CommandResponse response = (CommandResponse) StandardCommandManager.genericResponse("RESPONSE_226_CLOSING_DATA_CONNECTION")
+						.clone();
+
+				try {
+						os.close();
+						dataSocket.close();
+						response.addComment(conn.status());
+
+					return response;
+				} catch (IOException ioe) {
+					logger.error("", ioe);
+
+					return new CommandResponse(450, ioe.getMessage());
+				}
+			} catch (IOException ex) {
+				logger.warn("from master", ex);
+
+				return new CommandResponse(450, ex.getMessage());
+			}
+		} finally {
+			request.getConnection().getTransferState().reset();
+		}
+	}
+	
+	public CommandResponse doSTAT(CommandRequest request) {
+/*		if (request.getCommand().equals("STAT")) {
+			os = out;
+			out.write("213- Status of " + request.getArgument() + ":"
+					+ NEWLINE);
+			return new Reply(213, "End of Status");
+		}*/
+		return null;
+	}
+
+	public String[] getFeatReplies() {
+		return null;
+	}
+
+	/**
+	 * <code>STAT [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
+	 * 
+	 * This command shall cause a status response to be sent over the control
+	 * connection in the form of a reply.
+	 */
+
+	// public void doSTAT(FtpRequest request, PrintWriter out) {
+	// reset();
+	// if (request.hasArgument()) {
+	// doLIST(request, out);
+	// } else {
+	// out.print(FtpReply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM);
+	// }
+	// return;
+	// }
+}
Index: src/plugins/org.drftpd.commands.list/plugin.xml
===================================================================
--- src/plugins/org.drftpd.commands.list/plugin.xml	(revision 0)
+++ src/plugins/org.drftpd.commands.list/plugin.xml	(revision 0)
@@ -0,0 +1,33 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin PUBLIC "-//JPF//Java Plug-in Manifest 1.0" "http://jpf.sourceforge.net/plugin_1_0.dtd">
+<plugin id="org.drftpd.commands.list" version="2.1.0">
+	<requires>
+		<import plugin-id="org.drftpd.commandmanager" exported="true" />
+	</requires>
+	<runtime>
+		<library id="org.drftpd.commands.list" path="classes/" type="code">
+			<export prefix="*" />
+		</library>
+		<library id="oro" path="../../lib/oro.jar" type="code">
+		</library>
+	</runtime>
+	<extension-point id="FrontendHook">
+		<parameter-def id="HookClass" />
+		<parameter-def id="HookMethod" />
+		<parameter-def id="ParentMethod" />
+	</extension-point>
+	<extension-point id="PostHook">
+		<parameter-def id="HookClass" />
+		<parameter-def id="HookMethod" />
+		<parameter-def id="ParentMethod" />
+		<parameter-def id="Priority" type="number" />
+	</extension-point>
+	<extension-point id="PreHook">
+		<parameter-def id="HookClass" />
+		<parameter-def id="HookMethod" />
+		<parameter-def id="ParentMethod" />
+		<parameter-def id="Priority" type="number" />
+	</extension-point>
+	<extension plugin-id="org.drftpd.commandmanager" point-id="Command" id="ListHandler">
+	</extension>
+</plugin>
Index: src/plugins/org.drftpd.commands.list/build.xml
===================================================================
--- src/plugins/org.drftpd.commands.list/build.xml	(revision 0)
+++ src/plugins/org.drftpd.commands.list/build.xml	(revision 0)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.drftpd.commands.list plug-in build file"
+         default="build"
+         basedir=".">
+	<jpf-info manifest="${basedir}/plugin.xml"
+		propertyid="plugin.id"
+		propertyversion="plugin.version" />
+	<property name="plugin.home"
+		value="${basedir}/../../../plugins/${plugin.id}" />
+	<path id="plugin.classpath">
+		<fileset dir="${basedir}/../../../lib">
+			<include name="*.jar" />
+		</fileset>
+		<dirset dir="${plugin.home}/../../">
+			<include name="core/common/classes" />
+			<include name="core/master/classes" />
+			<include name="plugins/org.drftpd.commandmanager/classes" />
+		</dirset>
+	</path>
+
+	<target name="build">
+		<echo>Building ${plugin.id} plug-in to folder ${plugin.home}</echo>
+		<mkdir dir="${plugin.home}/classes" />
+		<javac destdir="${plugin.home}/classes"
+			srcdir="${basedir}/src"
+			classpathref="plugin.classpath"
+			source="1.5"
+			target="1.5"
+			debug="true"
+			optimize="false">
+		</javac>
+		<copy todir="${plugin.home}/classes">
+			<fileset dir="${basedir}/src"
+				includes="**/*"
+				excludes="**/.*,**/*.java" />
+		</copy>
+		<copy todir="${plugin.home}" includeemptydirs="false">
+			<fileset dir="${basedir}"
+				excludes="classes/,.*,*build*,src/" />
+		</copy>
+	</target>
+</project>
Index: src/master/src/org/drftpd/master/CommitManager.java
===================================================================
--- src/master/src/org/drftpd/master/CommitManager.java	(revision 1638)
+++ src/master/src/org/drftpd/master/CommitManager.java	(working copy)
@@ -32,6 +32,7 @@
 import org.java.plugin.PluginManager;
 
 /**
+ * @author zubov
  * @version $Id$
  */
 public class CommitManager {
Index: src/master/src/org/drftpd/commands/LIST.java
===================================================================
--- src/master/src/org/drftpd/commands/LIST.java	(revision 1638)
+++ src/master/src/org/drftpd/commands/LIST.java	(working copy)
@@ -1,422 +0,0 @@
-/*
- * This file is part of DrFTPD, Distributed FTP Daemon.
- *
- * DrFTPD is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * DrFTPD is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with DrFTPD; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-package org.drftpd.commands;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.net.Socket;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-
-
-import org.apache.log4j.Logger;
-import org.drftpd.commandmanager.CommandHandler;
-import org.drftpd.commandmanager.CommandHandlerFactory;
-import org.drftpd.commandmanager.CommandManager;
-import org.drftpd.commandmanager.CommandManagerFactory;
-import org.drftpd.commandmanager.Reply;
-import org.drftpd.master.BaseFtpConnection;
-import org.drftpd.master.TransferState;
-import org.drftpd.util.FtpRequest;
-import org.drftpd.vfs.DirectoryHandle;
-import org.drftpd.vfs.FileHandle;
-import org.drftpd.vfs.InodeHandleInterface;
-import org.drftpd.vfs.LinkHandle;
-import org.drftpd.vfs.ListUtils;
-import org.drftpd.vfs.ObjectNotValidException;
-
-/**
- * @author mog
- * 
- * @version $Id$
- */
-public class LIST implements CommandHandler, CommandHandlerFactory {
-	private final static DateFormat AFTER_SIX = new SimpleDateFormat(" yyyy");
-
-	private final static DateFormat BEFORE_SIX = new SimpleDateFormat("HH:mm");
-
-	private final static String DELIM = " ";
-
-	private final static DateFormat FULL = new SimpleDateFormat("HH:mm:ss yyyy");
-
-	private static final Logger logger = Logger.getLogger(LIST.class);
-
-	private final static String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May",
-			"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-	private final static String NEWLINE = "\r\n";
-
-	/*    */
-
-	/**
-	 * Get file name.
-	 */
-
-	/*
-	 * private static String getName(LinkedRemoteFileInterface fl) { String
-	 * flName = fl.getName();
-	 * 
-	 * int lastIndex = flName.lastIndexOf("/");
-	 * 
-	 * if (lastIndex == -1) { return flName; } else { return
-	 * flName.substring(lastIndex + 1); } }
-	 */
-
-	/**
-	 * Get permission string.
-	 */
-	private static String getPermission(InodeHandleInterface fl)
-			throws FileNotFoundException {
-		StringBuffer sb = new StringBuffer(13);
-
-		if (fl.isLink()) {
-			sb.append("l");
-		} else if (fl.isDirectory()) {
-			sb.append("d");
-		} else {
-			sb.append("-");
-		}
-		sb.append("rw");
-		sb.append(fl.isDirectory() ? "x" : "-");
-
-		sb.append("rw");
-		sb.append(fl.isDirectory() ? "x" : "-");
-
-		sb.append("rw");
-		sb.append(fl.isDirectory() ? "x" : "-");
-
-		return sb.toString();
-	}
-
-	public static String getUnixDate(long date, boolean fulldate) {
-		Date date1 = new Date(date);
-		long dateTime = date1.getTime();
-
-		if (dateTime < 0) {
-			return "------------";
-		}
-
-		Calendar cal = new GregorianCalendar();
-		cal.setTime(date1);
-
-		String firstPart = MONTHS[cal.get(Calendar.MONTH)] + ' ';
-
-		String dateStr = String.valueOf(cal.get(Calendar.DATE));
-
-		if (dateStr.length() == 1) {
-			dateStr = ' ' + dateStr;
-		}
-
-		firstPart += (dateStr + ' ');
-
-		long nowTime = System.currentTimeMillis();
-
-		if (fulldate) {
-			return firstPart + FULL.format(date1);
-		} else if (Math.abs(nowTime - dateTime) > (183L * 24L * 60L * 60L * 1000L)) {
-			return firstPart + AFTER_SIX.format(date1);
-		} else {
-			return firstPart + BEFORE_SIX.format(date1);
-		}
-	}
-
-	/**
-	 * Get each directory line.
-	 */
-	private static void printLine(InodeHandleInterface fl, Writer out,
-			boolean fulldate) throws IOException {
-		StringBuffer line = new StringBuffer();
-
-		if (fl instanceof FileHandle
-				&& !((FileHandle) fl).isAvailable()) {
-			line.append("----------");
-		} else {
-			line.append(getPermission(fl));
-		}
-
-		line.append(DELIM);
-		line.append((fl.isDirectory() ? "3" : "1"));
-		line.append(DELIM);
-		line.append(ListUtils.padToLength(fl.getUsername(), 8));
-		line.append(DELIM);
-		line.append(ListUtils.padToLength(fl.getGroup(), 8));
-		line.append(DELIM);
-		line.append(fl.getSize());
-		line.append(DELIM);
-		line.append(getUnixDate(fl.lastModified(), fulldate));
-		line.append(DELIM);
-		line.append(fl.getName());
-		if (fl.isLink()) {
-			line.append(DELIM + "->" + DELIM + ((LinkHandle)fl).getTargetString());
-		}
-		line.append(NEWLINE);
-		out.write(line.toString());
-	}
-
-	/**
-	 * Print file list. Detail listing.
-	 * 
-	 * <pre>
-	 *    -a : display all (including hidden files)
-	 * </pre>
-	 * 
-	 * @return true if success
-	 */
-	private static void printList(Collection<InodeHandleInterface> files, Writer os, boolean fulldate)
-			throws IOException {
-		// out = new BufferedWriter(out);
-		os.write("total 0" + NEWLINE);
-
-		// print file list
-		for (Iterator<InodeHandleInterface> iter = files.iterator(); iter.hasNext();) {
-			InodeHandleInterface file = iter.next();
-			LIST.printLine(file, os, fulldate);
-		}
-	}
-
-	/**
-	 * Print file list.
-	 * 
-	 * <pre>
-	 *    -l : detail listing
-	 *    -a : display all (including hidden files)
-	 * </pre>
-	 * 
-	 * @return true if success
-	 */
-	private static void printNList(Collection<InodeHandleInterface> fileList, boolean bDetail,
-			Writer out) throws IOException {
-		for (Iterator<InodeHandleInterface> iter = fileList.iterator(); iter.hasNext();) {
-			InodeHandleInterface file = iter.next();
-
-			if (bDetail) {
-				printLine(file, out, false);
-			} else {
-				out.write(file.getName() + NEWLINE);
-			}
-		}
-	}
-
-	/**
-	 * <code>NLST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
-	 * 
-	 * This command causes a directory listing to be sent from server to user
-	 * site. The pathname should specify a directory or other system-specific
-	 * file group descriptor; a null argument implies the current directory. The
-	 * server will return a stream of names of files and no other information.
-	 * 
-	 * 
-	 * <code>LIST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
-	 * 
-	 * This command causes a list to be sent from the server to the passive DTP.
-	 * If the pathname specifies a directory or other group of files, the server
-	 * should transfer a list of files in the specified directory. If the
-	 * pathname specifies a file then the server should send current information
-	 * on the file. A null argument implies the user's current working or
-	 * default directory. The data transfer is over the data connection
-	 * 
-	 * LIST 125, 150 226, 250 425, 426, 451 450 500, 501, 502, 421, 530
-	 */
-	public Reply execute(BaseFtpConnection conn) {
-		try {
-			FtpRequest request = conn.getRequest();
-
-			String directoryName = null;
-			String options = "";
-			TransferState ts = conn.getTransferState();
-
-			// String pattern = "*";
-			// get options, directory name and pattern
-			// argument == null if there was no argument for LIST
-			if (request.hasArgument()) {
-				// argument = argument.trim();
-				StringBuffer optionsSb = new StringBuffer(4);
-				StringTokenizer st = new StringTokenizer(request.getArgument(),
-						" ");
-
-				while (st.hasMoreTokens()) {
-					String token = st.nextToken();
-
-					if (token.charAt(0) == '-') {
-						if (token.length() > 1) {
-							optionsSb.append(token.substring(1));
-						}
-					} else {
-						directoryName = token;
-					}
-				}
-
-				options = optionsSb.toString();
-			}
-
-			// check options
-			// boolean allOption = options.indexOf('a') != -1;
-			boolean fulldate = options.indexOf('T') != -1;
-			boolean detailOption = request.getCommand().equals("LIST")
-					|| request.getCommand().equals("STAT")
-					|| (options.indexOf('l') != -1);
-
-			// boolean directoryOption = options.indexOf("d") != -1;
-
-			if (!request.getCommand().equals("STAT")) {
-
-				if (!ts.isPasv() && !ts.isPort()) {
-					return Reply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS;
-				}
-			}
-
-			DirectoryHandle directoryFile;
-
-			if (directoryName != null) {
-				try {
-					directoryFile = conn.getCurrentDirectory().getDirectory(
-							directoryName);
-				} catch (FileNotFoundException ex) {
-					return Reply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
-				} catch (ObjectNotValidException e) {
-					return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
-				}
-
-				if (!conn.getGlobalContext().getConfig().checkPathPermission(
-						"privpath", conn.getUserNull(),
-						directoryFile.getParent(), true)) {
-					return Reply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
-				}
-			} else {
-				directoryFile = conn.getCurrentDirectory();
-			}
-
-			PrintWriter out = conn.getControlWriter();
-			Socket dataSocket = null;
-			Writer os;
-
-			if (request.getCommand().equals("STAT")) {
-				os = out;
-				out.write("213- Status of " + request.getArgument() + ":"
-						+ NEWLINE);
-			} else {
-				if (!ts.getSendFilesEncrypted()
-						&& conn.getGlobalContext().getConfig().checkPermission(
-								"denydiruncrypted", conn.getUserNull())) {
-					return new Reply(550, "Secure Listing Required");
-				}
-
-				out.write(Reply.RESPONSE_150_OK);
-				out.flush();
-
-				try {
-					dataSocket = ts.getDataSocketForLIST();
-					os = new PrintWriter(new OutputStreamWriter(dataSocket
-							.getOutputStream()));
-
-					// out2 = dataSocket.getChannel();
-				} catch (IOException ex) {
-					logger.warn("from master", ex);
-
-					return new Reply(425, ex.getMessage());
-				}
-			}
-
-			// //////////////
-			logger.debug("Listing directoryFile - " + directoryFile);
-			List<InodeHandleInterface> listFiles = ListUtils.list(
-					directoryFile, conn);
-
-			// //////////////
-			try {
-				if (request.getCommand().equals("LIST")
-						|| request.getCommand().equals("STAT")) {
-					printList(listFiles, os, fulldate);
-				} else if (request.getCommand().equals("NLST")) {
-					printNList(listFiles, detailOption, os);
-				}
-
-				Reply response = (Reply) Reply.RESPONSE_226_CLOSING_DATA_CONNECTION
-						.clone();
-
-				try {
-					if (!request.getCommand().equals("STAT")) {
-						os.close();
-						dataSocket.close();
-						response.addComment(conn.status());
-
-						return response;
-					}
-
-					return new Reply(213, "End of Status");
-				} catch (IOException ioe) {
-					logger.error("", ioe);
-
-					return new Reply(450, ioe.getMessage());
-				}
-			} catch (IOException ex) {
-				logger.warn("from master", ex);
-
-				return new Reply(450, ex.getMessage());
-			}
-		} finally {
-			conn.getTransferState().reset();
-		}
-	}
-
-	public String[] getFeatReplies() {
-		return null;
-	}
-
-	/**
-	 * <code>STAT [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
-	 * 
-	 * This command shall cause a status response to be sent over the control
-	 * connection in the form of a reply.
-	 */
-
-	// public void doSTAT(FtpRequest request, PrintWriter out) {
-	// reset();
-	// if (request.hasArgument()) {
-	// doLIST(request, out);
-	// } else {
-	// out.print(FtpReply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM);
-	// }
-	// return;
-	// }
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see net.sf.drftpd.master.command.CommandHandler#initialize(net.sf.drftpd.master.BaseFtpConnection)
-	 */
-	public CommandHandler initialize(BaseFtpConnection conn,
-			CommandManager initializer) {
-		return this;
-	}
-
-	public void load(CommandManagerFactory initializer) {
-	}
-
-	public void unload() {
-	}
-}
Index: build.xml
===================================================================
--- build.xml	(revision 1638)
+++ build.xml	(working copy)
@@ -41,6 +41,7 @@
 		<ant dir="src/plugins/org.drftpd.commandmanager" target="${target}" />
 		<ant dir="src/plugins/org.drftpd.commands.dataconnection" target="${target}" />
 		<ant dir="src/plugins/org.drftpd.commands.login" target="${target}" />
+		<ant dir="src/plugins/org.drftpd.commands.list" target="${target}" />
 	</target>
 
 	<target name="build" description="Builds entire project">