001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * DrFTPD is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with DrFTPD; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018: package net.sf.drftpd.master.command.plugins;
019:
020: import java.io.PrintWriter;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.Date;
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.MissingResourceException;
029: import java.util.ResourceBundle;
030:
031: import net.sf.drftpd.master.BaseFtpConnection;
032: import net.sf.drftpd.master.command.CommandManager;
033: import net.sf.drftpd.master.command.CommandManagerFactory;
034:
035: import org.apache.log4j.Logger;
036: import org.drftpd.commands.CommandHandler;
037: import org.drftpd.commands.CommandHandlerFactory;
038: import org.drftpd.commands.Reply;
039: import org.drftpd.commands.ReplyException;
040: import org.drftpd.commands.UnhandledCommandException;
041: import org.drftpd.slave.Slave;
042:
043: /**
044: * @version $Id: Misc.java 1114 2005-03-13 01:26:58Z zubov $
045: */
046: public class Misc implements CommandHandlerFactory, CommandHandler {
047: private static Logger logger = Logger.getLogger(Misc.class);
048:
049: /**
050: * <code>ABOR <CRLF></code><br>
051: *
052: * This command tells the server to abort the previous FTP
053: * service command and any associated transfer of data.
054: * No action is to be taken if the previous command
055: * has been completed (including data transfer). The control
056: * connection is not to be closed by the server, but the data
057: * connection must be closed.
058: * Current implementation does not do anything. As here data
059: * transfers are not multi-threaded.
060: */
061: private Reply doABOR(BaseFtpConnection conn) {
062: return Reply.RESPONSE_226_CLOSING_DATA_CONNECTION;
063: }
064:
065: // LIST;NLST;RETR;STOR
066: private Reply doFEAT(BaseFtpConnection conn) {
067: PrintWriter out = conn.getControlWriter();
068: out.print("211-Extensions supported:\r\n");
069:
070: for (Iterator iter = conn.getCommandManager()
071: .getCommandHandlersMap().values().iterator(); iter
072: .hasNext();) {
073: CommandHandler hnd = (CommandHandler) iter.next();
074: String[] feat = hnd.getFeatReplies();
075:
076: if (feat == null) {
077: continue;
078: }
079:
080: for (int i = 0; i < feat.length; i++) {
081: out.print(" " + feat[i] + "\r\n");
082: }
083: }
084:
085: // + " CLNT\r\n"
086: // + " MDTM\r\n"
087: // + " PRET\r\n"
088: // + " SIZE\r\n"
089: // + " XCRC\r\n"
090: out.print("211 End\r\n");
091:
092: return null;
093: }
094:
095: /**
096: * <code>HELP [<SP> <string>] <CRLF></code><br>
097: *
098: * This command shall cause the server to send helpful
099: * information regarding its implementation status over the
100: * control connection to the user. The command may take an
101: * argument (e.g., any command name) and return more specific
102: * information as a response.
103: */
104:
105: //TODO implement HELP, SITE HELP would be good too.
106: // public FtpReply doHELP(BaseFtpConnection conn) {
107: //
108: // print global help
109: // if (!request.hasArgument()) {
110: // FtpReply response = new FtpReply(214);
111: // response.addComment("The following commands are recognized.");
112: //out.write(ftpStatus.getResponse(214, null, user, null));
113: // Method methods[] = this.getClass().getDeclaredMethods();
114: // for (int i = 0; i < methods.length; i++) {
115: // Method method = methods[i];
116: // Class parameterTypes[] = method.getParameterTypes();
117: // if (parameterTypes.length == 2
118: // && parameterTypes[0] == FtpRequest.class
119: // && parameterTypes[1] == PrintWriter.class) {
120: // String commandName =
121: // method.getName().substring(2).replace('_', ' ');
122: // response.addComment(commandName);
123: // }
124: // }
125: // out.print(response);
126: // return;
127: // }
128: //
129: // // print command specific help
130: // String ftpCmd = request.getArgument().toUpperCase();
131: // String args[] = null;
132: // FtpRequest tempRequest = new FtpRequest(ftpCmd);
133: // out.write(ftpStatus.getResponse(214, tempRequest, user, args));
134: // return;
135: // }
136: private Reply doSITE_STAT(BaseFtpConnection conn) {
137: if (conn.getRequest().hasArgument()) {
138: return Reply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM;
139: }
140:
141: Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
142:
143: response.addComment(conn.status());
144:
145: return response;
146: }
147:
148: private Reply doSITE_TIME(BaseFtpConnection conn) {
149: if (conn.getRequest().hasArgument()) {
150: return Reply.RESPONSE_501_SYNTAX_ERROR;
151: }
152:
153: return new Reply(200, "Server time is: " + new Date());
154: }
155:
156: private Reply doSITE_HELP(BaseFtpConnection conn)
157: throws ReplyException {
158: Map handlers = conn.getCommandManager().getCommandHandlersMap();
159: if (conn.getRequest().hasArgument()) {
160: String cmd = conn.getRequest().getArgument().toLowerCase();
161: for (Iterator iter = handlers.keySet().iterator(); iter
162: .hasNext();) {
163: CommandHandler hnd = (CommandHandler) handlers.get(iter
164: .next());
165: if (conn.getCommandManager().getHandledCommands(
166: hnd.getClass()).contains(
167: "SITE " + cmd.toUpperCase())) {
168: if (!conn.getGlobalContext().getConfig()
169: .checkPathPermission(cmd,
170: conn.getUserNull(),
171: conn.getCurrentDirectory(), true)) {
172: return new Reply(501,
173: "You do not have permissions for that command");
174: }
175: try {
176: Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK
177: .clone();
178: return response
179: .addComment(ResourceBundle.getBundle(
180: hnd.getClass().getName())
181: .getString(
182: "help." + cmd
183: + ".specific"));
184: } catch (MissingResourceException e) {
185: throw new ReplyException(
186: cmd
187: + " in "
188: + hnd.getClass().getName()
189: + " does not have any specific help, bug your siteop",
190: e);
191: }
192: }
193: }
194: throw new ReplyException("the " + cmd
195: + " command does not exist");
196: }
197: // global list of commands with help
198: HashMap<String, String> helpInfo = new HashMap<String, String>();
199: String pad = " ";
200: for (Iterator iter = handlers.keySet().iterator(); iter
201: .hasNext();) {
202: CommandHandler hnd = (CommandHandler) handlers.get(iter
203: .next());
204: List<String> handledCmds = conn.getCommandManager()
205: .getHandledCommands(hnd.getClass());
206:
207: for (String cmd : handledCmds) {
208: try {
209: cmd = cmd.substring("SITE ".length()).toLowerCase();
210: if (!conn.getGlobalContext().getConfig()
211: .checkPathPermission(cmd,
212: conn.getUserNull(),
213: conn.getCurrentDirectory(), true)) {
214: continue;
215: }
216: try {
217: String help = ResourceBundle.getBundle(
218: hnd.getClass().getName()).getString(
219: "help." + cmd);
220: helpInfo.put(cmd, pad.substring(cmd.length())
221: + cmd.toUpperCase() + " : " + help);
222: } catch (MissingResourceException e) {
223: helpInfo
224: .put(
225: cmd,
226: cmd
227: + " in "
228: + hnd.getClass()
229: .getName()
230: + " does not have any help, bug your siteop");
231: }
232: } catch (java.lang.StringIndexOutOfBoundsException e) {
233: }
234: }
235: }
236: ArrayList<String> sortedList = new ArrayList<String>(helpInfo
237: .keySet());
238: Collections.sort(sortedList);
239: Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
240: try {
241: response.addComment(ResourceBundle.getBundle(
242: Misc.class.getName()).getString("help.header"));
243: } catch (MissingResourceException e) {
244: response.addComment("Help has no header");
245: }
246: for (Iterator i = sortedList.iterator(); i.hasNext();) {
247: response.addComment(helpInfo.get(i.next()));
248: }
249: try {
250: response.addComment(ResourceBundle.getBundle(
251: Misc.class.getName()).getString("help.footer"));
252: } catch (MissingResourceException e) {
253: response.addComment("Help has no footer");
254: }
255: return response;
256: }
257:
258: private Reply doSITE_VERS(BaseFtpConnection conn) {
259: return new Reply(200, Slave.VERSION);
260: }
261:
262: public Reply execute(BaseFtpConnection conn) throws ReplyException {
263: String cmd = conn.getRequest().getCommand();
264:
265: if ("ABOR".equals(cmd)) {
266: return doABOR(conn);
267: }
268:
269: if ("FEAT".equals(cmd)) {
270: return doFEAT(conn);
271: }
272:
273: if ("SITE STAT".equals(cmd)) {
274: return doSITE_STAT(conn);
275: }
276:
277: if ("SITE TIME".equals(cmd)) {
278: return doSITE_TIME(conn);
279: }
280:
281: if ("SITE VERS".equals(cmd)) {
282: return doSITE_VERS(conn);
283: }
284:
285: if ("SITE HELP".equals(cmd)) {
286: return doSITE_HELP(conn);
287: }
288:
289: throw UnhandledCommandException.create(Misc.class, conn
290: .getRequest());
291: }
292:
293: public CommandHandler initialize(BaseFtpConnection conn,
294: CommandManager initializer) {
295: return this ;
296: }
297:
298: public String[] getFeatReplies() {
299: return null;
300: }
301:
302: public void load(CommandManagerFactory initializer) {
303: }
304:
305: public void unload() {
306: }
307: }
|