1 /* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License 4 * as published by the Free Software Foundation; either version 2 5 * of the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15 */ 16 package net.sf.jftp.net.wrappers; 17 18 import java.io.BufferedInputStream; 19 import java.io.BufferedOutputStream; 20 import java.io.File; 21 import java.io.FileOutputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.StreamTokenizer; 25 import java.util.Date; 26 import java.util.Vector; 27 28 import net.sf.jftp.config.Settings; 29 import net.sf.jftp.net.BasicConnection; 30 import net.sf.jftp.net.ConnectionListener; 31 import net.sf.jftp.net.DataConnection; 32 import net.sf.jftp.net.FtpConnection; 33 import net.sf.jftp.system.StringUtils; 34 import net.sf.jftp.system.logging.Log; 35 36 import org.apache.commons.httpclient.HttpException; 37 import org.apache.commons.httpclient.HttpURL; 38 import org.apache.webdav.lib.WebdavFile; 39 import org.apache.webdav.lib.WebdavResource; 40 41 42 public class WebdavConnection implements BasicConnection 43 { 44 public static int webdavBuffer = 32000; 45 private String path = ""; 46 private String pwd = ""; 47 private Vector listeners = new Vector(); 48 private String[] files; 49 private String[] size = new String[0]; 50 private int[] perms = null; 51 private String baseFile; 52 private int fileCount; 53 private boolean shortProgress = false; 54 private String user; 55 private String pass; 56 WebdavConnection(String path, String user, String pass, ConnectionListener l)57 public WebdavConnection(String path, String user, String pass, 58 ConnectionListener l) 59 { 60 this.user = user; 61 this.pass = pass; 62 63 listeners.add(l); 64 chdir(path); 65 } 66 removeFileOrDir(String file)67 public int removeFileOrDir(String file) 68 { 69 Log.debug("Feature is not implemented yet"); 70 71 if(true) 72 { 73 return -1; 74 } 75 76 try 77 { 78 if((file == null) || file.equals("")) 79 { 80 return -1; 81 } 82 83 String tmp = file; 84 85 if(StringUtils.isRelative(file)) 86 { 87 tmp = getPWD() + file; 88 } 89 90 WebdavFile f = new WebdavFile(getURL(tmp)); 91 92 if(!f.getAbsolutePath().equals(f.getCanonicalPath())) 93 { 94 //Log.debug("WARNING: Symlink removed");//Skipping symlink, remove failed."); 95 //Log.debug("This is necessary to prevent possible data loss when removing those symlinks."); 96 //return -1; 97 if(!f.delete()) 98 { 99 return -1; 100 } 101 } 102 103 if(f.exists() && f.isDirectory()) 104 { 105 cleanLocalDir(tmp); 106 } 107 108 //System.out.println(tmp); 109 if(!f.delete()) 110 { 111 Log.debug("Removal failed."); 112 113 return -1; 114 } 115 } 116 catch(Exception ex) 117 { 118 Log.debug("Error: " + ex.toString()); 119 ex.printStackTrace(); 120 } 121 122 return -1; 123 } 124 cleanLocalDir(String dir)125 private void cleanLocalDir(String dir) 126 { 127 try 128 { 129 dir = dir.replace('\\', '/'); 130 131 if(!dir.endsWith("/")) 132 { 133 dir = dir + "/"; 134 } 135 136 //String remoteDir = StringUtils.removeStart(dir,path); 137 //System.out.println(">>> " + dir); 138 WebdavFile f2 = new WebdavFile(getURL(dir)); 139 String[] tmp = f2.list(); 140 141 if(tmp == null) 142 { 143 return; 144 } 145 146 for(int i = 0; i < tmp.length; i++) 147 { 148 WebdavFile f3 = new WebdavFile(getURL(dir + tmp[i])); 149 150 if(!f3.getAbsolutePath().equals(f3.getCanonicalPath())) 151 { 152 //Log.debug("WARNING: Symlink remove");//Skipping symlink, remove may fail."); 153 f3.delete(); 154 155 //Log.debug("This is necessary to prevent possible data loss when removing those symlinks."); 156 //continue; 157 } 158 159 if(f3.isDirectory()) 160 { 161 //System.out.println(dir); 162 cleanLocalDir(dir + tmp[i]); 163 f3.delete(); 164 } 165 else 166 { 167 //System.out.println(dir+tmp[i]); 168 f3.delete(); 169 } 170 } 171 } 172 catch(Exception ex) 173 { 174 Log.debug("Error: " + ex.toString()); 175 ex.printStackTrace(); 176 } 177 } 178 sendRawCommand(String cmd)179 public void sendRawCommand(String cmd) 180 { 181 } 182 disconnect()183 public void disconnect() 184 { 185 } 186 isConnected()187 public boolean isConnected() 188 { 189 return true; 190 } 191 getPWD()192 public String getPWD() 193 { 194 return pwd; 195 } 196 cdup()197 public boolean cdup() 198 { 199 return chdir(pwd.substring(0, pwd.lastIndexOf("/") + 1)); 200 } 201 mkdir(String dirName)202 public boolean mkdir(String dirName) 203 { 204 Log.debug("Feature is not implemented yet"); 205 206 if(true) 207 { 208 return false; 209 } 210 211 try 212 { 213 if(StringUtils.isRelative(dirName)) 214 { 215 dirName = getPWD() + dirName; 216 } 217 218 WebdavFile f = new WebdavFile(getURL(dirName)); 219 220 boolean x = f.mkdir(); 221 fireDirectoryUpdate(); 222 223 return x; 224 } 225 catch(Exception ex) 226 { 227 Log.debug("Error: " + ex.toString()); 228 ex.printStackTrace(); 229 230 return false; 231 } 232 } 233 list()234 public void list() throws IOException 235 { 236 } 237 chdir(String p)238 public boolean chdir(String p) 239 { 240 try 241 { 242 String p2 = processPath(p); 243 244 if(p2 == null) 245 { 246 return false; 247 } 248 249 //WebdavFile f = new WebdavFile(getURL(p2)); 250 WebdavResource f = getResource(p2); 251 252 if(!f.exists() || !f.isCollection()) //!f.isDirectory() || !f.canRead()) 253 { 254 Log.debug("Access denied."); 255 256 return false; 257 } 258 259 pwd = p2; 260 261 Log.out("PWD: " + pwd); 262 263 fireDirectoryUpdate(); 264 265 return true; 266 } 267 catch(Exception ex) 268 { 269 Log.debug("Error: " + ex.toString()); 270 ex.printStackTrace(); 271 272 return false; 273 } 274 } 275 chdirNoRefresh(String p)276 public boolean chdirNoRefresh(String p) 277 { 278 String p2 = processPath(p); 279 280 if(p2 == null) 281 { 282 return false; 283 } 284 285 //System.out.println(p2); 286 pwd = p2; 287 288 return true; 289 } 290 getLocalPath()291 public String getLocalPath() 292 { 293 //System.out.println("local: " + path); 294 return path; 295 } 296 processPath(String p)297 public String processPath(String p) 298 { 299 try 300 { 301 if(!p.startsWith("http://")) 302 { 303 p = pwd + p; 304 } 305 306 if(!p.endsWith("/")) 307 { 308 p = p + "/"; 309 } 310 311 while(p.endsWith("/../")) 312 { 313 p = p.substring(0, p.lastIndexOf("/../") - 1); 314 p = p.substring(0, p.lastIndexOf("/")); 315 } 316 317 while(p.endsWith("/./")) 318 { 319 p = p.substring(0, p.lastIndexOf("/./") - 1); 320 p = p.substring(0, p.lastIndexOf("/")); 321 } 322 323 //System.out.println(", processPath 2: "+p); 324 //WebdavFile f = new WebdavFile(getURL(p)); 325 Log.out("\n\n\nprocessPath URL: " + p); 326 327 WebdavResource f = getResource(p); 328 String p2 = p; 329 330 if(f.exists() && f.isCollection()) 331 { 332 try 333 { 334 //p2 = f.toURL(); //CanonicalPath(); 335 if(!p2.endsWith("/")) 336 { 337 p2 = p2 + "/"; 338 } 339 340 //Log.out("processPath parsed URL: " + p); 341 //Log.out("processPath URL2: " + f.getPath()); 342 return p2; 343 } 344 catch(Exception ex) 345 { 346 Log.debug("Error: can not get pathname (processPath)!"); 347 348 return null; 349 } 350 } 351 else 352 { 353 Log.debug("(processpPath) No such path: \"" + p + "\""); 354 355 return null; 356 } 357 } 358 catch(Exception ex) 359 { 360 Log.debug("Error: " + ex.toString()); 361 ex.printStackTrace(); 362 363 return null; 364 } 365 } 366 setLocalPath(String p)367 public boolean setLocalPath(String p) 368 { 369 try 370 { 371 p = p.replace('\\', '/'); 372 373 //System.out.print("local 1:" + p); 374 if(StringUtils.isRelative(p)) 375 { 376 p = path + p; 377 } 378 379 p = p.replace('\\', '/'); 380 381 //System.out.println(", local 2:" + p); 382 File f = new File(p); 383 384 if(f.exists()) 385 { 386 try 387 { 388 path = f.getCanonicalPath(); 389 path = path.replace('\\', '/'); 390 391 if(!path.endsWith("/")) 392 { 393 path = path + "/"; 394 } 395 396 //System.out.println("localPath: "+path); 397 } 398 catch(Exception ex) 399 { 400 Log.debug("Error: can not get pathname (local)!"); 401 402 return false; 403 } 404 } 405 else 406 { 407 Log.debug("(local) No such path: \"" + p + "\""); 408 409 return false; 410 } 411 412 return true; 413 } 414 catch(Exception ex) 415 { 416 Log.debug("Error: " + ex.toString()); 417 ex.printStackTrace(); 418 419 return false; 420 } 421 } 422 sortLs()423 public String[] sortLs() 424 { 425 try 426 { 427 Log.out("sortLs PWD: " + pwd); 428 429 //WebdavFile fl = new WebdavFile(new URL(pwd), user, pass); 430 WebdavResource fp = getResource(pwd); 431 432 //new WebdavResource(getURL(pwd)); 433 //files = f.list(); 434 //File[] f = fl.listFiles(); 435 WebdavResource[] f = fp.listWebdavResources(); 436 437 //if(files == null) return new String[0]; 438 files = new String[f.length]; 439 size = new String[f.length]; 440 perms = new int[f.length]; 441 442 int accessible = 0; 443 444 for(int i = 0; i < f.length; i++) 445 { 446 files[i] = f[i].getName(); 447 448 /* 449 while(files[i].indexOf("%20") >= 0) 450 { 451 int x = files[i].indexOf("%20"); 452 String tmp = files[i].substring(0,x)+" "+ 453 files[i].substring(files[i].indexOf("%20")+3); 454 files[i] = tmp; 455 } 456 */ 457 /* 458 try 459 { 460 f[i].exists(); 461 } 462 catch(Exception ex) 463 { 464 Log.debug("ERROR: parsing problem with:" + files[i]); 465 size[i] = "-1"; 466 perms[i] = FtpConnection.DENIED; 467 continue; 468 } 469 */ 470 Log.out("sortLs files[" + i + "]: " + files[i]); 471 472 //size[i] = "" + (int) f[i].length(); 473 size[i] = "" + (int) f[i].getGetContentLength(); 474 perms[i] = FtpConnection.R; 475 476 if(f[i].isCollection() && !files[i].endsWith("/")) 477 { 478 files[i] = files[i] + "/"; 479 } 480 481 /* 482 if(f[i].canWrite()) accessible = FtpConnection.W; 483 else if(f[i].canRead()) accessible = FtpConnection.R; 484 else accessible = FtpConnection.DENIED; 485 perms[i] = accessible; 486 487 Log.out("sortLs files["+i+"]: " + files[i]); 488 WebdavFile f2 = new WebdavFile(new URL(files[i]), user, pass); 489 490 if(!f2.exists()) continue; 491 if(f2.isDirectory() && !files[i].endsWith("/")) files[i] = files[i] + "/"; 492 493 size[i] = "" + new WebdavFile(new URL(files[i]), user, pass).length(); 494 */ 495 } 496 497 return files; 498 } 499 catch(Exception ex) 500 { 501 Log.debug("Error: " + ex.toString()); 502 ex.printStackTrace(); 503 504 return new String[0]; 505 } 506 } 507 sortSize()508 public String[] sortSize() 509 { 510 return size; 511 } 512 getPermissions()513 public int[] getPermissions() 514 { 515 return perms; 516 } 517 handleDownload(String file)518 public int handleDownload(String file) 519 { 520 transfer(file); 521 522 return 0; 523 } 524 handleUpload(String file)525 public int handleUpload(String file) 526 { 527 transfer(file, true); 528 529 return 0; 530 } 531 download(String file)532 public int download(String file) 533 { 534 transfer(file); 535 536 return 0; 537 } 538 upload(String file)539 public int upload(String file) 540 { 541 transfer(file, true); 542 543 return 0; 544 } 545 transferDir(String dir, String out)546 private void transferDir(String dir, String out) 547 { 548 try 549 { 550 fileCount = 0; 551 shortProgress = true; 552 baseFile = StringUtils.getDir(dir); 553 554 WebdavFile f2 = new WebdavFile(getURL(dir)); 555 String[] tmp = f2.list(); 556 557 if(tmp == null) 558 { 559 return; 560 } 561 562 WebdavFile fx = new WebdavFile(getURL(out)); 563 564 if(!fx.mkdir()) 565 { 566 Log.debug("Can not create directory: " + out + 567 " - already exist or permission denied?"); 568 } 569 570 for(int i = 0; i < tmp.length; i++) 571 { 572 tmp[i] = tmp[i].replace('\\', '/'); 573 574 //System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]); 575 WebdavFile f3 = new WebdavFile(getURL(dir + tmp[i])); 576 577 if(f3.isDirectory()) 578 { 579 if(!tmp[i].endsWith("/")) 580 { 581 tmp[i] = tmp[i] + "/"; 582 } 583 584 transferDir(dir + tmp[i], out + tmp[i]); 585 } 586 else 587 { 588 fireProgressUpdate(baseFile, 589 DataConnection.GETDIR + ":" + fileCount, 590 -1); 591 work(dir + tmp[i], out + tmp[i]); 592 } 593 } 594 595 fireProgressUpdate(baseFile, 596 DataConnection.DFINISHED + ":" + fileCount, -1); 597 shortProgress = false; 598 } 599 catch(Exception ex) 600 { 601 Log.debug("Error: " + ex.toString()); 602 ex.printStackTrace(); 603 } 604 } 605 getURL(String u)606 private HttpURL getURL(String u) 607 { 608 try 609 { 610 HttpURL url = new HttpURL(u); 611 612 //System.out.println(user + ":"+ pass); 613 url.setUserinfo(user, pass); 614 615 return url; 616 } 617 catch(Exception ex) 618 { 619 ex.printStackTrace(); 620 Log.debug("ERROR: " + ex); 621 622 return null; 623 } 624 } 625 getResource(String res)626 private WebdavResource getResource(String res) 627 throws HttpException, IOException 628 { 629 return new WebdavResource(getURL(res)); 630 } 631 transfer(String file)632 private void transfer(String file) 633 { 634 transfer(file, false); 635 } 636 transfer(String file, boolean up)637 private void transfer(String file, boolean up) 638 { 639 String out = StringUtils.getDir(file); 640 641 if(StringUtils.isRelative(file)) 642 { 643 file = getPWD() + file; 644 } 645 646 file = file.replace('\\', '/'); 647 out = out.replace('\\', '/'); 648 649 String outfile = StringUtils.getFile(file); 650 651 if(file.endsWith("/")) 652 { 653 if(up) 654 { 655 Log.debug("Directory upload not implemented yet."); 656 657 return; 658 } 659 660 transferDir(file, getLocalPath() + out); 661 662 return; 663 } 664 else 665 { 666 if(up) 667 { 668 work(getLocalPath() + outfile, file); 669 } 670 else 671 { 672 work(file, getLocalPath() + outfile); 673 } 674 } 675 } 676 work(String file, String outfile)677 private void work(String file, String outfile) 678 { 679 Log.out("transfer started\nfile: " + file + "\noutfile: " + outfile); 680 681 BufferedInputStream in = null; 682 BufferedOutputStream out = null; 683 684 try 685 { 686 if(outfile.startsWith("http://")) 687 { 688 //out = new BufferedOutputStream(new FileOutputStream(new WebdavResource(new HttpURL(file)).getMethodData()); 689 //new WebdavFile(new URL(outfile), user, pass))); 690 //in = new BufferedInputStream(new FileInputStream(file)); 691 String resPath = outfile.substring(0, 692 outfile.lastIndexOf("/") + 693 1); 694 String name = outfile.substring(outfile.lastIndexOf("/") + 1); 695 696 Log.debug("Uploading " + file + " to " + resPath + " as " + 697 name); 698 699 //HttpURL url = getURL(resPath); 700 WebdavResource res = getResource(resPath); 701 702 //new WebdavResource(url); 703 704 /* 705 if(res.checkinMethod()) Log.debug("Checkin OK"); 706 else Log.debug("Checkin FAILED"); 707 708 Enumeration e = res.getAllowedMethods(); 709 while(e != null && e.hasMoreElements()) 710 { 711 Log.debug("Method: " + e.nextElement().toString()); 712 } 713 */ 714 if(res.putMethod(new File(file))) 715 { 716 fireProgressUpdate(file, DataConnection.FINISHED, -1); 717 } 718 else 719 { 720 Log.debug("Upload failed."); 721 fireProgressUpdate(file, DataConnection.FAILED, -1); 722 } 723 724 return; 725 } 726 727 Log.debug("Downloading " + file + " to " + outfile); 728 729 out = new BufferedOutputStream(new FileOutputStream(outfile)); 730 in = new BufferedInputStream(getResource(file).getMethodData()); 731 732 //new WebdavResource(getURL(file)).getMethodData()); 733 byte[] buf = new byte[webdavBuffer]; 734 int len = 0; 735 int reallen = 0; 736 737 //System.out.println(file+":"+getLocalPath()+outfile); 738 while(true) 739 { 740 len = in.read(buf); 741 742 //System.out.print("."); 743 if(len == StreamTokenizer.TT_EOF) 744 { 745 break; 746 } 747 748 out.write(buf, 0, len); 749 750 reallen += len; 751 fireProgressUpdate(StringUtils.getFile(file), 752 DataConnection.GET, reallen); 753 } 754 755 fireProgressUpdate(file, DataConnection.FINISHED, -1); 756 } 757 catch(IOException ex) 758 { 759 Log.debug("Error with file IO (" + ex + ")!"); 760 ex.printStackTrace(); 761 fireProgressUpdate(file, DataConnection.FAILED, -1); 762 } 763 finally 764 { 765 try 766 { 767 out.flush(); 768 out.close(); 769 in.close(); 770 } 771 catch(Exception ex) 772 { 773 ex.printStackTrace(); 774 } 775 } 776 } 777 upload(String file, InputStream in)778 public int upload(String file, InputStream in) 779 { 780 /* 781 if(StringUtils.isRelative(file)) file = getPWD() + file; 782 file = file.replace('\\','/'); 783 784 try 785 { 786 work(new BufferedInputStream(in), file, file); 787 return 0; 788 } 789 catch(Exception ex) 790 { 791 Log.debug("Error: " + ex.toString()); 792 ex.printStackTrace(); 793 return -1; 794 } 795 */ 796 Log.debug("Upload using InputStream is not implemented yet!"); 797 798 return -1; 799 } 800 801 /* 802 private void work(BufferedInputStream in, String outfile, String file) 803 { 804 Log.out("transfer started, input from stream\noutfile: " + outfile); 805 806 try 807 { 808 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outfile)); 809 byte buf[] = new byte[webdavBuffer]; 810 int len = 0; 811 int reallen = 0; 812 813 while(true) 814 { 815 len = in.read(buf); 816 System.out.print("."); 817 if(len == StreamTokenizer.TT_EOF) break; 818 out.write(buf,0,len); 819 820 reallen += len; 821 fireProgressUpdate(StringUtils.getFile(file),DataConnection.GET, reallen); 822 } 823 824 out.flush(); 825 out.close(); 826 in.close(); 827 fireProgressUpdate(file,DataConnection.FINISHED, -1); 828 } 829 catch(IOException ex) 830 { 831 Log.debug("Error with file IO ("+ex+")!"); 832 ex.printStackTrace(); 833 fireProgressUpdate(file,DataConnection.FAILED, -1); 834 } 835 } 836 */ getDownloadInputStream(String file)837 public InputStream getDownloadInputStream(String file) 838 { 839 if(StringUtils.isRelative(file)) 840 { 841 file = getPWD() + file; 842 } 843 844 file = file.replace('\\', '/'); 845 846 try 847 { 848 return getResource(file).getMethodData(); 849 } 850 catch(Exception ex) 851 { 852 ex.printStackTrace(); 853 Log.debug(ex.toString() + 854 " @WebdavConnection::getDownloadInputStream"); 855 856 return null; 857 } 858 } 859 addConnectionListener(ConnectionListener l)860 public void addConnectionListener(ConnectionListener l) 861 { 862 listeners.add(l); 863 } 864 setConnectionListeners(Vector l)865 public void setConnectionListeners(Vector l) 866 { 867 listeners = l; 868 } 869 870 /** remote directory has changed */ fireDirectoryUpdate()871 public void fireDirectoryUpdate() 872 { 873 if(listeners == null) 874 { 875 return; 876 } 877 else 878 { 879 for(int i = 0; i < listeners.size(); i++) 880 { 881 ((ConnectionListener) listeners.elementAt(i)).updateRemoteDirectory(this); 882 } 883 } 884 } 885 login(String user, String pass)886 public boolean login(String user, String pass) 887 { 888 return true; 889 } 890 fireProgressUpdate(String file, String type, int bytes)891 public void fireProgressUpdate(String file, String type, int bytes) 892 { 893 if(listeners == null) 894 { 895 return; 896 } 897 else 898 { 899 for(int i = 0; i < listeners.size(); i++) 900 { 901 ConnectionListener listener = (ConnectionListener) listeners.elementAt(i); 902 903 if(shortProgress && Settings.shortProgress) 904 { 905 if(type.startsWith(DataConnection.DFINISHED)) 906 { 907 listener.updateProgress(baseFile, 908 DataConnection.DFINISHED + ":" + 909 fileCount, bytes); 910 } 911 912 listener.updateProgress(baseFile, 913 DataConnection.GETDIR + ":" + 914 fileCount, bytes); 915 } 916 else 917 { 918 listener.updateProgress(file, type, bytes); 919 } 920 } 921 } 922 } 923 sortDates()924 public Date[] sortDates() 925 { 926 return null; 927 } 928 rename(String from, String to)929 public boolean rename(String from, String to) 930 { 931 Log.debug("Not implemented!"); 932 933 return false; 934 } 935 } 936