1 16 package net.sf.jftp.net; 17 18 import java.io.BufferedInputStream ; 19 import java.io.BufferedOutputStream ; 20 import java.io.File ; 21 import java.io.FileInputStream ; 22 import java.io.FileOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.StreamTokenizer ; 26 import java.util.Date ; 27 import java.util.Enumeration ; 28 import java.util.Vector ; 29 30 import javax.swing.JOptionPane ; 31 32 import net.sf.jftp.config.Settings; 33 import net.sf.jftp.system.StringUtils; 34 import net.sf.jftp.system.logging.Log; 35 36 import com.jcraft.jsch.Channel; 37 import com.jcraft.jsch.ChannelSftp; 38 import com.jcraft.jsch.JSch; 39 import com.jcraft.jsch.Session; 40 import com.jcraft.jsch.SftpException; 41 import com.jcraft.jsch.UserInfo; 42 import com.jcraft.jsch.ChannelSftp.LsEntry; 43 import com.sshtools.j2ssh.sftp.SftpFile; 44 import com.sshtools.j2ssh.sftp.SftpFileInputStream; 45 import com.sshtools.j2ssh.sftp.SftpFileOutputStream; 46 import com.sshtools.j2ssh.sftp.SftpSubsystemClient; 47 48 49 public class Sftp2Connection implements BasicConnection 50 { 51 public static int smbBuffer = 32000; 52 private String path = ""; 53 private String pwd = "/"; 54 private Vector listeners = new Vector (); 55 private String [] files; 56 private String [] size = new String [0]; 57 private int[] perms = null; 58 private String user; 59 private String pass; 60 private String host; 61 private String baseFile; 62 private int fileCount; 63 private boolean isDirUpload = false; 64 private boolean shortProgress = false; 65 private int RW = SftpSubsystemClient.OPEN_CREATE | 66 SftpSubsystemClient.OPEN_WRITE; 67 private int W = SftpSubsystemClient.OPEN_CREATE; 68 private int R = SftpSubsystemClient.OPEN_READ; 69 private int port = 22; 70 private boolean connected = false; 71 private String keyfile = null; 72 private Session session; 73 private ChannelSftp channel; 74 75 public Sftp2Connection(String host, String port, String keyfile) 76 { 77 this.host = host; 78 this.port = Integer.parseInt(port); 79 this.keyfile = keyfile; 80 81 Log.debug("Using JSch wrapper..."); 82 } 83 84 private boolean login() 85 { 86 try 87 { 88 JSch jsch = new JSch(); 89 if(keyfile != null) { 90 jsch.addIdentity(keyfile); 91 } 92 session = jsch.getSession(user, host, this.port); 93 UserInfo ui = new MyUserInfo(pass); 94 session.setUserInfo(ui); 95 session.connect(); 96 97 98 channel = (ChannelSftp) session.openChannel("sftp"); 99 channel.connect(); 100 101 Log.debug("Host: "+host+":"+port); 102 103 connected = true; 104 return true; 105 } 106 catch(Exception ex) 107 { 108 ex.printStackTrace(); 109 Log.debug("Error: " + ex); 110 111 return false; 112 } 113 } 114 115 public int removeFileOrDir(String file) 116 { 117 file = toSFTP(file); 118 119 try 120 { 121 122 if(!file.endsWith("/")) 123 { 124 Log.out(">>>>>>>> remove file: " + file); 125 channel.rm(file); 126 } 127 else 128 { 129 Log.out(">>>>>>>> remove dir: " + file); 130 cleanSftpDir(file); 131 channel.rmdir(file); 132 } 133 } 134 catch(Exception ex) 135 { 136 ex.printStackTrace(); 137 Log.debug("Removal failed (" + ex + ")."); 138 ex.printStackTrace(); 139 140 return -1; 141 } 142 143 return 1; 144 } 145 146 private void cleanSftpDir(String dir) 147 throws Exception 148 { 149 Log.out(">>>>>>>> cleanSftpDir: " + dir); 150 151 Vector v = channel.ls(dir); 152 153 String [] tmp = new String [v.size()]; 154 Enumeration e = v.elements(); 155 int x = 0; 156 157 while(e.hasMoreElements()) 158 { 159 LsEntry entry = ((LsEntry)e.nextElement()); 160 tmp[x] = entry.getFilename(); 161 162 if(entry.getAttrs().isDir() && !tmp[x].endsWith("/")) 164 { 165 tmp[x] = tmp[x] + "/"; 166 } 167 168 x++; 169 } 170 171 if(tmp == null) 172 { 173 return; 174 } 175 176 for(int i = 0; i < tmp.length; i++) 177 { 178 if(tmp[i].equals("./") || tmp[i].equals("../")) 179 { 180 continue; 181 } 182 183 Log.out(">>>>>>>> remove file/dir: " + dir + tmp[i]); 184 185 if(tmp[i].endsWith("/")) 186 { 187 cleanSftpDir(dir + tmp[i]); 188 channel.rmdir(dir + tmp[i]); 189 } 190 else 191 { 192 channel.rm(dir + tmp[i]); 193 } 194 } 195 } 196 197 public void sendRawCommand(String cmd) 198 { 199 } 200 201 public void disconnect() 202 { 203 try 204 { 205 channel.disconnect(); 206 session.disconnect(); 207 } 208 catch(Exception e) 209 { 210 e.printStackTrace(); 211 Log.debug("Sftp2Connection.disconnect()" + e); 212 } 213 214 connected = false; 215 } 216 217 public boolean isConnected() 218 { 219 return connected; 220 } 221 222 public String getPWD() 223 { 224 return toSFTPDir(pwd); 226 } 227 228 public boolean mkdir(String dirName) 229 { 230 try 231 { 232 if(!dirName.endsWith("/")) 233 { 234 dirName = dirName + "/"; 235 } 236 237 dirName = toSFTP(dirName); 238 239 channel.mkdir(dirName); 240 241 fireDirectoryUpdate(); 242 243 return true; 244 } 245 catch(Exception ex) 246 { 247 Log.debug("Failed to create directory (" + ex + ")."); 248 249 return false; 250 } 251 } 252 253 public void list() throws IOException 254 { 255 } 256 257 public boolean chdir(String p) 258 { 259 return chdir(p, true); 260 } 261 262 public boolean chdir(String p, boolean refresh) 263 { 264 String tmp = toSFTP(p); 265 266 try 267 { 268 if(!tmp.endsWith("/")) 269 { 270 tmp = tmp + "/"; 271 } 272 if(tmp.endsWith("../")) 273 { 274 return cdup(); 275 } 276 277 System.out.println("sftp path: "+tmp+", chan: "+channel); 278 channel.cd(tmp); 279 280 pwd = tmp; 281 282 if(refresh) 284 { 285 fireDirectoryUpdate(); 286 } 287 288 return true; 291 } 292 catch(Exception ex) 293 { 294 ex.printStackTrace(); 295 296 Log.debug("Could not change directory (" + ex + ")."); 298 299 return false; 300 } 301 } 302 303 public boolean cdup() 304 { 305 String tmp = pwd; 306 307 if(pwd.endsWith("/")) 308 { 309 tmp = pwd.substring(0, pwd.lastIndexOf("/")); 310 } 311 312 return chdir(tmp.substring(0, tmp.lastIndexOf("/") + 1)); 313 } 314 315 public boolean chdirNoRefresh(String p) 316 { 317 return chdir(p, false); 318 } 319 320 public String getLocalPath() 321 { 322 return path; 323 } 324 325 public boolean setLocalPath(String p) 326 { 327 if(StringUtils.isRelative(p)) 328 { 329 p = path + p; 330 } 331 332 p = p.replace('\\', '/'); 333 334 File f = new File (p); 336 337 if(f.exists()) 338 { 339 try 340 { 341 path = f.getCanonicalPath(); 342 path = path.replace('\\', '/'); 343 344 if(!path.endsWith("/")) 345 { 346 path = path + "/"; 347 } 348 349 } 351 catch(IOException ex) 352 { 353 Log.debug("Error: can not get pathname (local)!"); 354 355 return false; 356 } 357 } 358 else 359 { 360 Log.debug("(local) No such path: \"" + p + "\""); 361 362 return false; 363 } 364 365 return true; 366 } 367 368 public String [] sortLs() 369 { 370 try 371 { 372 System.out.println(pwd); 373 Vector v = channel.ls(pwd); 374 375 String [] tmp = new String [v.size()]; 376 files = new String [tmp.length]; 377 size = new String [tmp.length]; 378 perms = new int[tmp.length]; 379 380 Enumeration e = v.elements(); 381 int x = 0; 382 383 while(e.hasMoreElements()) 384 { 385 LsEntry entry = ((LsEntry)e.nextElement()); 386 tmp[x] = entry.getFilename(); 387 388 size[x] = ""+entry.getAttrs().getSize(); 389 390 392 399 perms[x] = FtpConnection.R; 400 402 if(entry.getAttrs().isDir() && !tmp[x].endsWith("/")) 404 { 405 tmp[x] = tmp[x] + "/"; 406 } 407 408 x++; 409 } 410 411 for(int i = 0; i < tmp.length; i++) 412 { 413 files[i] = tmp[i]; 414 } 415 416 return files; 417 } 418 catch(Exception ex) 419 { 420 ex.printStackTrace(); 421 Log.debug(" Error while listing directory: " + ex); 422 return new String [0]; 423 } 424 } 425 426 public String [] sortSize() 427 { 428 return size; 429 } 430 431 public int[] getPermissions() 432 { 433 return perms; 434 } 435 436 public int handleUpload(String f) 437 { 438 if(Settings.getEnableSftpMultiThreading()) 439 { 440 441 Sftp2Transfer t = new Sftp2Transfer(getLocalPath(), getPWD(), 442 f, user, pass, listeners, 443 Transfer.UPLOAD, keyfile, host, ""+port); 444 } 445 else 446 { 447 upload(f); 448 } 449 450 return 0; 451 } 452 453 public int handleDownload(String f) 454 { 455 if(Settings.getEnableSftpMultiThreading()) 456 { 457 Sftp2Transfer t = new Sftp2Transfer(getLocalPath(), getPWD(), 458 f, user, pass, listeners, 459 Transfer.DOWNLOAD, keyfile, host, ""+port); 460 } 461 else 462 { 463 download(f); 464 } 465 466 return 0; 467 } 468 469 public int upload(String f) 470 { 471 String file = toSFTP(f); 472 473 if(file.endsWith("/")) 474 { 475 String out = StringUtils.getDir(file); 476 uploadDir(file, getLocalPath() + out); 477 fireActionFinished(this); 478 } 479 else 480 { 481 String outfile = StringUtils.getFile(file); 482 483 work(getLocalPath() + outfile, file, true); 485 fireActionFinished(this); 486 } 487 488 return 0; 489 } 490 491 public int download(String f) 492 { 493 String file = toSFTP(f); 494 495 if(file.endsWith("/")) 496 { 497 String out = StringUtils.getDir(file); 498 downloadDir(file, getLocalPath() + out); 499 fireActionFinished(this); 500 } 501 else 502 { 503 String outfile = StringUtils.getFile(file); 504 505 work(file, getLocalPath() + outfile, false); 507 fireActionFinished(this); 508 } 509 510 return 0; 511 } 512 513 private void downloadDir(String dir, String out) 514 { 515 try 516 { 517 fileCount = 0; 519 shortProgress = true; 520 baseFile = StringUtils.getDir(dir); 521 522 Vector v = channel.ls(dir); 523 524 String [] tmp = new String [v.size()]; 525 SftpFile[] f = new SftpFile[v.size()]; 526 Enumeration e = v.elements(); 527 int x = 0; 528 529 while(e.hasMoreElements()) 530 { 531 LsEntry entry = ((LsEntry)e.nextElement()); 532 tmp[x] = entry.getFilename(); 533 534 if(entry.getAttrs().isDir() && !tmp[x].endsWith("/")) 535 { 536 tmp[x] = tmp[x] + "/"; 537 } 538 539 x++; 540 } 541 542 File fx = new File (out); 543 fx.mkdir(); 544 545 for(int i = 0; i < tmp.length; i++) 546 { 547 if(tmp[i].equals("./") || tmp[i].equals("../")) 548 { 549 continue; 550 } 551 552 tmp[i] = tmp[i].replace('\\', '/'); 553 554 556 if(tmp[i].endsWith("/")) 557 { 558 if(!tmp[i].endsWith("/")) 559 { 560 tmp[i] = tmp[i] + "/"; 561 } 562 563 downloadDir(dir + tmp[i], out + tmp[i]); 564 } 565 else 566 { 567 fileCount++; 568 fireProgressUpdate(baseFile, 569 DataConnection.GETDIR + ":" + fileCount, 570 -1); 571 work(dir + tmp[i], out + tmp[i], false); 572 } 573 574 } 575 576 578 fireProgressUpdate(baseFile, 579 DataConnection.DFINISHED + ":" + fileCount, -1); 580 } 581 catch(Exception ex) 582 { 583 ex.printStackTrace(); 584 System.out.println(dir + ", " + out); 585 Log.debug("Transfer error: " + ex); 586 fireProgressUpdate(baseFile, 587 DataConnection.FAILED + ":" + fileCount, -1); 588 } 589 590 shortProgress = false; 591 } 592 593 private void uploadDir(String dir, String out) 594 { 595 try 596 { 597 isDirUpload = true; 599 fileCount = 0; 600 shortProgress = true; 601 baseFile = StringUtils.getDir(dir); 602 603 File f2 = new File (out); 604 String [] tmp = f2.list(); 605 606 if(tmp == null) 607 { 608 return; 609 } 610 611 channel.mkdir(dir); 612 614 for(int i = 0; i < tmp.length; i++) 615 { 616 if(tmp[i].equals("./") || tmp[i].equals("../")) 617 { 618 continue; 619 } 620 621 tmp[i] = tmp[i].replace('\\', '/'); 622 623 File f3 = new File (out + tmp[i]); 625 626 if(f3.isDirectory()) 627 { 628 if(!tmp[i].endsWith("/")) 629 { 630 tmp[i] = tmp[i] + "/"; 631 } 632 633 uploadDir(dir + tmp[i], out + tmp[i]); 634 } 635 else 636 { 637 fileCount++; 638 fireProgressUpdate(baseFile, 639 DataConnection.PUTDIR + ":" + fileCount, 640 -1); 641 work(out + tmp[i], dir + tmp[i], true); 642 } 643 } 644 645 fireProgressUpdate(baseFile, 646 DataConnection.DFINISHED + ":" + fileCount, -1); 647 } 648 catch(Exception ex) 649 { 650 ex.printStackTrace(); 651 System.out.println(dir + ", " + out); 652 Log.debug("Transfer error: " + ex); 653 fireProgressUpdate(baseFile, 654 DataConnection.FAILED + ":" + fileCount, -1); 655 } 656 657 isDirUpload = false; 658 shortProgress = true; 659 } 660 661 private String toSFTP(String f) 662 { 663 String file; 664 665 if(f.startsWith("/")) 666 { 667 file = f; 668 } 669 else 670 { 671 file = getPWD() + f; 672 } 673 674 file = file.replace('\\', '/'); 675 676 return file; 678 } 679 680 private String toSFTPDir(String f) 681 { 682 String file; 683 684 if(f.startsWith("/")) 685 { 686 file = f; 687 } 688 else 689 { 690 file = pwd + f; 691 } 692 693 file = file.replace('\\', '/'); 694 695 if(!file.endsWith("/")) 696 { 697 file = file + "/"; 698 } 699 700 return file; 702 } 703 704 private void work(String file, String outfile, boolean up) 705 { 706 BufferedInputStream in = null; 707 BufferedOutputStream out = null; 708 709 711 try 712 { 713 boolean outflag = false; 714 715 if(up) 716 { 717 in = new BufferedInputStream (new FileInputStream (file)); 718 } 719 else 720 { 721 in = new BufferedInputStream (channel.get(file)); 722 } 723 724 if(up) 725 { 726 outflag = true; 727 728 try { 729 channel.rm(outfile); 730 } 731 catch(Exception ex) { 732 733 } 734 out = new BufferedOutputStream (channel.put(outfile)); 735 } 736 else 737 { 738 out = new BufferedOutputStream (new FileOutputStream (outfile)); 739 } 740 741 byte[] buf = new byte[smbBuffer]; 743 int len = 0; 744 int reallen = 0; 745 746 while(true) 748 { 749 len = in.read(buf); 750 751 if(len == StreamTokenizer.TT_EOF) 753 { 754 break; 755 } 756 757 out.write(buf, 0, len); 758 reallen += len; 759 760 if(outflag) 762 { 763 fireProgressUpdate(StringUtils.getFile(outfile), 764 DataConnection.PUT, reallen); 765 } 766 else 767 { 768 fireProgressUpdate(StringUtils.getFile(file), 769 DataConnection.GET, reallen); 770 } 771 } 772 773 777 fireProgressUpdate(file, DataConnection.FINISHED, -1); 778 } 779 catch(IOException ex) 780 { 781 ex.printStackTrace(); 782 Log.debug("Error with file IO (" + ex + ")!"); 783 fireProgressUpdate(file, DataConnection.FAILED, -1); 784 } 785 catch(SftpException ex) 786 { 787 ex.printStackTrace(); 788 Log.debug("Error with SFTP IO (" + ex + ")!"); 789 fireProgressUpdate(file, DataConnection.FAILED, -1); 790 } 791 finally 792 { 793 try 794 { 795 out.flush(); 796 out.close(); 797 in.close(); 798 } 799 catch(Exception ex) 800 { 801 ex.printStackTrace(); 802 } 803 } 804 } 805 806 public boolean rename(String oldName, String newName) 807 { 808 try 809 { 810 oldName = toSFTP(oldName); 811 newName = toSFTP(newName); 812 813 channel.rename(oldName, newName); 814 815 return true; 816 } 817 catch(Exception ex) 818 { 819 ex.printStackTrace(); 820 821 Log.debug("Could rename file (" + ex + ")."); 822 823 return false; 824 } 825 } 826 827 private void update(String file, String type, int bytes) 828 { 829 if(listeners == null) 830 { 831 return; 832 } 833 else 834 { 835 for(int i = 0; i < listeners.size(); i++) 836 { 837 ConnectionListener listener = (ConnectionListener) listeners.elementAt(i); 838 listener.updateProgress(file, type, bytes); 839 } 840 } 841 } 842 843 public void addConnectionListener(ConnectionListener l) 844 { 845 listeners.add(l); 846 } 847 848 public void setConnectionListeners(Vector l) 849 { 850 listeners = l; 851 } 852 853 854 public void fireDirectoryUpdate() 855 { 856 if(listeners == null) 857 { 858 return; 859 } 860 else 861 { 862 for(int i = 0; i < listeners.size(); i++) 863 { 864 ((ConnectionListener) listeners.elementAt(i)).updateRemoteDirectory(this); 865 } 866 } 867 } 868 869 public boolean login(String user, String pass) 870 { 871 this.user = user; 872 this.pass = pass; 873 874 if(!login()) 875 { 876 Log.debug("Login failed."); 877 878 return false; 879 } 880 else 881 { 882 Log.debug("Authed successfully."); 883 884 } 886 887 return true; 888 } 889 890 891 public void fireProgressUpdate(String file, String type, int bytes) 892 { 893 if(listeners == null) 894 { 895 return; 896 } 897 898 for(int i = 0; i < listeners.size(); i++) 899 { 900 ConnectionListener listener = (ConnectionListener) listeners.elementAt(i); 901 902 if(shortProgress && Settings.shortProgress) 903 { 904 if(type.startsWith(DataConnection.DFINISHED)) 905 { 906 listener.updateProgress(baseFile, 907 DataConnection.DFINISHED + ":" + 908 fileCount, bytes); 909 } 910 else if(isDirUpload) 911 { 912 listener.updateProgress(baseFile, 913 DataConnection.PUTDIR + ":" + 914 fileCount, bytes); 915 } 916 else 917 { 918 listener.updateProgress(baseFile, 919 DataConnection.GETDIR + ":" + 920 fileCount, bytes); 921 } 922 } 923 else 924 { 925 listener.updateProgress(file, type, bytes); 926 } 927 } 928 } 929 930 public void fireActionFinished(Sftp2Connection con) 931 { 932 if(listeners == null) 933 { 934 return; 935 } 936 else 937 { 938 for(int i = 0; i < listeners.size(); i++) 939 { 940 ((ConnectionListener) listeners.elementAt(i)).actionFinished(con); 941 } 942 } 943 } 944 945 public int upload(String file, InputStream i) 946 { 947 BufferedOutputStream out = null; 948 BufferedInputStream in = null; 949 950 try 951 { 952 file = toSFTP(file); 953 954 out = new BufferedOutputStream (channel.put(file)); 955 in = new BufferedInputStream (i); 956 957 byte[] buf = new byte[smbBuffer]; 959 int len = 0; 960 int reallen = 0; 961 962 while(true) 963 { 964 len = in.read(buf); 965 966 if(len == StreamTokenizer.TT_EOF) 968 { 969 break; 970 } 971 972 out.write(buf, 0, len); 973 reallen += len; 974 975 fireProgressUpdate(StringUtils.getFile(file), 976 DataConnection.PUT, reallen); 977 } 978 979 981 fireProgressUpdate(file, DataConnection.FINISHED, -1); 982 983 return 0; 984 } 985 catch(IOException ex) 986 { 987 ex.printStackTrace(); 988 Log.debug("Error with file IO (" + ex + ")!"); 989 fireProgressUpdate(file, DataConnection.FAILED, -1); 990 991 return -1; 992 } 993 catch(SftpException ex) 994 { 995 ex.printStackTrace(); 996 Log.debug("Error with file SFTP IO (" + ex + ")!"); 997 fireProgressUpdate(file, DataConnection.FAILED, -1); 998 999 return -1; 1000 } 1001 finally 1002 { 1003 try 1004 { 1005 out.flush(); 1006 out.close(); 1007 in.close(); 1008 } 1009 catch(Exception ex) 1010 { 1011 ex.printStackTrace(); 1012 } 1013 } 1014 } 1015 1016 public InputStream getDownloadInputStream(String file) 1017 { 1018 try 1019 { 1020 1021 return channel.get(file); 1022 } 1023 catch(SftpException ex) 1024 { 1025 ex.printStackTrace(); 1026 Log.debug(ex.toString() + 1027 " @Sftp2Connection::getDownloadInputStream"); 1028 1029 return null; 1030 } 1031 } 1032 1033 public Date [] sortDates() 1034 { 1035 return null; 1036 } 1037} 1038 1039class MyUserInfo implements UserInfo { 1040 1041 String password; 1042 1043 public MyUserInfo(String pass) { 1044 this.password = pass; 1045 } 1046 1047 public String getPassword(){ return password; } 1048 1049 public boolean promptYesNo(String str){ 1050 1060 1061 return true; 1062 } 1063 1064 public String getPassphrase(){ return password; } 1065 1066 public boolean promptPassphrase(String message){ return true; } 1067 1068 public boolean promptPassword(String message){ 1069 return true; 1070 } 1071 1072 public void showMessage(String message){ 1073 JOptionPane.showMessageDialog(null, message); 1074 } 1075} 1076 | Popular Tags |