1 18 package net.sf.drftpd.master.command.plugins; 19 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.text.SimpleDateFormat ; 23 import java.util.Collection ; 24 import java.util.Date ; 25 import java.util.Iterator ; 26 import java.util.StringTokenizer ; 27 28 import net.sf.drftpd.Bytes; 29 import net.sf.drftpd.Checksum; 30 import net.sf.drftpd.NoAvailableSlaveException; 31 import net.sf.drftpd.FileExistsException; 32 import net.sf.drftpd.event.DirectoryFtpEvent; 33 import net.sf.drftpd.master.BaseFtpConnection; 34 import net.sf.drftpd.master.FtpReply; 35 import net.sf.drftpd.master.FtpRequest; 36 import net.sf.drftpd.master.UploaderPosition; 37 import net.sf.drftpd.master.command.CommandHandlerBundle; 38 import net.sf.drftpd.master.command.CommandManager; 39 import net.sf.drftpd.master.command.CommandManagerFactory; 40 import net.sf.drftpd.master.usermanager.NoSuchUserException; 41 import net.sf.drftpd.master.usermanager.User; 42 import net.sf.drftpd.master.usermanager.UserFileException; 43 import net.sf.drftpd.remotefile.LinkedRemoteFile; 44 import net.sf.drftpd.remotefile.LinkedRemoteFileInterface; 45 import net.sf.drftpd.remotefile.LinkedRemoteFile.NonExistingFile; 46 import net.sf.drftpd.util.ListUtils; 47 import net.sf.drftpd.util.ReplacerUtils; 48 49 import org.apache.log4j.Level; 50 import org.apache.log4j.Logger; 51 import org.drftpd.commands.CommandHandler; 52 import org.drftpd.commands.UnhandledCommandException; 53 import org.drftpd.plugins.SiteBot; 54 import org.tanesha.replacer.FormatterException; 55 import org.tanesha.replacer.ReplacerEnvironment; 56 import org.tanesha.replacer.ReplacerFormat; 57 58 62 public class Dir implements CommandHandlerBundle, Cloneable { 63 private final static SimpleDateFormat DATE_FMT = 64 new SimpleDateFormat ("yyyyMMddHHmmss.SSS"); 65 66 private static final Logger logger = Logger.getLogger(Dir.class); 67 protected LinkedRemoteFileInterface _renameFrom = null; 68 69 public Dir() { 70 super(); 71 } 72 73 82 private FtpReply doCDUP(BaseFtpConnection conn) { 83 84 try { 86 conn.setCurrentDirectory( 87 conn.getCurrentDirectory().getParentFile()); 88 } catch (FileNotFoundException ex) { 89 } 90 91 return new FtpReply( 92 200, 93 "Directory changed to " + conn.getCurrentDirectory().getPath()); 94 } 95 96 105 private FtpReply doCWD(BaseFtpConnection conn) { 106 FtpRequest request = conn.getRequest(); 107 108 if (!request.hasArgument()) { 109 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 110 } 111 112 LinkedRemoteFile newCurrentDirectory; 113 try { 114 newCurrentDirectory = 115 conn.getCurrentDirectory().lookupFile(request.getArgument()); 116 } catch (FileNotFoundException ex) { 117 return new FtpReply(550, ex.getMessage()); 118 } 119 if (!conn 120 .getConfig() 121 .checkPrivPath(conn.getUserNull(), newCurrentDirectory)) { 122 return new FtpReply(550, request.getArgument() + ": Not found"); 123 } 125 126 if (!newCurrentDirectory.isDirectory()) { 127 return new FtpReply( 128 550, 129 request.getArgument() + ": Not a directory"); 130 } 131 conn.setCurrentDirectory(newCurrentDirectory); 132 133 FtpReply response = 134 new FtpReply( 135 250, 136 "Directory changed to " + newCurrentDirectory.getPath()); 137 conn.getConfig().directoryMessage( 138 response, 139 conn.getUserNull(), 140 newCurrentDirectory); 141 try { 142 Collection uploaders = 143 SiteBot.userSort(newCurrentDirectory.lookupSFVFile().getFiles(), "bytes", "high"); 144 145 ReplacerFormat format = null; 146 try { 147 format = ReplacerUtils.finalFormat(Dir.class, "cwd.uploaders"); 148 } catch (FormatterException e1) { 149 } 150 ReplacerEnvironment env = 151 BaseFtpConnection.getReplacerEnvironment( 152 null, 153 conn.getUserNull()); 154 for (Iterator iter = uploaders.iterator(); iter.hasNext();) { 155 UploaderPosition stat = (UploaderPosition) iter.next(); 156 157 User user; 158 try { 159 user = 160 conn.getConnectionManager().getUserManager().getUserByName(stat.getUsername()); 161 } catch (NoSuchUserException e2) { 162 continue; 163 } catch (UserFileException e2) { 164 logger.log(Level.FATAL, "Error reading userfile", e2); 165 continue; 166 } 167 168 env.add("speed", Bytes.formatBytes(stat.getXferspeed())+"/s"); 169 env.add("targetuser", stat.getUsername()); 170 env.add("targetgroup", user.getGroupName()); 171 env.add("files", "" + stat.getFiles()); 172 env.add("bytes", Bytes.formatBytes(stat.getBytes())); 173 try { 175 if (format == null) { 176 response.addComment("cwd.uploaders"); 177 } else { 178 response.addComment( 179 ReplacerUtils.finalJprintf(format, env)); 180 } 181 } catch (FormatterException e) { 182 response.addComment("cwd.uploaders"); 183 } 184 185 } 186 } catch (RuntimeException ex) { 187 logger.error("", ex); 188 } catch (IOException e) { 189 } catch (NoAvailableSlaveException e) { 191 } 193 return response; 194 } 195 196 202 private FtpReply doDELE(BaseFtpConnection conn) { 203 FtpRequest request = conn.getRequest(); 204 205 if (!request.hasArgument()) { 207 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 209 } 210 211 String fileName = request.getArgument(); 213 LinkedRemoteFile requestedFile; 214 try { 215 requestedFile = conn.getCurrentDirectory().lookupFile(fileName); 217 } catch (FileNotFoundException ex) { 218 return new FtpReply(550, "File not found: " + ex.getMessage()); 219 } 220 if (requestedFile 222 .getUsername() 223 .equals(conn.getUserNull().getUsername())) { 224 if (!conn 225 .getConfig() 226 .checkDeleteOwn(conn.getUserNull(), requestedFile)) { 227 return FtpReply.RESPONSE_530_ACCESS_DENIED; 228 } 229 } else if ( 230 !conn.getConfig().checkDelete(conn.getUserNull(), requestedFile)) { 231 return FtpReply.RESPONSE_530_ACCESS_DENIED; 232 } 233 234 FtpReply reply = (FtpReply) FtpReply.RESPONSE_250_ACTION_OKAY.clone(); 235 236 User uploader; 237 try { 238 uploader = 239 conn.getConnectionManager().getUserManager().getUserByName( 240 requestedFile.getUsername()); 241 uploader.updateCredits( 242 (long) - (requestedFile.length() * uploader.getRatio())); 243 } catch (UserFileException e) { 244 reply.addComment("Error removing credits: " + e.getMessage()); 245 } catch (NoSuchUserException e) { 246 reply.addComment("Error removing credits: " + e.getMessage()); 247 } 248 249 conn.getConnectionManager().dispatchFtpEvent( 250 new DirectoryFtpEvent(conn.getUserNull(), "DELE", requestedFile)); 251 requestedFile.delete(); 252 return reply; 253 } 254 255 260 private FtpReply doMDTM(BaseFtpConnection conn) { 261 FtpRequest request = conn.getRequest(); 262 if (!request.hasArgument()) { 264 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 265 } 266 267 String fileName = request.getArgument(); 269 LinkedRemoteFile reqFile; 270 try { 271 reqFile = conn.getCurrentDirectory().lookupFile(fileName); 272 } catch (FileNotFoundException ex) { 273 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN; 274 } 275 280 return new FtpReply( 283 213, 284 DATE_FMT.format(new Date (reqFile.lastModified()))); 285 } 290 291 304 private FtpReply doMKD(BaseFtpConnection conn) { 305 FtpRequest request = conn.getRequest(); 306 307 if (!request.hasArgument()) { 309 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 310 } 311 if(!conn.getSlaveManager().hasAvailableSlaves()) { 312 return FtpReply.RESPONSE_450_SLAVE_UNAVAILABLE; 313 } 314 LinkedRemoteFile.NonExistingFile ret = 315 conn.getCurrentDirectory().lookupNonExistingFile( 316 request.getArgument(), true); 317 LinkedRemoteFile dir = ret.getFile(); 318 if(dir.isDeleted()) { 319 dir.setLastModified(System.currentTimeMillis()); 320 dir.setOwner(conn.getUserNull().getUsername()); 321 dir.setGroup(conn.getUserNull().getGroupName()); 322 dir.setDeleted(false); 323 conn.getConnectionManager().dispatchFtpEvent( 324 new DirectoryFtpEvent(conn.getUserNull(), "MKD", dir)); 325 return new FtpReply( 326 257, 327 "\"" + dir.getPath() + "\" no longer deleted."); 328 } else { 329 330 if (!ret.hasPath()) { 331 return new FtpReply( 332 550, 333 "Requested action not taken. " 334 + request.getArgument() 335 + " already exists"); 336 } 337 338 String createdDirName = 339 conn.getConnectionManager().getConfig().getDirName(ret.getPath()); 340 if (!ListUtils.isLegalFileName(createdDirName)) { 341 return FtpReply.RESPONSE_553_REQUESTED_ACTION_NOT_TAKEN; 342 } 343 if (!conn.getConfig().checkMakeDir(conn.getUserNull(), dir)) { 344 return FtpReply.RESPONSE_530_ACCESS_DENIED; 345 } 346 347 try { 348 LinkedRemoteFile createdDir = 349 dir.createDirectory( 350 conn.getUserNull().getUsername(), 351 conn.getUserNull().getGroupName(), 352 createdDirName); 353 354 conn.getConnectionManager().dispatchFtpEvent( 355 new DirectoryFtpEvent(conn.getUserNull(), "MKD", createdDir)); 356 return new FtpReply( 357 257, 358 "\"" + createdDir.getPath() + "\" created."); 359 } catch (FileExistsException ex) { 360 return new FtpReply( 361 550, 362 "directory " + createdDirName + " already exists"); 363 } 364 } 365 } 366 367 373 private FtpReply doPWD(BaseFtpConnection conn) { 374 return new FtpReply( 375 257, 376 "\"" 377 + conn.getCurrentDirectory().getPath() 378 + "\" is current directory"); 379 } 380 381 389 private FtpReply doRMD(BaseFtpConnection conn) { 390 FtpRequest request = conn.getRequest(); 391 392 if (!request.hasArgument()) { 394 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 395 } 396 397 String fileName = request.getArgument(); 399 LinkedRemoteFile requestedFile; 400 try { 401 requestedFile = conn.getCurrentDirectory().lookupFile(fileName); 402 } catch (FileNotFoundException e) { 403 return new FtpReply(550, fileName + ": " + e.getMessage()); 404 } 405 406 if (requestedFile 407 .getUsername() 408 .equals(conn.getUserNull().getUsername())) { 409 if (!conn 410 .getConfig() 411 .checkDeleteOwn(conn.getUserNull(), requestedFile)) { 412 return FtpReply.RESPONSE_530_ACCESS_DENIED; 413 } 414 } else if ( 415 !conn.getConfig().checkDelete(conn.getUserNull(), requestedFile)) { 416 return FtpReply.RESPONSE_530_ACCESS_DENIED; 417 } 418 419 if (!requestedFile.isDirectory()) { 420 return new FtpReply(550, fileName + ": Not a directory"); 421 } 422 if (requestedFile.dirSize() != 0) { 423 return new FtpReply(550, fileName + ": Directory not empty"); 424 } 425 426 conn.getConnectionManager().dispatchFtpEvent( 429 new DirectoryFtpEvent(conn.getUserNull(), "RMD", requestedFile)); 430 requestedFile.delete(); 432 return FtpReply.RESPONSE_250_ACTION_OKAY; 433 } 434 435 448 private FtpReply doRNFR(BaseFtpConnection conn) { 449 FtpRequest request = conn.getRequest(); 450 451 if (!request.hasArgument()) { 453 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 454 } 455 456 458 463 try { 464 _renameFrom = 465 conn.getCurrentDirectory().lookupFile(request.getArgument()); 466 } catch (FileNotFoundException e) { 467 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN; 468 } 469 470 if (_renameFrom 472 .getUsername() 473 .equals(conn.getUserNull().getUsername())) { 474 if (!conn 475 .getConfig() 476 .checkRenameOwn(conn.getUserNull(), _renameFrom)) { 477 return FtpReply.RESPONSE_530_ACCESS_DENIED; 478 } 479 } else if ( 480 !conn.getConfig().checkRename(conn.getUserNull(), _renameFrom)) { 481 return FtpReply.RESPONSE_530_ACCESS_DENIED; 482 } 483 return new FtpReply(350, "File exists, ready for destination name"); 484 } 485 486 494 private FtpReply doRNTO(BaseFtpConnection conn) { 495 FtpRequest request = conn.getRequest(); 496 497 if (!request.hasArgument()) { 499 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 500 } 501 502 if (_renameFrom == null) { 504 return FtpReply.RESPONSE_503_BAD_SEQUENCE_OF_COMMANDS; 505 } 506 507 NonExistingFile ret = 508 conn.getCurrentDirectory().lookupNonExistingFile( 509 request.getArgument(), true); 510 LinkedRemoteFileInterface toDir = ret.getFile(); 511 String name = ret.getPath(); 512 if(toDir.isDeleted()) { 513 return new FtpReply(530, "Target file has been queued for deletion, can't overwrite"); 514 } 515 516 LinkedRemoteFileInterface fromFile = _renameFrom; 517 518 if (name == null) 519 name = fromFile.getName(); 520 522 if (_renameFrom 524 .getUsername() 525 .equals(conn.getUserNull().getUsername())) { 526 if (!conn.getConfig().checkRenameOwn(conn.getUserNull(), toDir)) { 527 return FtpReply.RESPONSE_530_ACCESS_DENIED; 528 } 529 } else if (!conn.getConfig().checkRename(conn.getUserNull(), toDir)) { 530 return FtpReply.RESPONSE_530_ACCESS_DENIED; 531 } 532 533 try { 534 fromFile.renameTo(toDir.getPath(), name); 535 } catch (IOException e) { 536 logger.warn("", e); 537 return new FtpReply(553, e.getMessage()); 538 } 540 541 return new FtpReply( 543 250, 544 request.getCommand() + " command successfull."); 545 } 546 547 private FtpReply doSITE_CHOWN(BaseFtpConnection conn) 548 throws UnhandledCommandException { 549 FtpRequest req = conn.getRequest(); 550 StringTokenizer st = 551 new StringTokenizer (conn.getRequest().getArgument()); 552 String owner = st.nextToken(); 553 String group = null; 554 int pos = owner.indexOf('.'); 555 if (pos != -1) { 556 group = owner.substring(pos + 1); 557 owner = owner.substring(0, pos); 558 } else if ("SITE CHGRP".equals(req.getCommand())) { 559 group = owner; 560 owner = null; 561 } else if (!"SITE CHOWN".equals(req.getCommand())) { 562 throw UnhandledCommandException.create(Dir.class, req); 563 } 564 FtpReply reply = new FtpReply(200); 565 566 while (st.hasMoreTokens()) { 567 try { 568 LinkedRemoteFileInterface file = 569 conn.getCurrentDirectory().lookupFile(st.nextToken()); 570 if (owner != null) 571 file.setOwner(owner); 572 if (group != null) 573 file.setGroup(group); 574 } catch (FileNotFoundException e) { 575 reply.addComment(e.getMessage()); 576 } 577 } 578 return FtpReply.RESPONSE_200_COMMAND_OK; 579 } 580 581 616 private FtpReply doSITE_WIPE(BaseFtpConnection conn) { 617 if (!conn.getUserNull().isAdmin()) { 618 return FtpReply.RESPONSE_530_ACCESS_DENIED; 619 } 620 if (!conn.getRequest().hasArgument()) { 621 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 622 } 623 624 String arg = conn.getRequest().getArgument(); 625 626 boolean recursive; 627 if (arg.startsWith("-r ")) { 628 arg = arg.substring(3); 629 recursive = true; 630 } else { 631 recursive = false; 632 } 633 634 LinkedRemoteFile wipeFile; 635 try { 636 wipeFile = conn.getCurrentDirectory().lookupFile(arg); 637 } catch (FileNotFoundException e) { 638 return new FtpReply( 639 200, 640 "Can't wipe: " 641 + arg 642 + " does not exist or it's not a plain file/directory"); 643 } 644 if (wipeFile.isDirectory() && wipeFile.dirSize() != 0 && !recursive) { 645 return new FtpReply(200, "Can't wipe, directory not empty"); 646 } 647 conn.getConnectionManager().dispatchFtpEvent( 649 new DirectoryFtpEvent(conn.getUserNull(), "WIPE", wipeFile)); 650 wipeFile.delete(); 652 return FtpReply.RESPONSE_200_COMMAND_OK; 653 } 654 655 660 private FtpReply doSIZE(BaseFtpConnection conn) { 661 FtpRequest request = conn.getRequest(); 662 if (!request.hasArgument()) { 663 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 664 } 665 LinkedRemoteFile file; 666 try { 667 file = conn.getCurrentDirectory().lookupFile(request.getArgument()); 668 } catch (FileNotFoundException ex) { 669 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN; 670 } 671 return new FtpReply(213, Long.toString(file.length())); 672 } 673 674 679 private FtpReply doXCRC(BaseFtpConnection conn) { 680 FtpRequest request = conn.getRequest(); 681 if (!request.hasArgument()) { 682 return FtpReply.RESPONSE_501_SYNTAX_ERROR; 683 } 684 StringTokenizer st = new StringTokenizer (request.getArgument()); 685 LinkedRemoteFile myFile; 686 try { 687 myFile = conn.getCurrentDirectory().lookupFile(st.nextToken()); 688 } catch (FileNotFoundException e) { 689 return FtpReply.RESPONSE_550_REQUESTED_ACTION_NOT_TAKEN; 690 } 691 692 if (st.hasMoreTokens()) { 693 if (!st.nextToken().equals("0") 694 || !st.nextToken().equals(Long.toString(myFile.length()))) { 695 return FtpReply.RESPONSE_504_COMMAND_NOT_IMPLEMENTED_FOR_PARM; 696 } 697 } 698 try { 699 return new FtpReply( 700 250, 701 "XCRC Successful. " 702 + Checksum.formatChecksum(myFile.getCheckSum())); 703 } catch (NoAvailableSlaveException e1) { 704 logger.warn("", e1); 705 return new FtpReply(550, "NoAvailableSlaveException: " + e1.getMessage()); 706 } 707 708 } 709 710 public FtpReply execute(BaseFtpConnection conn) 711 throws UnhandledCommandException { 712 FtpRequest request = conn.getRequest(); 713 String cmd = request.getCommand(); 714 if ("CDUP".equals(cmd)) 715 return doCDUP(conn); 716 if ("CWD".equals(cmd)) 717 return doCWD(conn); 718 if ("MKD".equals(cmd)) 719 return doMKD(conn); 720 if ("PWD".equals(cmd)) 721 return doPWD(conn); 722 if ("RMD".equals(cmd)) 723 return doRMD(conn); 724 if ("RNFR".equals(cmd)) 725 return doRNFR(conn); 726 if ("RNTO".equals(cmd)) 727 return doRNTO(conn); 728 if ("SITE WIPE".equals(cmd)) 729 return doSITE_WIPE(conn); 730 if ("XCRC".equals(cmd)) 731 return doXCRC(conn); 732 if ("MDTM".equals(cmd)) 733 return doMDTM(conn); 734 if ("SIZE".equals(cmd)) 735 return doSIZE(conn); 736 if ("DELE".equals(cmd)) 737 return doDELE(conn); 738 if ("SITE CHOWN".equals(cmd) || "SITE CHGRP".equals(cmd)) 739 return doSITE_CHOWN(conn); 740 throw UnhandledCommandException.create(Dir.class, request); 741 742 } 743 744 public String [] getFeatReplies() { 745 return null; 746 } 747 748 public CommandHandler initialize( 749 BaseFtpConnection conn, 750 CommandManager initializer) { 751 try { 752 return (Dir) clone(); 753 } catch (CloneNotSupportedException e) { 754 throw new RuntimeException (e); 755 } 756 } 757 public void load(CommandManagerFactory initializer) { 758 } 759 public void unload() { 760 } 761 } 762 | Popular Tags |