1 18 package net.sf.drftpd.master.command.plugins; 19 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.io.OutputStreamWriter ; 23 import java.io.PrintWriter ; 24 import java.io.Writer ; 25 import java.net.Socket ; 26 import java.text.DateFormat ; 27 import java.text.SimpleDateFormat ; 28 import java.util.Calendar ; 29 import java.util.Collection ; 30 import java.util.Date ; 31 import java.util.GregorianCalendar ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 import java.util.StringTokenizer ; 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 55 public class LIST implements CommandHandlerFactory, CommandHandler { 56 57 private final static DateFormat AFTER_SIX = new SimpleDateFormat (" yyyy"); 58 59 private final static DateFormat BEFORE_SIX = new SimpleDateFormat ("HH:mm"); 60 61 private final static String DELIM = " "; 62 63 private final static DateFormat FULL = 64 new SimpleDateFormat ("HH:mm:ss yyyy"); 65 private static final Logger logger = Logger.getLogger(LIST.class); 66 67 private final static String [] 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 NEWLINE = "\r\n"; 83 84 88 private static String getLength(RemoteFileInterface fl) { 89 String initStr = " "; 90 String 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 100 private static String getName(LinkedRemoteFileInterface fl) { 101 String 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 114 private static String getPermission(RemoteFileInterface fl) { 115 116 StringBuffer sb = new StringBuffer (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 getUnixDate(long date, boolean fulldate) { 132 Date date1 = new Date (date); 133 long dateTime = date1.getTime(); 134 if (dateTime < 0) { 135 return "------------"; 136 } 137 138 Calendar cal = new GregorianCalendar (); 139 cal.setTime(date1); 140 String firstPart = MONTHS[cal.get(Calendar.MONTH)] + ' '; 141 142 String 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 162 private static void printLine( 163 RemoteFileInterface fl, 164 Writer out, 165 boolean fulldate) 166 throws IOException { 167 StringBuffer line = new StringBuffer (); 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 197 private static void printList( 198 Collection files, 199 Writer os, 200 boolean fulldate) 201 throws IOException { 202 os.write("total 0" + NEWLINE); 204 205 for (Iterator iter = files.iterator(); iter.hasNext();) { 207 RemoteFileInterface file = (RemoteFileInterface) iter.next(); 208 LIST.printLine(file, os, fulldate); 209 } 210 } 211 212 220 private static void printNList( 221 Collection fileList, 222 boolean bDetail, 223 Writer out) 224 throws IOException { 225 226 for (Iterator 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 265 public FtpReply execute(BaseFtpConnection conn) { 266 FtpRequest request = conn.getRequest(); 267 268 String directoryName = null; 269 String options = ""; 270 272 if (request.hasArgument()) { 275 StringBuffer optionsSb = new StringBuffer (4); 277 StringTokenizer st = 278 new StringTokenizer (request.getArgument(), " "); 279 while (st.hasMoreTokens()) { 280 String 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 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 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 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 out = conn.getControlWriter(); 327 Socket dataSocket = null; 328 Writer 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 ( 345 new OutputStreamWriter (dataSocket.getOutputStream())); 346 } catch (IOException ex) { 348 logger.warn("from master", ex); 349 return new FtpReply(425, ex.getMessage()); 350 } 351 } 352 353 List listFiles = ListUtils.list(directoryFile, conn); 355 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 ioe) { 380 logger.error("", ioe); 381 return new FtpReply(450, ioe.getMessage()); 382 } 383 384 } catch (IOException ex) { 385 logger.warn("from master", ex); 386 return new FtpReply(450, ex.getMessage()); 387 } 388 389 } 392 public String [] getFeatReplies() { 393 return null; 394 } 395 396 402 412 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 |