KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > drftpd > master > command > plugins > LIST


1 /*
2  * This file is part of DrFTPD, Distributed FTP Daemon.
3  *
4  * DrFTPD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * DrFTPD is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with DrFTPD; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package net.sf.drftpd.master.command.plugins;
19
20 import java.io.FileNotFoundException JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.OutputStreamWriter JavaDoc;
23 import java.io.PrintWriter JavaDoc;
24 import java.io.Writer JavaDoc;
25 import java.net.Socket JavaDoc;
26 import java.text.DateFormat JavaDoc;
27 import java.text.SimpleDateFormat JavaDoc;
28 import java.util.Calendar JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.GregorianCalendar JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35
36 import net.sf.drftpd.master.BaseFtpConnection;
37 import net.sf.drftpd.master.FtpReply;
38 import net.sf.drftpd.master.FtpRequest;
39 import net.sf.drftpd.master.command.CommandManager;
40 import net.sf.drftpd.master.command.CommandManagerFactory;
41 import net.sf.drftpd.remotefile.LinkedRemoteFile;
42 import net.sf.drftpd.remotefile.LinkedRemoteFileInterface;
43 import net.sf.drftpd.remotefile.RemoteFileInterface;
44 import net.sf.drftpd.util.ListUtils;
45
46 import org.apache.log4j.Logger;
47 import org.drftpd.commands.CommandHandler;
48 import org.drftpd.commands.CommandHandlerFactory;
49
50 /**
51  * @author mog
52  *
53  * @version $Id: LIST.java,v 1.19.2.1 2004/06/19 23:37:26 mog Exp $
54  */

55 public class LIST implements CommandHandlerFactory, CommandHandler {
56
57     private final static DateFormat JavaDoc AFTER_SIX = new SimpleDateFormat JavaDoc(" yyyy");
58
59     private final static DateFormat JavaDoc BEFORE_SIX = new SimpleDateFormat JavaDoc("HH:mm");
60
61     private final static String JavaDoc DELIM = " ";
62
63     private final static DateFormat JavaDoc FULL =
64         new SimpleDateFormat JavaDoc("HH:mm:ss yyyy");
65     private static final Logger logger = Logger.getLogger(LIST.class);
66
67     private final static String JavaDoc[] MONTHS =
68         {
69             "Jan",
70             "Feb",
71             "Mar",
72             "Apr",
73             "May",
74             "Jun",
75             "Jul",
76             "Aug",
77             "Sep",
78             "Oct",
79             "Nov",
80             "Dec" };
81
82     private final static String JavaDoc NEWLINE = "\r\n";
83
84     /**
85      * Get size
86      * @deprecated
87      */

88     private static String JavaDoc getLength(RemoteFileInterface fl) {
89         String JavaDoc initStr = " ";
90         String JavaDoc szStr = Long.toString(fl.length());
91         if (szStr.length() > initStr.length()) {
92             return szStr;
93         }
94         return initStr.substring(0, initStr.length() - szStr.length()) + szStr;
95     }
96
97     /**
98      * Get file name.
99      */

100     private static String JavaDoc getName(LinkedRemoteFileInterface fl) {
101         String JavaDoc flName = fl.getName();
102
103         int lastIndex = flName.lastIndexOf("/");
104         if (lastIndex == -1) {
105             return flName;
106         } else {
107             return flName.substring(lastIndex + 1);
108         }
109     }
110
111     /**
112      * Get permission string.
113      */

114     private static String JavaDoc getPermission(RemoteFileInterface fl) {
115
116         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(13);
117         sb.append(fl.isDirectory() ? 'd' : '-');
118
119         sb.append("rw");
120         sb.append(fl.isDirectory() ? "x" : "-");
121
122         sb.append("rw");
123         sb.append(fl.isDirectory() ? "x" : "-");
124
125         sb.append("rw");
126         sb.append(fl.isDirectory() ? "x" : "-");
127
128         return sb.toString();
129     }
130
131     public static String JavaDoc getUnixDate(long date, boolean fulldate) {
132         Date JavaDoc date1 = new Date JavaDoc(date);
133         long dateTime = date1.getTime();
134         if (dateTime < 0) {
135             return "------------";
136         }
137
138         Calendar JavaDoc cal = new GregorianCalendar JavaDoc();
139         cal.setTime(date1);
140         String JavaDoc firstPart = MONTHS[cal.get(Calendar.MONTH)] + ' ';
141
142         String JavaDoc dateStr = String.valueOf(cal.get(Calendar.DATE));
143         if (dateStr.length() == 1) {
144             dateStr = ' ' + dateStr;
145         }
146         firstPart += dateStr + ' ';
147
148         long nowTime = System.currentTimeMillis();
149         if (fulldate) {
150             return firstPart + FULL.format(date1);
151         } else if (
152             Math.abs(nowTime - dateTime) > 183L * 24L * 60L * 60L * 1000L) {
153             return firstPart + AFTER_SIX.format(date1);
154         } else {
155             return firstPart + BEFORE_SIX.format(date1);
156         }
157     }
158
159     /**
160      * Get each directory line.
161      */

162     private static void printLine(
163         RemoteFileInterface fl,
164         Writer JavaDoc out,
165         boolean fulldate)
166         throws IOException JavaDoc {
167         StringBuffer JavaDoc line = new StringBuffer JavaDoc();
168         if (fl instanceof LinkedRemoteFileInterface
169             && !((LinkedRemoteFileInterface) fl).isAvailable()) {
170             line.append("----------");
171         } else {
172             line.append(getPermission(fl));
173         }
174         line.append(DELIM);
175         line.append((fl.isDirectory() ? "3" : "1"));
176         line.append(DELIM);
177         line.append(ListUtils.padToLength(fl.getUsername(), 8));
178         line.append(DELIM);
179         line.append(ListUtils.padToLength(fl.getGroupname(), 8));
180         line.append(DELIM);
181         line.append(getLength(fl));
182         line.append(DELIM);
183         line.append(getUnixDate(fl.lastModified(), fulldate));
184         line.append(DELIM);
185         line.append(fl.getName());
186         line.append(NEWLINE);
187         out.write(line.toString());
188     }
189
190     /**
191      * Print file list. Detail listing.
192      * <pre>
193      * -a : display all (including hidden files)
194      * </pre>
195      * @return true if success
196      */

197     private static void printList(
198         Collection JavaDoc files,
199         Writer JavaDoc os,
200         boolean fulldate)
201         throws IOException JavaDoc {
202         //out = new BufferedWriter(out);
203
os.write("total 0" + NEWLINE);
204
205         // print file list
206
for (Iterator JavaDoc iter = files.iterator(); iter.hasNext();) {
207             RemoteFileInterface file = (RemoteFileInterface) iter.next();
208             LIST.printLine(file, os, fulldate);
209         }
210     }
211
212     /**
213      * Print file list.
214      * <pre>
215      * -l : detail listing
216      * -a : display all (including hidden files)
217      * </pre>
218      * @return true if success
219      */

220     private static void printNList(
221         Collection JavaDoc fileList,
222         boolean bDetail,
223         Writer JavaDoc out)
224         throws IOException JavaDoc {
225
226         for (Iterator JavaDoc iter = fileList.iterator(); iter.hasNext();) {
227             LinkedRemoteFile file = (LinkedRemoteFile) iter.next();
228             if (bDetail) {
229                 printLine(file, out, false);
230             } else {
231                 out.write(file.getName() + NEWLINE);
232             }
233         }
234     }
235
236     /**
237      * <code>NLST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
238      *
239      * This command causes a directory listing to be sent from
240      * server to user site. The pathname should specify a
241      * directory or other system-specific file group descriptor; a
242      * null argument implies the current directory. The server
243      * will return a stream of names of files and no other
244      * information.
245      *
246      *
247      * <code>LIST [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
248      *
249      * This command causes a list to be sent from the server to the
250      * passive DTP. If the pathname specifies a directory or other
251      * group of files, the server should transfer a list of files
252      * in the specified directory. If the pathname specifies a
253      * file then the server should send current information on the
254      * file. A null argument implies the user's current working or
255      * default directory. The data transfer is over the data
256      * connection
257      *
258      * LIST
259      * 125, 150
260      * 226, 250
261      * 425, 426, 451
262      * 450
263      * 500, 501, 502, 421, 530
264      */

265     public FtpReply execute(BaseFtpConnection conn) {
266         FtpRequest request = conn.getRequest();
267
268         String JavaDoc directoryName = null;
269         String JavaDoc options = "";
270         //String pattern = "*";
271

272         // get options, directory name and pattern
273
//argument == null if there was no argument for LIST
274
if (request.hasArgument()) {
275             //argument = argument.trim();
276
StringBuffer JavaDoc optionsSb = new StringBuffer JavaDoc(4);
277             StringTokenizer JavaDoc st =
278                 new StringTokenizer JavaDoc(request.getArgument(), " ");
279             while (st.hasMoreTokens()) {
280                 String JavaDoc token = st.nextToken();
281                 if (token.charAt(0) == '-') {
282                     if (token.length() > 1) {
283                         optionsSb.append(token.substring(1));
284                     }
285                 } else {
286                     directoryName = token;
287                 }
288             }
289             options = optionsSb.toString();
290         }
291
292         // check options
293
// boolean allOption = options.indexOf('a') != -1;
294
boolean fulldate = options.indexOf('T') != -1;
295         boolean detailOption =
296             request.getCommand().equals("LIST")
297                 || request.getCommand().equals("STAT")
298                 || options.indexOf('l') != -1;
299         // boolean directoryOption = options.indexOf("d") != -1;
300

301         DataConnectionHandler dataconn = null;
302         if (!request.getCommand().equals("STAT")) {
303             dataconn = conn.getDataConnectionHandler();
304             if (!dataconn.isPasv() && !dataconn.isPort()) {
305                 return FtpReply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS;
306             }
307         }
308
309         LinkedRemoteFile directoryFile;
310         if (directoryName != null) {
311             try {
312                 directoryFile =
313                     conn.getCurrentDirectory().lookupFile(directoryName);
314             } catch (FileNotFoundException JavaDoc ex) {
315                 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
316             }
317             if (!conn
318                 .getConfig()
319                 .checkPrivPath(conn.getUserNull(), directoryFile)) {
320                 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN;
321             }
322         } else {
323             directoryFile = conn.getCurrentDirectory();
324         }
325
326         PrintWriter JavaDoc out = conn.getControlWriter();
327         Socket JavaDoc dataSocket = null;
328         Writer JavaDoc os;
329
330         if (request.getCommand().equals("STAT")) {
331             os = out;
332             out.write(
333                 "213- Status of " + request.getArgument() + ":" + NEWLINE);
334         } else {
335             if (!dataconn.isEncryptedDataChannel()
336                 && conn.getConfig().checkDenyDirUnencrypted(conn.getUserNull())) {
337                 return new FtpReply(550, "Secure Listing Required");
338             }
339             out.write(FtpReply.RESPONSE_150_OK);
340             out.flush();
341             try {
342                 dataSocket = dataconn.getDataSocket(conn.getSocketFactory());
343                 os =
344                     new PrintWriter JavaDoc(
345                         new OutputStreamWriter JavaDoc(dataSocket.getOutputStream()));
346                 //out2 = dataSocket.getChannel();
347
} catch (IOException JavaDoc ex) {
348                 logger.warn("from master", ex);
349                 return new FtpReply(425, ex.getMessage());
350             }
351         }
352
353         ////////////////
354
List JavaDoc listFiles = ListUtils.list(directoryFile, conn);
355         ////////////////
356

357         try {
358             if (request.getCommand().equals("LIST")
359                 || request.getCommand().equals("STAT")) {
360                 printList(listFiles, os, fulldate);
361             } else if (request.getCommand().equals("NLST")) {
362                 printNList(listFiles, detailOption, os);
363             }
364
365             FtpReply response =
366                 (FtpReply) FtpReply
367                     .RESPONSE_226_CLOSING_DATA_CONNECTION
368                     .clone();
369
370             try {
371                 if (!request.getCommand().equals("STAT")) {
372                     os.close();
373                     dataSocket.close();
374                     response.addComment(conn.status());
375                     return response;
376                 } else {
377                     return new FtpReply(213, "End of Status");
378                 }
379             } catch (IOException JavaDoc ioe) {
380                 logger.error("", ioe);
381                 return new FtpReply(450, ioe.getMessage());
382             }
383
384         } catch (IOException JavaDoc ex) {
385             logger.warn("from master", ex);
386             return new FtpReply(450, ex.getMessage());
387         }
388
389         //redo connection handling
390
//conn.reset();
391
}
392     public String JavaDoc[] getFeatReplies() {
393         return null;
394     }
395
396     /**
397      * <code>STAT [&lt;SP&gt; &lt;pathname&gt;] &lt;CRLF&gt;</code><br>
398      *
399      * This command shall cause a status response to be sent over
400      * the control connection in the form of a reply.
401      */

402     // public void doSTAT(FtpRequest request, PrintWriter out) {
403
// reset();
404
// if (request.hasArgument()) {
405
// doLIST(request, out);
406
// } else {
407
// out.print(FtpReply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM);
408
// }
409
// return;
410
// }
411

412     /* (non-Javadoc)
413      * @see net.sf.drftpd.master.command.CommandHandler#initialize(net.sf.drftpd.master.BaseFtpConnection)
414      */

415     public CommandHandler initialize(
416         BaseFtpConnection conn,
417         CommandManager initializer) {
418         return this;
419     }
420
421     public void load(CommandManagerFactory initializer) {
422     }
423     public void unload() {
424     }
425 }
426
Popular Tags