1 21 22 package org.armedbear.j; 23 24 import java.io.BufferedReader ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.InputStreamReader ; 28 import java.io.OutputStream ; 29 import java.io.OutputStreamWriter ; 30 import java.io.StringReader ; 31 import java.net.InetAddress ; 32 import java.net.ServerSocket ; 33 import java.net.Socket ; 34 import java.net.SocketException ; 35 import java.util.Random ; 36 import java.util.StringTokenizer ; 37 import java.util.Vector ; 38 import javax.swing.SwingUtilities ; 39 40 public class FtpSession implements Constants 41 { 42 private static final boolean echo = true; 43 private static final Vector sessionList = new Vector (); 44 45 private static CleanupThread cleanupThread; 46 47 private String host; 48 private int port; 49 private String user; 50 private String password; 51 private String loginDirectory; 52 private String currentDirectory; 53 private Socket controlSocket; 54 private BufferedReader controlIn; 55 private OutputStreamWriter controlOut; 56 private ServerSocket serverSocket; 57 private Socket dataSocket; 58 private InputStream dataIn; 59 private OutputStream dataOut; 60 private boolean connected; 61 private boolean usePassiveMode = true; 62 private String errorText; 63 private ProgressNotifier progressNotifier; 64 private boolean locked; 65 66 private FtpSession() 67 { 68 register(this); 69 } 70 71 private FtpSession(Login login, int port) 72 { 73 host = login.host; 74 user = login.user; 75 password = login.password; 76 this.port = port; 77 usePassiveMode = 78 Editor.preferences().getBooleanProperty(Property.FTP_USE_PASSIVE_MODE); 79 register(this); 80 } 81 82 private static synchronized void register(FtpSession session) 83 { 84 sessionList.add(session); 85 if (cleanupThread == null) { 86 cleanupThread = new CleanupThread(cleanupRunnable); 87 cleanupThread.start(); 88 } 89 } 90 91 private static synchronized void unregister(FtpSession session) 92 { 93 if (!sessionList.contains(session)) 94 Debug.bug(); 95 sessionList.remove(session); 96 } 97 98 protected Object clone() 99 { 100 FtpSession session = new FtpSession(); 101 session.host = host; 102 session.user = user; 103 session.password = password; 104 session.port = port; 105 session.usePassiveMode = usePassiveMode; 106 return session; 107 } 108 109 public final String getHost() 110 { 111 return host; 112 } 113 114 public final String getErrorText() 115 { 116 return errorText; 117 } 118 119 public final String getLoginDirectory() 120 { 121 return loginDirectory; 122 } 123 124 public final void setProgressNotifier(ProgressNotifier progressNotifier) 125 { 126 this.progressNotifier = progressNotifier; 127 } 128 129 public final boolean isLocked() 130 { 131 return locked; 132 } 133 134 private synchronized boolean lock() 135 { 136 if (locked) 137 return false; 138 locked = true; 139 return true; 140 } 141 142 public synchronized void unlock() 143 { 144 if (locked) { 145 progressNotifier = null; 146 locked = false; 147 } else 148 Debug.bug("FtpSession.unlock session was not locked"); 149 } 150 151 private boolean changeDirectory(String dirname) 152 { 153 if (dirname.equals(currentDirectory)) 154 return true; 155 command("CWD " + dirname); 156 String s= getReplyString(); 157 int code = getCode(s); 158 if (code == 421) { 159 connect(); 160 if (connected) { 161 command("CWD " + dirname); 162 s = getReplyString(); 163 } 164 else 165 return false; 166 } 167 if (getCode(s) == 250) { 168 currentDirectory = dirname; 169 return true; 170 } 171 return false; 172 } 173 174 public boolean isDirectory(String remotePath) 175 { 176 if (changeDirectory(remotePath)) 177 return true; 178 179 return false; 180 } 181 182 public boolean isFile(String remotePath) 183 { 184 command("SIZE " + remotePath); 185 String s = getReplyString(); 186 int code = getCode(s); 187 if (code == 213) 188 return true; 189 if (code == 500) { 190 String listing = getDirectoryListingForFile(remotePath); 192 if (listing != null && listing.length() > 0) { 193 char c = listing.charAt(0); 194 if (c == '-' || c == 'l') 195 return true; 196 } 197 } 198 return false; 199 } 200 201 public boolean exists(String remotePath) 202 { 203 if (isDirectory(remotePath)) 204 return true; 205 else 206 return isFile(remotePath); 207 } 208 209 private long getFileSize(String remotePath) 210 { 211 long fileSize = -1; 212 command("SIZE " + remotePath); 213 String s = getReplyString(); 214 if (getCode(s) == 213) { 215 s = s.substring(3).trim(); 216 try { 217 fileSize = Long.parseLong(s); 218 } 219 catch (NumberFormatException e) { 220 Log.error(e); 221 } 222 } 223 return fileSize; 224 } 225 226 boolean deleteFile(String remotePath) 227 { 228 command("DELE " + remotePath); 229 return getReply() == 250; 230 } 231 232 boolean removeDirectory(String remotePath) 233 { 234 command("RMD " + remotePath); 235 return getReply() == 250; 236 } 237 238 public boolean chmod(FtpFile file, int permissions) 239 { 240 if (permissions != 0) { 241 FastStringBuffer sb = new FastStringBuffer("SITE CHMOD "); 242 sb.append(Integer.toString(permissions, 8)); 243 sb.append(' '); 244 sb.append(file.canonicalPath()); 245 command(sb.toString()); 246 return getReply() == 200; 247 } 248 else 249 return false; 250 } 251 252 public int getPermissions(FtpFile file) 253 { 254 int permissions = 0; 255 String listing = getDirectoryListingForFile(file.canonicalPath()); 256 if (listing != null) { 257 String s = listing.substring(1, 10); 258 Log.debug("s = |" + s + "|"); 259 if (s.length() == 9) { 260 if (s.charAt(0) == 'r') 261 permissions += 0400; 262 if (s.charAt(1) == 'w') 263 permissions += 0200; 264 if (s.charAt(2) == 'x') 265 permissions += 0100; 266 if (s.charAt(3) == 'r') 267 permissions += 040; 268 if (s.charAt(4) == 'w') 269 permissions += 020; 270 if (s.charAt(5) == 'x') 271 permissions += 010; 272 if (s.charAt(6) == 'r') 273 permissions += 4; 274 if (s.charAt(7) == 'w') 275 permissions += 2; 276 if (s.charAt(8) == 'x') 277 permissions += 1; 278 } 279 } 280 return permissions; 281 } 282 283 int getFileStatus(String filename) 284 { 285 if (!connected) { 286 connect(); 287 if (!connected) 288 return -1; 289 } 290 if (changeDirectory(filename)) 291 return 2; if (!openDataSocket()) 294 return -1; 295 int status = -1; command("LIST " + filename); 297 int code = getReply(); 298 if (code == 125 || code == 150 || code == 226) { 302 String s = getData(); 303 closeDataSocket(); 304 if (s != null && s.length() > 10) { 306 char c = s.charAt(0); 307 if (c == 'd') 308 status = 2; else if (c == '-') 310 status = 1; 311 if (status != -1) { 312 boolean valid = true; 314 c = s.charAt(1); 315 if (c != 'r' && c != 'w' && c != '-') 316 valid = false; 317 else { 318 c = s.charAt(2); 319 if (c != 'r' && c != 'w' && c != '-') 320 valid = false; 321 } 322 if (!valid) 323 status = -1; 324 } 325 } 326 if (code == 125 || code == 150) 330 getReply(226); 331 } 332 return status; 333 } 334 335 public String getDirectoryListing(File file) 336 { 337 if (!(file instanceof FtpFile)) { 338 Debug.bug(); 339 return null; 340 } 341 Debug.assertTrue(isLocked()); 342 String listing = DirectoryCache.getDirectoryCache().getListing(file); 343 if (listing == null) { 344 listing = getDirectoryListing(file.canonicalPath()); 345 if (listing != null) 346 DirectoryCache.getDirectoryCache().put(file, listing); 347 } 348 return listing; 349 } 350 351 public String getDirectoryListing(String dirname) 352 { 353 Debug.assertTrue(isLocked()); 354 String listing = null; 355 if (verifyConnected()) { 356 if (changeDirectory(dirname)) { 357 if (openDataSocket()) { 358 command("LIST -la"); 359 int code = getReply(); 360 361 if (code == 125 || code == 150 || code == 226) 365 listing = getData(); 366 367 closeDataSocket(); 368 if (code == 125 || code == 150) 369 getReply(226); 370 } 371 } 372 } 373 return listing; 374 } 375 376 public String getDirectoryListingForFile(String filename) 377 { 378 String listing = null; 379 if (connected) { 380 if (openDataSocket()) { 381 command("LIST -la " + filename); 382 int code = getReply(); 383 384 if (code == 125 || code == 150 || code == 226) 388 listing = getData(); 389 390 closeDataSocket(); 391 if (code == 125 || code == 150) 392 getReply(226); 393 } 394 } 395 396 400 403 406 if (listing == null || listing.length() == 0) { 407 int index = filename.lastIndexOf('/'); 408 if (index >= 0) { 409 String parent = index == 0 ? "/" : filename.substring(0, index); 410 String name = filename.substring(index + 1); 411 String parentListing = getDirectoryListing(parent); 412 if (parentListing != null) { 413 BufferedReader reader = 414 new BufferedReader (new StringReader (parentListing)); 415 String entry; 416 try { 417 while ((entry = reader.readLine()) != null) { 418 if (name.equals(DirectoryEntry.getName(entry))) { 419 listing = entry; 421 break; 422 } 423 } 424 } 425 catch (IOException e) { 426 Log.error(e); 427 } 428 } 429 } 430 } 431 432 Log.debug("getDirectoryListingForFile |" + listing + "|"); 433 return listing; 434 } 435 436 public int put(File localFile, File remoteFile, long fileSize, boolean saveInPlace) 437 { 438 boolean succeeded = false; 439 boolean cancelled = false; 440 String tempName = null; 441 442 if (changeDirectory(remoteFile.getParent())) { 444 OutputStream out = null; 445 if (saveInPlace) { 446 out = getOutputStreamForFile(remoteFile.canonicalPath()); 447 } else { 448 tempName = getUniqueName(remoteFile.getParentFile()); 451 Log.debug("tempName = |" + tempName + "|"); 452 if (tempName != null) 453 out = getOutputStreamForFile(tempName); 454 } 455 if (out != null) { 456 try { 457 InputStream in = localFile.getInputStream(); 458 byte[] bytes = new byte[16384]; 459 long totalBytes = 0; 460 int bytesRead; 461 if (progressNotifier != null) 462 progressNotifier.progressStart(); 463 while((bytesRead = in.read(bytes)) > 0) { 464 out.write(bytes, 0, bytesRead); 465 totalBytes += bytesRead; 466 if (progressNotifier != null) { 467 if (progressNotifier.cancelled()) { 468 cancelled = true; 469 break; 470 } 471 progressNotifier.progress("Sent ", totalBytes, fileSize); 472 } 473 Debug.throttle(); 475 } 476 if (progressNotifier != null) 477 progressNotifier.progressStop(); 478 out.flush(); 479 out.close(); 480 closeDataSocket(); 481 in.close(); 482 succeeded = getReply(226); 483 if (cancelled && tempName != null) { 484 command("DELE " + tempName); 485 getReplyString(); } 487 } 488 catch (Exception e) { 489 Log.error(e); 490 } 491 } 492 } 493 494 if (succeeded && !cancelled && tempName != null) { 495 do { 496 if (progressNotifier != null) 497 progressNotifier.setText("Renaming temporary file"); 498 command("RNFR " + tempName); 499 if (!getReply(350)) { 500 succeeded = false; 501 break; 502 } 503 command("RNTO " + remoteFile.canonicalPath()); 504 if (!getReply(250)) 505 succeeded = false; 506 break; 507 } while (false); 508 } 509 510 if (progressNotifier != null) { 511 if (cancelled) 512 progressNotifier.setText("Transfer cancelled"); 513 else if (succeeded) 514 progressNotifier.setText("Transfer completed"); 515 else 516 progressNotifier.setText("Transfer failed"); 517 } 518 519 if (cancelled) 520 return CANCELLED; 521 else if (succeeded) 522 return SUCCESS; 523 else 524 return ERROR; 525 } 526 527 private static Random random; 528 529 private String getUniqueName(File dir) 530 { 531 long now = System.currentTimeMillis(); 532 if (random == null) { 533 random = new Random (now - Editor.getStartTimeMillis()); 535 } 536 long n = now + Math.abs(random.nextLong() % now); 537 for (int i = 0; i < 100; i++) { 538 File file = File.getInstance(dir, String.valueOf(n)); 539 String name = file.canonicalPath(); 540 if (!exists(name)) { 541 Log.debug("unique name = |" + name + "|"); 542 return name; 543 } 544 n += Math.abs(random.nextLong() % now); 545 } 546 return null; 547 } 548 549 public int get(File remoteFile, File localFile, long fileSize) 550 { 551 boolean succeeded = false; 552 boolean cancelled = false; 553 if (fileSize == 0) { 554 fileSize = getFileSize(remoteFile.canonicalPath()); 555 if (fileSize < 0) fileSize = 0; 557 } 558 InputStream in = getInputStreamForFile(remoteFile.canonicalPath()); 559 if (in == null) 560 return ERROR; 561 try { 562 OutputStream out = localFile.getOutputStream(); 563 byte[] bytes = new byte[16384]; 564 long totalBytes = 0; 565 566 if (progressNotifier != null) 567 progressNotifier.progressStart(); 568 569 while (true) { 570 int bytesRead = 0; 571 try { 572 bytesRead = in.read(bytes); 574 } 575 catch (Exception e) { 576 if (progressNotifier == null || !progressNotifier.cancelled()) 577 Log.error(e); 578 else 579 Log.debug("FtpSession.get cancelled"); 581 } 582 if (bytesRead <= 0) 583 break; 584 out.write(bytes, 0, bytesRead); 585 totalBytes += bytesRead; 586 if (progressNotifier != null) { 587 if (progressNotifier.cancelled()) { 588 cancelled = true; 589 break; 590 } 591 progressNotifier.progress("Received ", totalBytes, fileSize); 592 } 593 Debug.throttle(); 595 } 596 if (progressNotifier != null) 597 progressNotifier.progressStop(); 598 out.flush(); 601 out.close(); 602 in.close(); 603 closeDataSocket(); 604 if (cancelled) 605 localFile.delete(); 606 succeeded = getReply(226); 607 } 608 catch (SocketException e) { 609 if (cancelled) 610 ; else 612 Log.error(e); 613 } 614 catch (Exception e) { 615 Log.error(e); 616 } 617 if (progressNotifier != null) { 618 if (cancelled) 619 progressNotifier.setText("Transfer cancelled"); 620 else if (succeeded) 621 progressNotifier.setText("Transfer completed"); 622 else 623 progressNotifier.setText("Transfer failed"); 624 } 625 if (cancelled) 626 return CANCELLED; 627 else if (succeeded) 628 return SUCCESS; 629 else 630 return ERROR; 631 } 632 633 public synchronized boolean verifyConnected() 634 { 635 if (connected) { 636 command("NOOP"); 637 if (getReply() == 421) { 638 Log.debug("verifyConnected calling connect"); 639 connect(); 640 } 641 } else 642 connect(); 643 if (connected && progressNotifier != null) 644 progressNotifier.setText("Connected to " + host); 645 return connected; 646 } 647 648 private synchronized void connect() 649 { 650 if (progressNotifier != null) 651 progressNotifier.setText("Connecting to " + host); 652 Log.debug("connecting to " + host); 653 654 connected = false; 655 loginDirectory = null; 656 currentDirectory = null; 657 errorText = null; 658 659 SocketConnection sc = new SocketConnection(host, port, 30000, 200, progressNotifier); 660 controlSocket = sc.connect(); 661 if (controlSocket == null) { 662 errorText = sc.getErrorText(); 663 return; 664 } 665 666 try { 667 controlIn = 668 new BufferedReader (new InputStreamReader (controlSocket.getInputStream())); 669 controlOut = new OutputStreamWriter (controlSocket.getOutputStream()); 670 } 671 catch (IOException e) { 672 Log.error(e); 673 disconnect(); 674 return; 675 } 676 getReplyString(); 677 command("USER " + user); 678 int code = getReply(); 679 if (code == 331) { 680 if (password != null) { 682 command("PASS " + password); 683 code = getReply(); 684 if (code == 530) { 685 errorText = "Login incorrect"; 686 user = null; 687 password = null; 688 } 689 } 690 } 691 if (code != 230) { 692 if (errorText == null || errorText.length() == 0) { 693 if (lastReply != null) 694 errorText = lastReply.substring(3).trim(); 695 if (errorText == null || errorText.length() == 0) 696 errorText = "Unable to connect to " + host; 697 } 698 disconnect(); 699 return; 700 } 701 702 command("PWD"); 704 String s = getReplyString(); 705 int begin = s.indexOf('"'); 706 if (begin >= 0) { 707 int end = s.indexOf('"', ++begin); 708 if (end >= 0) 709 loginDirectory = currentDirectory = s.substring(begin, end); 710 } 711 712 command("TYPE I"); 713 code = getReply(); 714 if (code != 200) { 715 Log.error("connect didn't get 200"); 716 disconnect(); 717 return; 718 } 719 720 connected = true; 721 Log.debug("connected!"); 722 } 723 724 private void command(String s) 725 { 726 boolean reconnect = false; 727 if (echo) 728 Log.debug("==> " + (s.startsWith("PASS ") ? "PASS" : s)); 729 try { 730 controlOut.write(s + "\r\n"); 731 controlOut.flush(); 732 return; 733 } 734 catch (Exception e) { 735 Log.error("exception command " + s); 736 reconnect = true; 737 } 738 if (reconnect) { 739 Log.debug("trying to reconnect..."); 742 connect(); 743 if (connected) { 744 if (echo) 745 Log.debug("==> " + (s.startsWith("PASS ") ? "PASS" : s)); 746 try { 747 controlOut.write(s + "\r\n"); 748 controlOut.flush(); 749 return; 750 } 751 catch (Exception e) { 752 Log.error("2nd exception command " + s); 753 reconnect = true; 754 } 755 } 756 } 757 } 758 759 private String lastReply; 760 761 private String getReplyString() 763 { 764 String s = null; 765 try { 766 do { 767 s = controlIn.readLine(); 768 if (echo && s != null) 769 Log.debug("<== " + s); 770 } while (s != null && !isEndOfReply(s)); 771 } 772 catch (Exception e) {} 773 lastReply = s; 774 return s; 775 } 776 777 private static boolean isEndOfReply(String s) 778 { 779 if (s != null && 781 s.length() >= 4 && 782 s.charAt(3) == ' ' && 783 Character.isDigit(s.charAt(0)) && 784 Character.isDigit(s.charAt(1)) && 785 Character.isDigit(s.charAt(2))) 786 { 787 return true; 788 } 789 790 return false; 791 } 792 793 private boolean getReply(int required) 794 { 795 String s = getReplyString(); 796 if (s == null) 797 return false; 798 return getCode(s) == required; 799 } 800 801 private int getReply() 802 { 803 String s = getReplyString(); 804 if (s == null) 805 return 421; 806 return getCode(s); 807 } 808 809 private static int getCode(String reply) 810 { 811 int code = -1; 812 if (reply != null) { 813 try { 816 code = Integer.parseInt(reply.substring(0, 3)); 817 } 818 catch (NumberFormatException e) { 819 Log.error(e); 820 } 821 } 822 return code; 823 } 824 825 private String getData() 826 { 827 if (!usePassiveMode) 828 acceptConnectionFromServer(); 829 byte[] buf = new byte[16384]; 830 FastStringBuffer sb = new FastStringBuffer(); 831 try { 832 while (true) { 833 int bytesRead = dataIn.read(buf); if (bytesRead < 0) 835 break; 836 sb.append(new String (buf, 0, bytesRead)); 837 } 838 } 839 catch (IOException e) { 840 Log.error(e); 841 } 842 return sb.toString(); 843 } 844 845 private void closeDataSocket() 846 { 847 if (dataSocket != null) { 848 if (dataIn != null) { 849 try { 850 dataIn.close(); 851 } 852 catch (IOException e) { 853 Log.error(e); 854 } 855 } 856 if (dataOut != null) { 857 try { 858 dataOut.close(); 859 } 860 catch (IOException e) { 861 Log.error(e); 862 } 863 } 864 try { 865 dataSocket.close(); 866 } 867 catch (IOException e){ 868 Log.error(e); 869 } 870 dataSocket = null; 871 dataIn = null; 872 dataOut = null; 873 } 874 } 875 876 private boolean openDataSocket() 877 { 878 if (!connected) { 879 connect(); 880 if (!connected) 881 return false; 882 } 883 closeDataSocket(); 884 if (usePassiveMode) { 885 command("PASV"); 886 String reply; 887 while (true){ 888 reply = getReplyString(); 889 if (reply == null) { 890 Log.error("openDataSocket null reply to PASV"); 891 return false; 892 } 893 int code = getCode(reply); 894 if (code >= 400) 895 return false; if (code == 227) 897 break; } 901 int begin = reply.indexOf('('); 902 if (begin < 0) 903 return false; 904 int end = reply.indexOf(')'); 905 if (end < 0) 906 return false; 907 String s = reply.substring(begin+1, end); 908 StringTokenizer st = new StringTokenizer (s, ",", false); 909 if (st.countTokens() != 6) 910 return false; 911 String [] addr = new String [4]; 912 for (int i = 0; i < 4; i++) 913 addr[i] = st.nextToken(); 914 String address = addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3]; 915 try { 916 int hibyte = Integer.parseInt(st.nextToken()); 917 int lobyte = Integer.parseInt(st.nextToken()); 918 int dataPort = hibyte * 256 + lobyte; 919 Log.debug("opening data socket"); 920 dataSocket = new Socket (address, dataPort); 921 dataIn = dataSocket.getInputStream(); 922 dataOut = dataSocket.getOutputStream(); 923 } 924 catch (NumberFormatException e) { 925 Log.error(e); 926 } 927 catch (IOException ex) { 928 Log.error(ex); 929 } 930 return dataSocket != null; 931 } else { 932 try { 934 InetAddress localHost = controlSocket.getLocalAddress(); 935 serverSocket = new ServerSocket (0); 936 int dataPort = serverSocket.getLocalPort(); 937 int lobyte = (dataPort & 0x00ff); 938 int hibyte = ((dataPort & 0xff00) >> 8); 939 byte[] addrBytes = localHost.getAddress(); 940 int[] addr = new int[4]; 941 for (int i = 0; i < 4; i++) { 942 addr[i] = addrBytes[i]; 943 if (addr[i] < 0) 944 addr[i] += 256; 945 } 946 String s = "PORT " + addr[0] + "," + addr[1] + "," + addr[2] + "," + addr[3] + "," + hibyte + "," + lobyte; 947 command(s); 948 return getReply(200); 949 } 950 catch (Exception e) { 951 Log.error(e); 952 } 953 return false; 954 } 955 } 956 957 private void acceptConnectionFromServer() 958 { 959 try { 960 dataSocket = serverSocket.accept(); 961 if (dataSocket != null) { 962 dataIn = dataSocket.getInputStream(); 963 dataOut = dataSocket.getOutputStream(); 964 } 965 } 966 catch (Exception e) { 967 Log.error(e); 968 } 969 } 970 971 private InputStream getInputStreamForFile(String filename) 972 { 973 if (openDataSocket()) { 974 command("RETR " + filename); 975 int code = getCode(getReplyString()); 976 if (code > -1 && code < 400) { 977 if (!usePassiveMode) 978 acceptConnectionFromServer(); 979 return dataIn; 980 } 981 } 982 return null; 983 } 984 985 private OutputStream getOutputStreamForFile(String filename) 986 { 987 if (filename == null) 988 return null; 989 if (openDataSocket()) { 990 command("STOR " + filename); 991 int code = getCode(getReplyString()); 992 if (code > -1 && code < 400) { 993 if (!usePassiveMode) 994 acceptConnectionFromServer(); 995 return dataOut; 996 } 997 if (code == 550 || code == 553) 998 errorText = "Access denied"; 999 } 1000 return null; 1001 } 1002 1003 private static synchronized void cleanup() 1004 { 1005 if (!SwingUtilities.isEventDispatchThread()) { 1007 Debug.bug(); 1008 return; 1009 } 1010 if (sessionList.size() == 0) 1011 return; for (int i = sessionList.size(); i-- > 0;) { 1013 FtpSession session = (FtpSession) sessionList.get(i); 1014 String host = session.getHost(); 1015 boolean inUse = false; 1016 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 1017 Buffer buf = it.nextBuffer(); 1018 if (buf.getFile() instanceof FtpFile) { 1019 if (host.equals(buf.getFile().getHostName())) { 1020 inUse = true; 1021 break; 1022 } 1023 } 1024 } 1025 if (!inUse) { 1026 session.close(); 1027 unregister(session); 1028 } 1029 } 1030 if (sessionList.size() == 0) { 1031 if (cleanupThread != null) { 1032 cleanupThread.cancel(); 1033 cleanupThread = null; 1034 } 1035 } 1036 } 1037 1038 private static final Runnable cleanupRunnable = new Runnable () { 1039 public void run() 1040 { 1041 cleanup(); 1042 } 1043 }; 1044 1045 public synchronized void disconnect() 1046 { 1047 Log.debug("disconnect"); 1048 if (controlSocket != null) { 1049 Log.debug("closing control socket..."); 1050 try { 1051 controlSocket.close(); 1052 } 1053 catch (IOException e) { 1054 Log.error(e); 1055 } 1056 controlSocket = null; 1057 controlIn = null; 1058 controlOut = null; 1059 } 1060 if (dataSocket != null) { 1061 Log.debug("closing data socket..."); 1062 try { 1063 dataSocket.close(); 1064 } 1065 catch (IOException e) { 1066 Log.error(e); 1067 } 1068 dataSocket = null; 1069 dataIn = null; 1070 dataOut = null; 1071 } 1072 connected = false; 1073 } 1074 1075 private void close() 1076 { 1077 Log.debug("FtpSession.close"); 1078 if (connected) { 1079 final Editor editor = Editor.currentEditor(); 1080 editor.setWaitCursor(); 1081 Runnable r = new Runnable () { 1082 public void run() 1083 { 1084 try { 1085 if (echo) 1086 Log.debug("==> QUIT"); 1087 controlOut.write("QUIT\r\n"); 1088 controlOut.flush(); 1089 getReply(); 1090 } 1091 catch (IOException e) {} 1092 } 1093 }; 1094 Thread t = new Thread (r); 1095 t.start(); 1096 try { 1097 t.join(3000); 1098 } 1099 catch (InterruptedException e) { 1100 Log.error(e); 1101 } 1102 if (t.isAlive()) { 1103 Log.debug("stopping QUIT thread"); 1104 t.stop(); 1105 } 1106 disconnect(); 1107 editor.setDefaultCursor(); 1108 } 1109 Log.debug("leaving close"); 1110 } 1111 1112 public static synchronized FtpSession getSession(FtpFile file) 1113 { 1114 if (file == null) 1115 return null; 1116 Login login = new Login(file.getHostName(), file.getUserName(), file.getPassword()); 1117 if (login == null) 1118 return null; FtpSession session = lockSession(login.host, file.getPort()); 1121 if (session != null) { 1122 if (session.checkLogin()) 1123 return session; 1124 1125 session.unlock(); 1126 return null; 1127 } 1128 session = findSession(login.host, file.getPort()); 1130 if (session != null) { 1131 session = (FtpSession) session.clone(); 1132 if (session.lock()) { 1133 if (session.checkLogin()) 1134 return session; 1135 session.unlock(); 1136 } 1137 return null; 1138 } 1139 if (login.user == null || login.password == null) { 1140 final Editor editor = Editor.currentEditor(); 1142 if (login.user == null) { 1143 Login maybe = Netrc.getLogin(login.host); 1146 if (maybe != null) { 1147 login.user = maybe.user; 1148 login.password = maybe.password; 1149 } 1150 if (login.user == null) { 1151 login.user = InputDialog.showInputDialog(editor, "Login:", "Login on " + login.host); 1153 editor.repaintNow(); 1154 } 1155 } 1156 if (login.user == null) 1157 return null; if (login.user.length() == 0) 1159 login.user = "anonymous"; 1160 if (login.password == null) { 1161 login.password = Netrc.getPassword(login.host, login.user); 1163 if (login.password == null) { 1164 if (login.user.equals("anonymous")) 1165 login.password = Editor.preferences().getStringProperty(Property.FTP_ANONYMOUS_PASSWORD); 1166 if (login.password == null) { 1167 login.password = PasswordDialog.showPasswordDialog(editor, "Password:", "Password"); 1169 editor.repaintNow(); 1170 } 1171 } 1172 } 1173 if (login.password == null) 1176 return null; 1177 } 1178 if (login.user.length() == 0) 1180 return null; 1181 session = new FtpSession(login, file.getPort()); 1184 if (session.lock()) 1185 return session; 1186 return null; 1187 } 1188 1189 private boolean checkLogin() 1193 { 1194 final Editor editor = Editor.currentEditor(); 1195 if (user == null) { 1196 user = InputDialog.showInputDialog(editor, "Login:", "Login on " + host); 1198 editor.repaintNow(); 1199 if (user == null) 1200 return false; } 1202 if (user.length() == 0) 1203 user = "anonymous"; 1204 if (password == null) { 1205 password = PasswordDialog.showPasswordDialog(editor, "Password:", "Password"); 1207 editor.repaintNow(); 1208 if (password == null) 1210 return false; 1211 } 1212 if (user.length() == 0) 1214 return false; 1215 return true; 1216 } 1217 1218 private static FtpSession lockSession(String host, int port) 1219 { 1220 for (int i = 0; i < sessionList.size(); i++) { 1221 FtpSession session = (FtpSession) sessionList.get(i); 1222 if (session.host.equals(host) && session.port == port) { 1223 if (session.lock()) 1224 return session; 1225 } 1226 } 1227 return null; 1228 } 1229 1230 private static FtpSession findSession(String host, int port) 1231 { 1232 for (int i = 0; i < sessionList.size(); i++) { 1233 FtpSession session = (FtpSession) sessionList.get(i); 1234 if (session.host.equals(host) && session.port == port) 1235 return session; 1236 } 1237 return null; 1238 } 1239} 1240 | Popular Tags |