00001
00002 using System.Runtime.CompilerServices;
00003 using Tamir.Streams;
00004 using Tamir.SharpSsh.java.io;
00005 using Tamir.SharpSsh.java.lang;
00006 using Tamir.SharpSsh.java.util;
00007 using Tamir.SharpSsh.java;
00008
00009 namespace Tamir.SharpSsh.jsch
00010 {
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00043 public class ChannelSftp : ChannelSession
00044 {
00045 private static byte SSH_FXP_INIT= 1;
00046 private static byte SSH_FXP_VERSION= 2;
00047 private static byte SSH_FXP_OPEN= 3;
00048 private static byte SSH_FXP_CLOSE= 4;
00049 private static byte SSH_FXP_READ= 5;
00050 private static byte SSH_FXP_WRITE= 6;
00051 private static byte SSH_FXP_LSTAT= 7;
00052 private static byte SSH_FXP_FSTAT= 8;
00053 private static byte SSH_FXP_SETSTAT= 9;
00054 private static byte SSH_FXP_FSETSTAT= 10;
00055 private static byte SSH_FXP_OPENDIR= 11;
00056 private static byte SSH_FXP_READDIR= 12;
00057 private static byte SSH_FXP_REMOVE= 13;
00058 private static byte SSH_FXP_MKDIR= 14;
00059 private static byte SSH_FXP_RMDIR= 15;
00060 private static byte SSH_FXP_REALPATH= 16;
00061 private static byte SSH_FXP_STAT= 17;
00062 private static byte SSH_FXP_RENAME= 18;
00063 private static byte SSH_FXP_READLINK= 19;
00064 private static byte SSH_FXP_SYMLINK= 20;
00065 private static byte SSH_FXP_STATUS= 101;
00066 private static byte SSH_FXP_HANDLE= 102;
00067 private static byte SSH_FXP_DATA= 103;
00068 private static byte SSH_FXP_NAME= 104;
00069 private static byte SSH_FXP_ATTRS= 105;
00070 private static byte SSH_FXP_EXTENDED= (byte)200;
00071 private static byte SSH_FXP_EXTENDED_REPLY= (byte)201;
00072
00073
00074 private static int SSH_FXF_READ= 0x00000001;
00075 private static int SSH_FXF_WRITE= 0x00000002;
00076 private static int SSH_FXF_APPEND= 0x00000004;
00077 private static int SSH_FXF_CREAT= 0x00000008;
00078 private static int SSH_FXF_TRUNC= 0x00000010;
00079 private static int SSH_FXF_EXCL= 0x00000020;
00080
00081 private static int SSH_FILEXFER_ATTR_SIZE= 0x00000001;
00082 private static int SSH_FILEXFER_ATTR_UIDGID= 0x00000002;
00083 private static int SSH_FILEXFER_ATTR_PERMISSIONS= 0x00000004;
00084 private static int SSH_FILEXFER_ATTR_ACMODTIME= 0x00000008;
00085 private static uint SSH_FILEXFER_ATTR_EXTENDED= 0x80000000;
00086
00087 public static int SSH_FX_OK= 0;
00088 public static int SSH_FX_EOF= 1;
00089 public static int SSH_FX_NO_SUCH_FILE= 2;
00090 public static int SSH_FX_PERMISSION_DENIED= 3;
00091 public static int SSH_FX_FAILURE= 4;
00092 public static int SSH_FX_BAD_MESSAGE= 5;
00093 public static int SSH_FX_NO_CONNECTION= 6;
00094 public static int SSH_FX_CONNECTION_LOST= 7;
00095 public static int SSH_FX_OP_UNSUPPORTED= 8;
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 private static int MAX_MSG_LENGTH = 256* 1024;
00133
00134 public static int OVERWRITE=0;
00135 public static int RESUME=1;
00136 public static int APPEND=2;
00137
00138
00139 private bool interactive=false;
00140 internal int seq=1;
00141 private int[] ackid=new int[1];
00142 private Buffer buf;
00143 private Packet packet;
00144
00145 private String _version="3";
00146 private int server_version=3;
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 private static String file_separator=java.io.File.separator;
00164 private static char file_separatorc=java.io.File.separatorChar;
00165
00166 private String cwd;
00167 private String home;
00168 private String lcwd;
00169
00170 internal ChannelSftp(){packet=new Packet(buf);}
00171
00172 public override void init()
00173 {
00174
00175
00176
00177
00178 }
00179
00180 public override void start()
00181 {
00182 try
00183 {
00184
00185 PipedOutputStream pos=new PipedOutputStream();
00186 io.setOutputStream(pos);
00187 PipedInputStream pis=new MyPipedInputStream(pos, 32*1024);
00188 io.setInputStream(pis);
00189
00190 Request request=new RequestSftp();
00191 request.request(session, this);
00192
00193
00194
00195
00196
00197
00198
00199
00200 buf=new Buffer(rmpsize);
00201 packet=new Packet(buf);
00202 int i=0;
00203 int length;
00204 int type;
00205 byte[] str;
00206
00207
00208 sendINIT();
00209
00210
00211 Header _header=new Header();
00212 _header=header(buf, _header);
00213 length=_header.length;
00214 if(length > MAX_MSG_LENGTH)
00215 {
00216 throw new SftpException(SSH_FX_FAILURE, "Received message is too long: " + length);
00217 }
00218 type=_header.type;
00219 server_version=_header.rid;
00220 skip(length);
00221
00222
00223
00224
00225 sendREALPATH(new String(".").getBytes());
00226
00227
00228 _header=header(buf, _header);
00229 length=_header.length;
00230 type=_header.type;
00231 buf.rewind();
00232 fill(buf.buffer, 0, length);
00233 i=buf.getInt();
00234
00235 str=buf.getString();
00236
00237 home=cwd=new String(str);
00238 str=buf.getString();
00239
00240
00241 lcwd=new File(".").getCanonicalPath();
00242 }
00243 catch(Exception e)
00244 {
00245
00246
00247 if(e is JSchException) throw (JSchException)e;
00248 throw new JSchException(e.toString());
00249 }
00250 }
00251
00252 public void quit(){ disconnect();}
00253 public void exit(){ disconnect();}
00254 public void lcd(String path)
00255 {
00256 path=localAbsolutePath(path);
00257 if((new File(path)).isDirectory())
00258 {
00259 try
00260 {
00261 path=(new File(path)).getCanonicalPath();
00262 }
00263 catch(Exception e){}
00264 lcwd=path;
00265 return;
00266 }
00267 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such directory");
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 public void cd(String path)
00278 {
00279
00280 try
00281 {
00282 path=remoteAbsolutePath(path);
00283
00284 Vector v=glob_remote(path);
00285 if(v.size()!=1)
00286 {
00287 throw new SftpException(SSH_FX_FAILURE, v.toString());
00288 }
00289 path=(String)(v.elementAt(0));
00290 sendREALPATH(path.getBytes());
00291
00292 Header _header=new Header();
00293 _header=header(buf, _header);
00294 int length=_header.length;
00295 int type=_header.type;
00296 buf.rewind();
00297 fill(buf.buffer, 0, length);
00298
00299 if(type!=101 && type!=104)
00300 {
00301 throw new SftpException(SSH_FX_FAILURE, "");
00302 }
00303 int i;
00304 if(type==101)
00305 {
00306 i=buf.getInt();
00307 throwStatusError(buf, i);
00308 }
00309 i=buf.getInt();
00310 byte[] str=buf.getString();
00311 if(str!=null && str[0]!='/')
00312 {
00313 str=(cwd+"/"+new String(str)).getBytes();
00314 }
00315 str=buf.getString();
00316 i=buf.getInt();
00317
00318 String newpwd=new String(str);
00319 SftpATTRS attr=_stat(newpwd);
00320 if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0)
00321 {
00322 throw new SftpException(SSH_FX_FAILURE,
00323 "Can't change directory: "+path);
00324 }
00325 if(!attr.isDir())
00326 {
00327 throw new SftpException(SSH_FX_FAILURE,
00328 "Can't change directory: "+path);
00329 }
00330 cwd=newpwd;
00331 }
00332 catch(Exception e)
00333 {
00334 if(e is SftpException) throw (SftpException)e;
00335 throw new SftpException(SSH_FX_FAILURE, "");
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 public void put(String src, String dst)
00349 {
00350 put(src, dst, null, OVERWRITE);
00351 }
00352 public void put(String src, String dst, int mode)
00353 {
00354 put(src, dst, null, mode);
00355 }
00356 public void put(String src, String dst,
00357 SftpProgressMonitor monitor)
00358 {
00359 put(src, dst, monitor, OVERWRITE);
00360 }
00361 public void put(String src, String dst,
00362 SftpProgressMonitor monitor, int mode)
00363 {
00364
00365 src=localAbsolutePath(src);
00366 dst=remoteAbsolutePath(dst);
00367
00368
00369 try
00370 {
00371 Vector v=glob_remote(dst);
00372 int vsize=v.size();
00373 if(vsize!=1)
00374 {
00375 if(vsize==0)
00376 {
00377 if(isPattern(dst))
00378 throw new SftpException(SSH_FX_FAILURE, dst);
00379 else
00380 dst=Util.unquote(dst);
00381 }
00382 throw new SftpException(SSH_FX_FAILURE, v.toString());
00383 }
00384 else
00385 {
00386 dst=(String)(v.elementAt(0));
00387 }
00388
00389
00390
00391 bool _isRemoteDir=isRemoteDir(dst);
00392
00393 v=glob_local(src);
00394
00395 vsize=v.size();
00396
00397 StringBuffer dstsb=null;
00398 if(_isRemoteDir)
00399 {
00400 if(!dst.endsWith("/"))
00401 {
00402 dst+="/";
00403 }
00404 dstsb=new StringBuffer(dst);
00405 }
00406 else if(vsize>1)
00407 {
00408 throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but destination is missing or a file.");
00409 }
00410
00411 for(int j=0; j<vsize; j++)
00412 {
00413 String _src=(String)(v.elementAt(j));
00414 String _dst=null;
00415 if(_isRemoteDir)
00416 {
00417 int i=_src.lastIndexOf(file_separatorc);
00418 if(i==-1) dstsb.append(_src);
00419 else dstsb.append(_src.substring(i + 1));
00420 _dst=dstsb.toString();
00421 dstsb.delete(dst.length(), _dst.length());
00422 }
00423 else
00424 {
00425 _dst=dst;
00426 }
00427
00428
00429 long size_of_dst=0;
00430 if(mode==RESUME)
00431 {
00432 try
00433 {
00434 SftpATTRS attr=_stat(_dst);
00435 size_of_dst=attr.getSize();
00436 }
00437 catch(Exception eee)
00438 {
00439
00440 }
00441 long size_of_src=new File(_src).length();
00442 if(size_of_src<size_of_dst)
00443 {
00444 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+_dst);
00445 }
00446 if(size_of_src==size_of_dst)
00447 {
00448 return;
00449 }
00450 }
00451
00452 if(monitor!=null)
00453 {
00454 monitor.init(SftpProgressMonitor.PUT, _src, _dst,
00455 (new File(_src)).length());
00456 if(mode==RESUME)
00457 {
00458 monitor.count(size_of_dst);
00459 }
00460 }
00461 FileInputStream fis=null;
00462 try
00463 {
00464 fis=new FileInputStream(_src);
00465 _put(fis, _dst, monitor, mode);
00466 }
00467 finally
00468 {
00469 if(fis!=null)
00470 {
00471
00472 fis.close();
00473
00474 }
00475 }
00476 }
00477 }
00478 catch(Exception e)
00479 {
00480 if(e is SftpException) throw (SftpException)e;
00481 throw new SftpException(SSH_FX_FAILURE, e.toString());
00482 }
00483 }
00484 public void put(InputStream src, String dst)
00485 {
00486 put(src, dst, null, OVERWRITE);
00487 }
00488 public void put(InputStream src, String dst, int mode)
00489 {
00490 put(src, dst, null, mode);
00491 }
00492 public void put(InputStream src, String dst,
00493 SftpProgressMonitor monitor)
00494 {
00495 put(src, dst, monitor, OVERWRITE);
00496 }
00497 public void put(InputStream src, String dst,
00498 SftpProgressMonitor monitor, int mode)
00499 {
00500 try{
00501 dst=remoteAbsolutePath(dst);
00502 Vector v=glob_remote(dst);
00503 int vsize=v.size();
00504 if(vsize!=1){
00505 if(vsize==0){
00506 if(isPattern(dst))
00507 throw new SftpException(SSH_FX_FAILURE, dst);
00508 else
00509 dst=Util.unquote(dst);
00510 }
00511 throw new SftpException(SSH_FX_FAILURE, v.toString());
00512 }
00513 else{
00514 dst=(String)(v.elementAt(0));
00515 }
00516 if(isRemoteDir(dst)){
00517 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
00518 }
00519 _put(src, dst, monitor, mode);
00520 }
00521 catch(Exception e){
00522 if(e is SftpException) throw (SftpException)e;
00523 throw new SftpException(SSH_FX_FAILURE, e.toString());
00524 }
00525 }
00526
00527 private void _put(InputStream src, String dst,
00528 SftpProgressMonitor monitor, int mode)
00529 {
00530 try
00531 {
00532 long skip=0;
00533 if(mode==RESUME || mode==APPEND)
00534 {
00535 try
00536 {
00537 SftpATTRS attr=_stat(dst);
00538 skip=attr.getSize();
00539 }
00540 catch(Exception eee)
00541 {
00542
00543 }
00544 }
00545 if(mode==RESUME && skip>0)
00546 {
00547 long skipped=src.skip(skip);
00548 if(skipped<skip)
00549 {
00550 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+dst);
00551 }
00552 }
00553 if(mode==OVERWRITE){ sendOPENW(dst.getBytes()); }
00554 else{ sendOPENA(dst.getBytes()); }
00555
00556 Header _header=new Header();
00557 _header=header(buf, _header);
00558 int length=_header.length;
00559 int type=_header.type;
00560 buf.rewind();
00561 fill(buf.buffer, 0, length);
00562
00563 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
00564 {
00565 throw new SftpException(SSH_FX_FAILURE, "invalid type="+type);
00566 }
00567 if(type==SSH_FXP_STATUS)
00568 {
00569 int i=buf.getInt();
00570 throwStatusError(buf, i);
00571 }
00572 byte[] handle=buf.getString();
00573 byte[] data=null;
00574
00575 bool dontcopy=true;
00576
00577 if(!dontcopy)
00578 {
00579 data=new byte[buf.buffer.Length
00580 -(5+13+21+handle.Length
00581 +32 +20
00582 )
00583 ];
00584 }
00585
00586 long offset=0;
00587 if(mode==RESUME || mode==APPEND)
00588 {
00589 offset+=skip;
00590 }
00591
00592 int startid=seq;
00593 int _ackid=seq;
00594 int ackcount=0;
00595 while(true)
00596 {
00597 int nread=0;
00598 int s=0;
00599 int datalen=0;
00600 int count=0;
00601
00602 if(!dontcopy)
00603 {
00604 datalen=data.Length-s;
00605 }
00606 else
00607 {
00608 data=buf.buffer;
00609 s=5+13+21+handle.Length;
00610 datalen=buf.buffer.Length -s
00611 -32 -20;
00612 }
00613
00614 do
00615 {
00616 nread=src.read(data, s, datalen);
00617 if(nread>0)
00618 {
00619 s+=nread;
00620 datalen-=nread;
00621 count+=nread;
00622 }
00623 }
00624 while(datalen>0 && nread>0);
00625 if(count<=0)break;
00626
00627 int _i=count;
00628 while(_i>0)
00629 {
00630 _i-=sendWRITE(handle, offset, data, 0, _i);
00631 if((seq-1)==startid ||
00632 io.ins.available()>=1024)
00633 {
00634 while(io.ins.available()>0)
00635 {
00636 if(checkStatus(ackid, _header))
00637 {
00638 _ackid=ackid[0];
00639 if(startid>_ackid || _ackid>seq-1)
00640 {
00641 if(_ackid==seq)
00642 {
00643 java.System.err.println("ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
00644 }
00645 else
00646 {
00647
00648 throw new SftpException(SSH_FX_FAILURE, "ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
00649 }
00650 }
00651 ackcount++;
00652 }
00653 else
00654 {
00655 break;
00656 }
00657 }
00658 }
00659 }
00660 offset+=count;
00661 if(monitor!=null && !monitor.count(count))
00662 {
00663 break;
00664 }
00665 }
00666 int _ackcount=seq-startid;
00667 while(_ackcount>ackcount)
00668 {
00669 if(!checkStatus(null, _header))
00670 {
00671 break;
00672 }
00673 ackcount++;
00674 }
00675 if(monitor!=null)monitor.end();
00676 _sendCLOSE(handle, _header);
00677
00678 }
00679 catch(Exception e)
00680 {
00681 if(e is SftpException) throw (SftpException)e;
00682 throw new SftpException(SSH_FX_FAILURE, e.toString());
00683 }
00684 }
00685
00686 private SftpATTRS _stat(String path)
00687 {
00688 try
00689 {
00690 sendSTAT(path.getBytes());
00691
00692 Header _header=new Header();
00693 _header=header(buf, _header);
00694 int length=_header.length;
00695 int type=_header.type;
00696 buf.rewind();
00697 fill(buf.buffer, 0, length);
00698
00699 if(type!=SSH_FXP_ATTRS)
00700 {
00701 if(type==SSH_FXP_STATUS)
00702 {
00703 int i=buf.getInt();
00704 throwStatusError(buf, i);
00705 }
00706 throw new SftpException(SSH_FX_FAILURE, "");
00707 }
00708 SftpATTRS attr=SftpATTRS.getATTR(buf);
00709 return attr;
00710 }
00711 catch(Exception e)
00712 {
00713 if(e is SftpException) throw (SftpException)e;
00714 throw new SftpException(SSH_FX_FAILURE, "");
00715 }
00716
00717 }
00718
00719
00720
00721 public OutputStream put(String dst)
00722 {
00723 return put(dst, (SftpProgressMonitor)null, OVERWRITE);
00724 }
00725 public OutputStream put(String dst, int mode)
00726 {
00727 return put(dst, (SftpProgressMonitor)null, mode);
00728 }
00729 public OutputStream put(String dst, SftpProgressMonitor monitor, int mode)
00730 {
00731 return put(dst, monitor, mode, 0);
00732 }
00733 public OutputStream put(String dst, SftpProgressMonitor monitor, int mode, long offset)
00734 {
00735 dst=remoteAbsolutePath(dst);
00736 try
00737 {
00738 Vector v=glob_remote(dst);
00739 if(v.size()!=1)
00740 {
00741 throw new SftpException(SSH_FX_FAILURE, v.toString());
00742 }
00743 dst=(String)(v.elementAt(0));
00744 if(isRemoteDir(dst))
00745 {
00746 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
00747 }
00748
00749 long skip=0;
00750 if(mode==RESUME || mode==APPEND)
00751 {
00752 try
00753 {
00754 SftpATTRS attr=stat(dst);
00755 skip=attr.getSize();
00756 }
00757 catch(Exception eee)
00758 {
00759
00760 }
00761 }
00762
00763 if(mode==OVERWRITE){ sendOPENW(dst.getBytes()); }
00764 else{ sendOPENA(dst.getBytes()); }
00765
00766 Header _header=new Header();
00767 _header=header(buf, _header);
00768 int length=_header.length;
00769 int type=_header.type;
00770
00771 buf.rewind();
00772 fill(buf.buffer, 0, length);
00773
00774 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
00775 {
00776 throw new SftpException(SSH_FX_FAILURE, "");
00777 }
00778 if(type==SSH_FXP_STATUS)
00779 {
00780 int i=buf.getInt();
00781 throwStatusError(buf, i);
00782 }
00783
00784 byte[] handle=buf.getString();
00785
00786
00787 if(mode==RESUME || mode==APPEND)
00788 {
00789 offset+=skip;
00790 }
00791
00792 long[] _offset=new long[1];
00793 _offset[0]=offset;
00794 OutputStream outs = new OutputStreamPut(this,handle,_offset,monitor);
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 return outs;
00868 }
00869 catch(Exception e)
00870 {
00871 if(e is SftpException) throw (SftpException)e;
00872 throw new SftpException(SSH_FX_FAILURE, "");
00873 }
00874 }
00875
00876
00877 public void get(String src, String dst)
00878 {
00879 get(src, dst, null, OVERWRITE);
00880 }
00881 public void get(String src, String dst,
00882 SftpProgressMonitor monitor)
00883 {
00884 get(src, dst, monitor, OVERWRITE);
00885 }
00886 public void get(String src, String dst,
00887 SftpProgressMonitor monitor, int mode)
00888 {
00889
00890 src=remoteAbsolutePath(src);
00891 dst=localAbsolutePath(dst);
00892 try
00893 {
00894 Vector v=glob_remote(src);
00895 int vsize=v.size();
00896 if(vsize==0)
00897 {
00898 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file");
00899 }
00900
00901 File dstFile=new File(dst);
00902 bool isDstDir=dstFile.isDirectory();
00903 StringBuffer dstsb=null;
00904 if(isDstDir)
00905 {
00906 if(!dst.endsWith(file_separator))
00907 {
00908 dst+=file_separator;
00909 }
00910 dstsb=new StringBuffer(dst);
00911 }
00912 else if(vsize>1)
00913 {
00914 throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but destination is missing or a file.");
00915 }
00916
00917 for(int j=0; j<vsize; j++)
00918 {
00919 String _src=(String)(v.elementAt(j));
00920
00921 SftpATTRS attr=_stat(_src);
00922 if(attr.isDir())
00923 {
00924 throw new SftpException(SSH_FX_FAILURE, "not supported to get directory "+_src);
00925 }
00926
00927 String _dst=null;
00928 if(isDstDir)
00929 {
00930 int i=_src.lastIndexOf('/');
00931 if(i==-1) dstsb.append(_src);
00932 else dstsb.append(_src.substring(i + 1));
00933 _dst=dstsb.toString();
00934 dstsb.delete(dst.length(), _dst.length());
00935 }
00936 else
00937 {
00938 _dst=dst;
00939 }
00940
00941 if(mode==RESUME)
00942 {
00943 long size_of_src=attr.getSize();
00944 long size_of_dst=new File(_dst).length();
00945 if(size_of_dst>size_of_src)
00946 {
00947 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+_dst);
00948 }
00949 if(size_of_dst==size_of_src)
00950 {
00951 return;
00952 }
00953 }
00954
00955 if(monitor!=null)
00956 {
00957 monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize());
00958 if(mode==RESUME)
00959 {
00960 monitor.count(new File(_dst).length());
00961 }
00962 }
00963 FileOutputStream fos=null;
00964 if(mode==OVERWRITE)
00965 {
00966 fos=new FileOutputStream(_dst);
00967 }
00968 else
00969 {
00970 fos=new FileOutputStream(_dst, true);
00971 }
00972
00973
00974 _get(_src, fos, monitor, mode, new File(_dst).length());
00975 fos.close();
00976 }
00977 }
00978 catch(Exception e)
00979 {
00980 if(e is SftpException) throw (SftpException)e;
00981 throw new SftpException(SSH_FX_FAILURE, "");
00982 }
00983 }
00984 public void get(String src, OutputStream dst)
00985 {
00986 get(src, dst, null, OVERWRITE, 0);
00987 }
00988 public void get(String src, OutputStream dst,
00989 SftpProgressMonitor monitor)
00990 {
00991 get(src, dst, monitor, OVERWRITE, 0);
00992 }
00993 public void get(String src, OutputStream dst,
00994 SftpProgressMonitor monitor, int mode, long skip)
00995 {
00996
00997 try
00998 {
00999 src=remoteAbsolutePath(src);
01000 Vector v=glob_remote(src);
01001 if(v.size()!=1)
01002 {
01003 throw new SftpException(SSH_FX_FAILURE, v.toString());
01004 }
01005 src=(String)(v.elementAt(0));
01006
01007 if(monitor!=null)
01008 {
01009 SftpATTRS attr=_stat(src);
01010 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
01011 if(mode==RESUME)
01012 {
01013 monitor.count(skip);
01014 }
01015 }
01016 _get(src, dst, monitor, mode, skip);
01017 }
01018 catch(Exception e)
01019 {
01020 if(e is SftpException) throw (SftpException)e;
01021 throw new SftpException(SSH_FX_FAILURE, "");
01022 }
01023 }
01024
01026 private void _get(String src, OutputStream dst,
01027 SftpProgressMonitor monitor, int mode, long skip)
01028 {
01029
01030 try
01031 {
01032 sendOPENR(src.getBytes());
01033
01034
01035 Header _header=new Header();
01036 _header=header(buf, _header);
01037 int length=_header.length;
01038 int type=_header.type;
01039
01040 buf.rewind();
01041
01042 fill(buf.buffer, 0, length);
01043
01044 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
01045 {
01046
01047 throw new SftpException(SSH_FX_FAILURE, "Type is "+type);
01048 }
01049
01050 if(type==SSH_FXP_STATUS)
01051 {
01052 int i=buf.getInt();
01053 throwStatusError(buf, i);
01054 }
01055
01056 byte[] handle=buf.getString();
01057
01058 long offset=0;
01059 if(mode==RESUME)
01060 {
01061 offset+=skip;
01062 }
01063
01064 int request_len=0;
01065 loop:
01066 while(true)
01067 {
01068
01069 request_len=buf.buffer.Length-13;
01070 if(server_version==0){ request_len=1024; }
01071 sendREAD(handle, offset, request_len);
01072
01073 _header=header(buf, _header);
01074 length=_header.length;
01075 type=_header.type;
01076
01077 int i;
01078 if(type==SSH_FXP_STATUS)
01079 {
01080 buf.rewind();
01081 fill(buf.buffer, 0, length);
01082 i=buf.getInt();
01083 if(i==SSH_FX_EOF)
01084 {
01085 goto BREAK;
01086 }
01087 throwStatusError(buf, i);
01088 }
01089
01090 if(type!=SSH_FXP_DATA)
01091 {
01092 goto BREAK;
01093 }
01094
01095 buf.rewind();
01096 fill(buf.buffer, 0, 4); length-=4;
01097 i=buf.getInt();
01098 int foo=i;
01099 while(foo>0)
01100 {
01101 int bar=foo;
01102 if(bar>buf.buffer.Length)
01103 {
01104 bar=buf.buffer.Length;
01105 }
01106 i=io.ins.read(buf.buffer, 0, bar);
01107 if(i<0)
01108 {
01109 goto BREAK;
01110 }
01111 int data_len=i;
01112 dst.write(buf.buffer, 0, data_len);
01113
01114 offset+=data_len;
01115 foo-=data_len;
01116
01117 if(monitor!=null)
01118 {
01119 if(!monitor.count(data_len))
01120 {
01121 while(foo>0)
01122 {
01123 i=io.ins.read(buf.buffer,
01124 0,
01125 (buf.buffer.Length<foo?buf.buffer.Length:foo));
01126 if(i<=0) break;
01127 foo-=i;
01128 }
01129 goto BREAK;
01130 }
01131 }
01132 }
01133
01134 }
01135 BREAK:
01136 dst.flush();
01137
01138 if(monitor!=null)monitor.end();
01139 _sendCLOSE(handle, _header);
01140 }
01141 catch(Exception e)
01142 {
01143
01144 if(e is SftpException) throw (SftpException)e;
01145 throw new SftpException(SSH_FX_FAILURE, "");
01146 }
01147 }
01148
01149 public InputStream get(String src)
01150 {
01151 return get(src, null, OVERWRITE);
01152 }
01153 public InputStream get(String src, SftpProgressMonitor monitor)
01154 {
01155 return get(src, monitor, OVERWRITE);
01156 }
01157 public InputStream get(String src, int mode)
01158 {
01159 return get(src, null, mode);
01160 }
01161 public InputStream get(String src, SftpProgressMonitor monitor, int mode)
01162 {
01163 if(mode==RESUME)
01164 {
01165 throw new SftpException(SSH_FX_FAILURE, "faile to resume from "+src);
01166 }
01167 src=remoteAbsolutePath(src);
01168 try
01169 {
01170 Vector v=glob_remote(src);
01171 if(v.size()!=1)
01172 {
01173 throw new SftpException(SSH_FX_FAILURE, v.toString());
01174 }
01175 src=(String)(v.elementAt(0));
01176
01177 SftpATTRS attr=_stat(src);
01178 if(monitor!=null)
01179 {
01180 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
01181 }
01182
01183 sendOPENR(src.getBytes());
01184
01185 Header _header=new Header();
01186 _header=header(buf, _header);
01187 int length=_header.length;
01188 int type=_header.type;
01189 buf.rewind();
01190 fill(buf.buffer, 0, length);
01191
01192 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
01193 {
01194 throw new SftpException(SSH_FX_FAILURE, "");
01195 }
01196 if(type==SSH_FXP_STATUS)
01197 {
01198 int i=buf.getInt();
01199 throwStatusError(buf, i);
01200 }
01201
01202 byte[] handle=buf.getString();
01203
01204 java.io.InputStream ins=new InputStreamGet(this, handle, monitor);
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 return ins;
01317 }
01318 catch(Exception e)
01319 {
01320 if(e is SftpException) throw (SftpException)e;
01321 throw new SftpException(SSH_FX_FAILURE, "");
01322 }
01323 }
01324
01325 public java.util.Vector ls(String path)
01326 {
01327 try
01328 {
01329 path=remoteAbsolutePath(path);
01330
01331 String dir=path;
01332 byte[] pattern=null;
01333 SftpATTRS attr=null;
01334 if(isPattern(dir) ||
01335 ((attr=stat(dir))!=null && !attr.isDir()))
01336 {
01337 int foo=path.lastIndexOf('/');
01338 dir=path.substring(0, ((foo==0)?1:foo));
01339 pattern=path.substring(foo+1).getBytes();
01340 }
01341
01342 sendOPENDIR(dir.getBytes());
01343
01344 Header _header=new Header();
01345 _header=header(buf, _header);
01346 int length=_header.length;
01347 int type=_header.type;
01348 buf.rewind();
01349 fill(buf.buffer, 0, length);
01350
01351 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
01352 {
01353 throw new SftpException(SSH_FX_FAILURE, "");
01354 }
01355 if(type==SSH_FXP_STATUS)
01356 {
01357 int i=buf.getInt();
01358 throwStatusError(buf, i);
01359 }
01360
01361 byte[] handle=buf.getString();
01362
01363 java.util.Vector v=new java.util.Vector();
01364 while(true)
01365 {
01366 sendREADDIR(handle);
01367
01368 _header=header(buf, _header);
01369 length=_header.length;
01370 type=_header.type;
01371 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME)
01372 {
01373 throw new SftpException(SSH_FX_FAILURE, "");
01374 }
01375 if(type==SSH_FXP_STATUS)
01376 {
01377 buf.rewind();
01378 fill(buf.buffer, 0, length);
01379 int i=buf.getInt();
01380 if(i==SSH_FX_EOF)
01381 break;
01382 throwStatusError(buf, i);
01383 }
01384
01385 buf.rewind();
01386 fill(buf.buffer, 0, 4); length-=4;
01387 int count=buf.getInt();
01388
01389 byte[] str;
01390 int flags;
01391
01392 buf.reset();
01393 while(count>0)
01394 {
01395 if(length>0)
01396 {
01397 buf.shift();
01398 int j=(buf.buffer.Length>(buf.index+length)) ? length : (buf.buffer.Length-buf.index);
01399 int i=fill(buf.buffer, buf.index, j);
01400 buf.index+=i;
01401 length-=i;
01402 }
01403 byte[] filename=buf.getString();
01404 str=buf.getString();
01405 String longname=new String(str);
01406
01407 SftpATTRS attrs=SftpATTRS.getATTR(buf);
01408 if(pattern==null || Util.glob(pattern, filename))
01409 {
01410 v.addElement(new LsEntry(new String(filename), longname, attrs));
01411 }
01412
01413 count--;
01414 }
01415 }
01416 _sendCLOSE(handle, _header);
01417 return v;
01418 }
01419 catch(Exception e)
01420 {
01421 if(e is SftpException) throw (SftpException)e;
01422 throw new SftpException(SSH_FX_FAILURE, "");
01423 }
01424 }
01425
01426 public String readlink(String path)
01427 {
01428
01429 try
01430 {
01431 path=remoteAbsolutePath(path);
01432 Vector v=glob_remote(path);
01433 if(v.size()!=1)
01434 {
01435 throw new SftpException(SSH_FX_FAILURE, v.toString());
01436 }
01437 path=(String)(v.elementAt(0));
01438
01439 sendREADLINK(path.getBytes());
01440
01441 Header _header=new Header();
01442 _header=header(buf, _header);
01443 int length=_header.length;
01444 int type=_header.type;
01445 buf.rewind();
01446 fill(buf.buffer, 0, length);
01447
01448 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME)
01449 {
01450 throw new SftpException(SSH_FX_FAILURE, "");
01451 }
01452 int i;
01453 if(type==SSH_FXP_NAME)
01454 {
01455 int count=buf.getInt();
01456 byte[] filename=null;
01457 byte[] longname=null;
01458 for(i=0; i<count; i++)
01459 {
01460 filename=buf.getString();
01461 longname=buf.getString();
01462 SftpATTRS.getATTR(buf);
01463 }
01464 return new String(filename);
01465 }
01466
01467 i=buf.getInt();
01468 throwStatusError(buf, i);
01469 }
01470 catch(Exception e)
01471 {
01472 if(e is SftpException) throw (SftpException)e;
01473 throw new SftpException(SSH_FX_FAILURE, "");
01474 }
01475 return null;
01476 }
01477
01478
01479 public void symlink(String oldpath, String newpath)
01480 {
01481
01482 if(server_version<3)
01483 {
01484 throw new SftpException(SSH_FX_FAILURE,
01485 "The remote sshd is too old to support symlink operation.");
01486 }
01487
01488 try
01489 {
01490 oldpath=remoteAbsolutePath(oldpath);
01491 newpath=remoteAbsolutePath(newpath);
01492
01493 Vector v=glob_remote(oldpath);
01494 int vsize=v.size();
01495 if(vsize!=1)
01496 {
01497 throw new SftpException(SSH_FX_FAILURE, v.toString());
01498 }
01499 oldpath=(String)(v.elementAt(0));
01500
01501 if(isPattern(newpath))
01502 {
01503 throw new SftpException(SSH_FX_FAILURE, v.toString());
01504 }
01505
01506 newpath=Util.unquote(newpath);
01507
01508 sendSYMLINK(oldpath.getBytes(), newpath.getBytes());
01509
01510 Header _header=new Header();
01511 _header=header(buf, _header);
01512 int length=_header.length;
01513 int type=_header.type;
01514 buf.rewind();
01515 fill(buf.buffer, 0, length);
01516
01517 if(type!=SSH_FXP_STATUS)
01518 {
01519 throw new SftpException(SSH_FX_FAILURE, "");
01520 }
01521
01522 int i=buf.getInt();
01523 if(i==SSH_FX_OK) return;
01524 throwStatusError(buf, i);
01525 }
01526 catch(Exception e)
01527 {
01528 if(e is SftpException) throw (SftpException)e;
01529 throw new SftpException(SSH_FX_FAILURE, "");
01530 }
01531 }
01532 public void rename(String oldpath, String newpath)
01533 {
01534
01535 if(server_version<2)
01536 {
01537 throw new SftpException(SSH_FX_FAILURE,
01538 "The remote sshd is too old to support rename operation.");
01539 }
01540 try
01541 {
01542 oldpath=remoteAbsolutePath(oldpath);
01543 newpath=remoteAbsolutePath(newpath);
01544
01545 Vector v=glob_remote(oldpath);
01546 int vsize=v.size();
01547 if(vsize!=1)
01548 {
01549 throw new SftpException(SSH_FX_FAILURE, v.toString());
01550 }
01551 oldpath=(String)(v.elementAt(0));
01552
01553 v=glob_remote(newpath);
01554 vsize=v.size();
01555 if(vsize>=2)
01556 {
01557 throw new SftpException(SSH_FX_FAILURE, v.toString());
01558 }
01559 if(vsize==1)
01560 {
01561 newpath=(String)(v.elementAt(0));
01562 }
01563 else
01564 {
01565 if(isPattern(newpath))
01566 throw new SftpException(SSH_FX_FAILURE, newpath);
01567 newpath=Util.unquote(newpath);
01568 }
01569
01570 sendRENAME(oldpath.getBytes(), newpath.getBytes());
01571
01572 Header _header=new Header();
01573 _header=header(buf, _header);
01574 int length=_header.length;
01575 int type=_header.type;
01576 buf.rewind();
01577 fill(buf.buffer, 0, length);
01578
01579 if(type!=SSH_FXP_STATUS)
01580 {
01581 throw new SftpException(SSH_FX_FAILURE, "");
01582 }
01583
01584 int i=buf.getInt();
01585 if(i==SSH_FX_OK) return;
01586 throwStatusError(buf, i);
01587 }
01588 catch(Exception e)
01589 {
01590 if(e is SftpException) throw (SftpException)e;
01591 throw new SftpException(SSH_FX_FAILURE, "");
01592 }
01593 }
01594 public void rm(String path)
01595 {
01596
01597 try
01598 {
01599 path=remoteAbsolutePath(path);
01600 Vector v=glob_remote(path);
01601 int vsize=v.size();
01602 Header _header=new Header();
01603
01604 for(int j=0; j<vsize; j++)
01605 {
01606 path=(String)(v.elementAt(j));
01607 sendREMOVE(path.getBytes());
01608
01609 _header=header(buf, _header);
01610 int length=_header.length;
01611 int type=_header.type;
01612 buf.rewind();
01613 fill(buf.buffer, 0, length);
01614
01615 if(type!=SSH_FXP_STATUS)
01616 {
01617 throw new SftpException(SSH_FX_FAILURE, "");
01618 }
01619 int i=buf.getInt();
01620 if(i!=SSH_FX_OK)
01621 {
01622 throwStatusError(buf, i);
01623 }
01624 }
01625 }
01626 catch(Exception e)
01627 {
01628 if(e is SftpException) throw (SftpException)e;
01629 throw new SftpException(SSH_FX_FAILURE, "");
01630 }
01631 }
01632 private bool isRemoteDir(String path)
01633 {
01634 try
01635 {
01636 sendSTAT(path.getBytes());
01637
01638 Header _header=new Header();
01639 _header=header(buf, _header);
01640 int length=_header.length;
01641 int type=_header.type;
01642 buf.rewind();
01643 fill(buf.buffer, 0, length);
01644
01645 if(type!=SSH_FXP_ATTRS)
01646 {
01647 return false;
01648 }
01649 SftpATTRS attr=SftpATTRS.getATTR(buf);
01650 return attr.isDir();
01651 }
01652 catch(Exception e){}
01653 return false;
01654 }
01655
01656
01657
01658
01659
01660
01661 public void chgrp(int gid, String path)
01662 {
01663 try
01664 {
01665 path=remoteAbsolutePath(path);
01666
01667 Vector v=glob_remote(path);
01668 int vsize=v.size();
01669 for(int j=0; j<vsize; j++)
01670 {
01671 path=(String)(v.elementAt(j));
01672
01673 SftpATTRS attr=_stat(path);
01674
01675 attr.setFLAGS(0);
01676 attr.setUIDGID(attr.uid, gid);
01677 _setStat(path, attr);
01678 }
01679 }
01680 catch(Exception e)
01681 {
01682 if(e is SftpException) throw (SftpException)e;
01683 throw new SftpException(SSH_FX_FAILURE, "");
01684 }
01685 }
01686 public void chown(int uid, String path)
01687 {
01688 try
01689 {
01690 path=remoteAbsolutePath(path);
01691
01692 Vector v=glob_remote(path);
01693 int vsize=v.size();
01694 for(int j=0; j<vsize; j++)
01695 {
01696 path=(String)(v.elementAt(j));
01697
01698 SftpATTRS attr=_stat(path);
01699
01700 attr.setFLAGS(0);
01701 attr.setUIDGID(uid, attr.gid);
01702 _setStat(path, attr);
01703 }
01704 }
01705 catch(Exception e)
01706 {
01707 if(e is SftpException) throw (SftpException)e;
01708 throw new SftpException(SSH_FX_FAILURE, "");
01709 }
01710 }
01711 public void chmod(int permissions, String path)
01712 {
01713 try
01714 {
01715 path=remoteAbsolutePath(path);
01716
01717 Vector v=glob_remote(path);
01718 int vsize=v.size();
01719 for(int j=0; j<vsize; j++)
01720 {
01721 path=(String)(v.elementAt(j));
01722
01723 SftpATTRS attr=_stat(path);
01724
01725 attr.setFLAGS(0);
01726 attr.setPERMISSIONS(permissions);
01727 _setStat(path, attr);
01728 }
01729 }
01730 catch(Exception e)
01731 {
01732 if(e is SftpException) throw (SftpException)e;
01733 throw new SftpException(SSH_FX_FAILURE, "");
01734 }
01735 }
01736 public void setMtime(String path, int mtime)
01737 {
01738 try
01739 {
01740 path=remoteAbsolutePath(path);
01741
01742 Vector v=glob_remote(path);
01743 int vsize=v.size();
01744 for(int j=0; j<vsize; j++)
01745 {
01746 path=(String)(v.elementAt(j));
01747
01748 SftpATTRS attr=_stat(path);
01749
01750 attr.setFLAGS(0);
01751 attr.setACMODTIME(attr.getATime(), mtime);
01752 _setStat(path, attr);
01753 }
01754 }
01755 catch(Exception e)
01756 {
01757 if(e is SftpException) throw (SftpException)e;
01758 throw new SftpException(SSH_FX_FAILURE, "");
01759 }
01760 }
01761 public void rmdir(String path)
01762 {
01763
01764 try
01765 {
01766 path=remoteAbsolutePath(path);
01767
01768 Vector v=glob_remote(path);
01769 int vsize=v.size();
01770 Header _header=new Header();
01771
01772 for(int j=0; j<vsize; j++)
01773 {
01774 path=(String)(v.elementAt(j));
01775 sendRMDIR(path.getBytes());
01776
01777 _header=header(buf, _header);
01778 int length=_header.length;
01779 int type=_header.type;
01780 buf.rewind();
01781 fill(buf.buffer, 0, length);
01782
01783 if(type!=SSH_FXP_STATUS)
01784 {
01785 throw new SftpException(SSH_FX_FAILURE, "");
01786 }
01787
01788 int i=buf.getInt();
01789 if(i!=SSH_FX_OK)
01790 {
01791 throwStatusError(buf, i);
01792 }
01793 }
01794 }
01795 catch(Exception e)
01796 {
01797 if(e is SftpException) throw (SftpException)e;
01798 throw new SftpException(SSH_FX_FAILURE, "");
01799 }
01800 }
01801
01802 public void mkdir(String path)
01803 {
01804
01805 try
01806 {
01807 path=remoteAbsolutePath(path);
01808
01809 sendMKDIR(path.getBytes(), null);
01810
01811 Header _header=new Header();
01812 _header=header(buf, _header);
01813 int length=_header.length;
01814 int type=_header.type;
01815 buf.rewind();
01816 fill(buf.buffer, 0, length);
01817
01818 if(type!=SSH_FXP_STATUS)
01819 {
01820 throw new SftpException(SSH_FX_FAILURE, "");
01821 }
01822
01823 int i=buf.getInt();
01824 if(i==SSH_FX_OK) return;
01825 throwStatusError(buf, i);
01826 }
01827 catch(Exception e)
01828 {
01829 if(e is SftpException) throw (SftpException)e;
01830 throw new SftpException(SSH_FX_FAILURE, "");
01831 }
01832 }
01833
01834 public SftpATTRS stat(String path)
01835 {
01836
01837 try
01838 {
01839 path=remoteAbsolutePath(path);
01840
01841 Vector v=glob_remote(path);
01842 if(v.size()!=1)
01843 {
01844 throw new SftpException(SSH_FX_FAILURE, v.toString());
01845 }
01846 path=(String)(v.elementAt(0));
01847 return _stat(path);
01848 }
01849 catch(Exception e)
01850 {
01851 if(e is SftpException) throw (SftpException)e;
01852 throw new SftpException(SSH_FX_FAILURE, "");
01853 }
01854
01855 }
01856 public SftpATTRS lstat(String path)
01857 {
01858
01859 try
01860 {
01861 path=remoteAbsolutePath(path);
01862
01863 Vector v=glob_remote(path);
01864 if(v.size()!=1)
01865 {
01866 throw new SftpException(SSH_FX_FAILURE, v.toString());
01867 }
01868 path=(String)(v.elementAt(0));
01869
01870 return _lstat(path);
01871 }
01872 catch(Exception e)
01873 {
01874 if(e is SftpException) throw (SftpException)e;
01875 throw new SftpException(SSH_FX_FAILURE, "");
01876 }
01877 }
01878
01879 private SftpATTRS _lstat(String path)
01880 {
01881
01882 try
01883 {
01884 sendLSTAT(path.getBytes());
01885
01886 Header _header=new Header();
01887 _header=header(buf, _header);
01888 int length=_header.length;
01889 int type=_header.type;
01890 buf.rewind();
01891 fill(buf.buffer, 0, length);
01892
01893 if(type!=SSH_FXP_ATTRS)
01894 {
01895 if(type==SSH_FXP_STATUS)
01896 {
01897 int i=buf.getInt();
01898 throwStatusError(buf, i);
01899 }
01900 throw new SftpException(SSH_FX_FAILURE, "");
01901 }
01902 SftpATTRS attr=SftpATTRS.getATTR(buf);
01903 return attr;
01904 }
01905 catch(Exception e)
01906 {
01907 if(e is SftpException) throw (SftpException)e;
01908 throw new SftpException(SSH_FX_FAILURE, "");
01909 }
01910 }
01911
01912
01913 public void setStat(String path, SftpATTRS attr)
01914 {
01915 try
01916 {
01917 path=remoteAbsolutePath(path);
01918
01919 Vector v=glob_remote(path);
01920 int vsize=v.size();
01921 for(int j=0; j<vsize; j++)
01922 {
01923 path=(String)(v.elementAt(j));
01924 _setStat(path, attr);
01925 }
01926 }
01927 catch(Exception e)
01928 {
01929 if(e is SftpException) throw (SftpException)e;
01930 throw new SftpException(SSH_FX_FAILURE, "");
01931 }
01932 }
01933 private void _setStat(String path, SftpATTRS attr)
01934 {
01935
01936 try
01937 {
01938 sendSETSTAT(path.getBytes(), attr);
01939
01940 Header _header=new Header();
01941 _header=header(buf, _header);
01942 int length=_header.length;
01943 int type=_header.type;
01944 buf.rewind();
01945 fill(buf.buffer, 0, length);
01946
01947 if(type!=SSH_FXP_STATUS)
01948 {
01949 throw new SftpException(SSH_FX_FAILURE, "");
01950 }
01951 int i=buf.getInt();
01952 if(i!=SSH_FX_OK)
01953 {
01954 throwStatusError(buf, i);
01955 }
01956 }
01957 catch(Exception e)
01958 {
01959 if(e is SftpException) throw (SftpException)e;
01960 throw new SftpException(SSH_FX_FAILURE, "");
01961 }
01962 }
01963
01964 public String pwd(){ return cwd; }
01965 public String lpwd(){ return lcwd; }
01966 public String version(){ return _version; }
01967 public String getHome(){ return home; }
01968
01969 private void read(byte[] buf, int s, int l)
01970 {
01971 int i=0;
01972 while(l>0)
01973 {
01974 i=io.ins.read(buf, s, l);
01975 if(i<=0)
01976 {
01977 throw new SftpException(SSH_FX_FAILURE, "");
01978 }
01979 s+=i;
01980 l-=i;
01981 }
01982 }
01983 internal bool checkStatus(int[] ackid, Header _header )
01984 {
01985 _header=header(buf, _header);
01986 int length=_header.length;
01987 int type=_header.type;
01988 if(ackid!=null)
01989 ackid[0]=_header.rid;
01990 buf.rewind();
01991 fill(buf.buffer, 0, length);
01992
01993 if(type!=SSH_FXP_STATUS)
01994 {
01995 throw new SftpException(SSH_FX_FAILURE, "");
01996 }
01997 int i=buf.getInt();
01998 if(i!=SSH_FX_OK)
01999 {
02000 throwStatusError(buf, i);
02001 }
02002 return true;
02003 }
02004
02005 internal bool _sendCLOSE(byte[] handle, Header header)
02006
02007 {
02008 sendCLOSE(handle);
02009 return checkStatus(null, header);
02010 }
02011
02012 private void sendINIT()
02013 {
02014 packet.reset();
02015 putHEAD(SSH_FXP_INIT, 5);
02016 buf.putInt(3);
02017 session.write(packet, this, 5+4);
02018 }
02019
02020 private void sendREALPATH(byte[] path)
02021 {
02022 sendPacketPath(SSH_FXP_REALPATH, path);
02023 }
02024 private void sendSTAT(byte[] path)
02025 {
02026 sendPacketPath(SSH_FXP_STAT, path);
02027 }
02028 private void sendLSTAT(byte[] path)
02029 {
02030 sendPacketPath(SSH_FXP_LSTAT, path);
02031 }
02032 private void sendFSTAT(byte[] handle)
02033 {
02034 sendPacketPath(SSH_FXP_FSTAT, handle);
02035 }
02036 private void sendSETSTAT(byte[] path, SftpATTRS attr)
02037 {
02038 packet.reset();
02039 putHEAD(SSH_FXP_SETSTAT, 9+path.Length+attr.Length());
02040 buf.putInt(seq++);
02041 buf.putString(path);
02042 attr.dump(buf);
02043 session.write(packet, this, 9+path.Length+attr.Length()+4);
02044 }
02045 private void sendREMOVE(byte[] path)
02046 {
02047 sendPacketPath(SSH_FXP_REMOVE, path);
02048 }
02049 private void sendMKDIR(byte[] path, SftpATTRS attr)
02050 {
02051 packet.reset();
02052 putHEAD(SSH_FXP_MKDIR, 9+path.Length+(attr!=null?attr.Length():4));
02053 buf.putInt(seq++);
02054 buf.putString(path);
02055 if(attr!=null) attr.dump(buf);
02056 else buf.putInt(0);
02057 session.write(packet, this, 9+path.Length+(attr!=null?attr.Length():4)+4);
02058 }
02059 private void sendRMDIR(byte[] path)
02060 {
02061 sendPacketPath(SSH_FXP_RMDIR, path);
02062 }
02063 private void sendSYMLINK(byte[] p1, byte[] p2)
02064 {
02065 sendPacketPath(SSH_FXP_SYMLINK, p1, p2);
02066 }
02067 private void sendREADLINK(byte[] path)
02068 {
02069 sendPacketPath(SSH_FXP_READLINK, path);
02070 }
02071 private void sendOPENDIR(byte[] path)
02072 {
02073 sendPacketPath(SSH_FXP_OPENDIR, path);
02074 }
02075 private void sendREADDIR(byte[] path)
02076 {
02077 sendPacketPath(SSH_FXP_READDIR, path);
02078 }
02079 private void sendRENAME(byte[] p1, byte[] p2)
02080 {
02081 sendPacketPath(SSH_FXP_RENAME, p1, p2);
02082 }
02083 private void sendCLOSE(byte[] path)
02084 {
02085 sendPacketPath(SSH_FXP_CLOSE, path);
02086 }
02087 private void sendOPENR(byte[] path)
02088 {
02089 sendOPEN(path, SSH_FXF_READ);
02090 }
02091 private void sendOPENW(byte[] path)
02092 {
02093 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC);
02094 }
02095 private void sendOPENA(byte[] path)
02096 {
02097 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT);
02098 }
02099 private void sendOPEN(byte[] path, int mode)
02100 {
02101 packet.reset();
02102 putHEAD(SSH_FXP_OPEN, 17+path.Length);
02103 buf.putInt(seq++);
02104 buf.putString(path);
02105 buf.putInt(mode);
02106 buf.putInt(0);
02107 session.write(packet, this, 17+path.Length+4);
02108 }
02109 private void sendPacketPath(byte fxp, byte[] path)
02110 {
02111 packet.reset();
02112 putHEAD(fxp, 9+path.Length);
02113 buf.putInt(seq++);
02114 buf.putString(path);
02115 session.write(packet, this, 9+path.Length+4);
02116 }
02117 private void sendPacketPath(byte fxp, byte[] p1, byte[] p2)
02118 {
02119 packet.reset();
02120 putHEAD(fxp, 13+p1.Length+p2.Length);
02121 buf.putInt(seq++);
02122 buf.putString(p1);
02123 buf.putString(p2);
02124 session.write(packet, this, 13+p1.Length+p2.Length+4);
02125 }
02126
02127 internal int sendWRITE(byte[] handle, long offset,
02128 byte[] data, int start, int length)
02129 {
02130 int _length=length;
02131 packet.reset();
02132 if(buf.buffer.Length<buf.index+13+21+handle.Length+length
02133 +32 +20
02134 )
02135 {
02136 _length=buf.buffer.Length-(buf.index+13+21+handle.Length
02137 +32 +20
02138 );
02139
02140 }
02141 putHEAD(SSH_FXP_WRITE, 21+handle.Length+_length);
02142 buf.putInt(seq++);
02143 buf.putString(handle);
02144 buf.putLong(offset);
02145 if(buf.buffer!=data)
02146 {
02147 buf.putString(data, start, _length);
02148 }
02149 else
02150 {
02151 buf.putInt(_length);
02152 buf.skip(_length);
02153 }
02154 session.write(packet, this, 21+handle.Length+_length+4);
02155 return _length;
02156 }
02157
02158 private void sendREAD(byte[] handle, long offset, int length)
02159 {
02160 packet.reset();
02161 putHEAD(SSH_FXP_READ, 21+handle.Length);
02162 buf.putInt(seq++);
02163 buf.putString(handle);
02164 buf.putLong(offset);
02165 buf.putInt(length);
02166 session.write(packet, this, 21+handle.Length+4);
02167 }
02168
02169 private void putHEAD(byte type, int length)
02170 {
02171 buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);
02172 buf.putInt(recipient);
02173 buf.putInt(length+4);
02174 buf.putInt(length);
02175 buf.putByte(type);
02176 }
02177 private Vector glob_remote(String _path)
02178 {
02179
02180
02181 Vector v=new Vector();
02182 byte[] path=_path.getBytes();
02183 if(!isPattern(path))
02184 {
02185 v.addElement(Util.unquote(_path)); return v;
02186 }
02187 int i=path.Length-1;
02188 while(i>=0){if(path[i]=='/')break;i--;}
02189 if(i<0){ v.addElement(Util.unquote(_path)); return v;}
02190 byte[] dir;
02191 if(i==0){dir=new byte[]{(byte)'/'};}
02192 else
02193 {
02194 dir=new byte[i];
02195 java.System.arraycopy(path, 0, dir, 0, i);
02196 }
02197
02198 byte[] pattern=new byte[path.Length-i-1];
02199 java.System.arraycopy(path, i+1, pattern, 0, pattern.Length);
02200
02201
02202 sendOPENDIR(dir);
02203
02204 Header _header=new Header();
02205 _header=header(buf, _header);
02206 int length=_header.length;
02207 int type=_header.type;
02208 buf.rewind();
02209 fill(buf.buffer, 0, length);
02210
02211 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE)
02212 {
02213 throw new SftpException(SSH_FX_FAILURE, "");
02214 }
02215 if(type==SSH_FXP_STATUS)
02216 {
02217 i=buf.getInt();
02218 throwStatusError(buf, i);
02219 }
02220
02221 byte[] handle=buf.getString();
02222
02223 while(true)
02224 {
02225 sendREADDIR(handle);
02226 _header=header(buf, _header);
02227 length=_header.length;
02228 type=_header.type;
02229
02230 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME)
02231 {
02232 throw new SftpException(SSH_FX_FAILURE, "");
02233 }
02234 if(type==SSH_FXP_STATUS)
02235 {
02236 buf.rewind();
02237 fill(buf.buffer, 0, length);
02238 break;
02239 }
02240
02241 buf.rewind();
02242 fill(buf.buffer, 0, 4); length-=4;
02243 int count=buf.getInt();
02244
02245 byte[] str;
02246 int flags;
02247
02248 buf.reset();
02249 while(count>0)
02250 {
02251 if(length>0)
02252 {
02253 buf.shift();
02254 int j=(buf.buffer.Length>(buf.index+length)) ? length : (buf.buffer.Length-buf.index);
02255 i=io.ins.read(buf.buffer, buf.index, j);
02256 if(i<=0)break;
02257 buf.index+=i;
02258 length-=i;
02259 }
02260
02261 byte[] filename=buf.getString();
02262
02263 str=buf.getString();
02264 SftpATTRS attrs=SftpATTRS.getATTR(buf);
02265
02266 if(Util.glob(pattern, filename))
02267 {
02268 v.addElement(new String(dir)+"/"+new String(filename));
02269 }
02270 count--;
02271 }
02272 }
02273 if(_sendCLOSE(handle, _header))
02274 return v;
02275 return null;
02276 }
02277
02278 private Vector glob_local(String _path)
02279 {
02280
02281 Vector v=new Vector();
02282 byte[] path=_path.getBytes();
02283 int i=path.Length-1;
02284 while(i>=0){if(path[i]=='*' || path[i]=='?')break;i--;}
02285 if(i<0){ v.addElement(_path); return v;}
02286 while(i>=0){if(path[i]==file_separatorc)break;i--;}
02287 if(i<0){ v.addElement(_path); return v;}
02288 byte[] dir;
02289 if(i==0){dir=new byte[]{(byte)file_separatorc};}
02290 else
02291 {
02292 dir=new byte[i];
02293 Tamir.SharpSsh.java.System.arraycopy(path, 0, dir, 0, i);
02294 }
02295 byte[] pattern=new byte[path.Length-i-1];
02296 Tamir.SharpSsh.java.System.arraycopy(path, i+1, pattern, 0, pattern.Length);
02297
02298 try
02299 {
02300 String[] children=(new File(new String(dir))).list();
02301 for(int j=0; j<children.Length; j++)
02302 {
02303
02304 if(Util.glob(pattern, children[j].getBytes()))
02305 {
02306 v.addElement(new String(dir)+file_separator+children[j]);
02307 }
02308 }
02309 }
02310 catch(Exception e)
02311 {
02312 }
02313 return v;
02314 }
02315
02316 private void throwStatusError(Buffer buf, int i)
02317 {
02318 if(server_version>=3)
02319 {
02320 byte[] str=buf.getString();
02321
02322 throw new SftpException(i, new String(str));
02323 }
02324 else
02325 {
02326 throw new SftpException(i, "Failure");
02327 }
02328 }
02329
02330 private static bool isLocalAbsolutePath(String path)
02331 {
02332 return (new File(path)).isAbsolute();
02333 }
02334
02335
02336
02337
02338
02339
02340
02341 public override void disconnect()
02342 {
02343
02344 clearRunningThreads();
02345 base.disconnect();
02346 }
02347 private java.util.Vector threadList=null;
02348 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
02349 protected void addRunningThread(Thread thread)
02350 {
02351 if(threadList==null)threadList=new java.util.Vector();
02352 threadList.add(thread);
02353 }
02354 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
02355 protected void clearRunningThreads()
02356 {
02357 if(threadList==null)return;
02358 for(int t=0;t<threadList.size();t++)
02359 {
02360 Thread thread=(Thread)threadList.get(t);
02361 if(thread!=null)
02362 if(thread.isAlive())
02363 thread.interrupt();
02364 }
02365 threadList.clear();
02366 }
02367 private bool isPattern(String path)
02368 {
02369 return path.indexOf("*")!=-1 || path.indexOf("?")!=-1;
02370 }
02371 private bool isPattern(byte[] path)
02372 {
02373 int i=path.Length-1;
02374 while(i>=0)
02375 {
02376 if(path[i]=='*' || path[i]=='?')
02377 {
02378 if(i>0 && path[i-1]=='\\')
02379 {
02380 i--;
02381 }
02382 else
02383 {
02384 break;
02385 }
02386 }
02387 i--;
02388 }
02389
02390 return !(i<0);
02391 }
02392
02393 private int fill(byte[] buf, int s, int len)
02394 {
02395 int i=0;
02396 int foo=s;
02397 while(len>0)
02398 {
02399 i=io.ins.read(buf, s, len);
02400 if(i<=0)
02401 {
02402 throw new System.IO.IOException("inputstream is closed");
02403
02404 }
02405 s+=i;
02406 len-=i;
02407 }
02408 return s-foo;
02409 }
02410
02411
02412 private void skip(long foo)
02413 {
02414 while(foo>0)
02415 {
02416 long bar=io.ins.skip(foo);
02417 if(bar<=0)
02418 break;
02419 foo-=bar;
02420 }
02421 }
02422
02423 internal class Header
02424 {
02425 public int length;
02426 public int type;
02427 public int rid;
02428 }
02429 internal Header header(Buffer buf, Header header)
02430 {
02431 buf.rewind();
02432 int i=fill(buf.buffer, 0, 9);
02433 header.length=buf.getInt()-5;
02434 header.type=buf.getByte()&0xff;
02435 header.rid=buf.getInt();
02436 return header;
02437 }
02438
02439 private String remoteAbsolutePath(String path)
02440 {
02441 if(path.charAt(0)=='/') return path;
02442 if(cwd.endsWith("/")) return cwd+path;
02443 return cwd+"/"+path;
02444 }
02445
02446 private String localAbsolutePath(String path)
02447 {
02448 if(isLocalAbsolutePath(path)) return path;
02449 if(lcwd.endsWith(file_separator)) return lcwd+path;
02450 return lcwd+file_separator+path;
02451 }
02452
02453 public class LsEntry
02454 {
02455 private String filename;
02456 private String longname;
02457 private SftpATTRS attrs;
02458 internal LsEntry(String filename, String longname, SftpATTRS attrs)
02459 {
02460 setFilename(filename);
02461 setLongname(longname);
02462 setAttrs(attrs);
02463 }
02464 public String getFilename(){return filename;}
02465 void setFilename(String filename){this.filename = filename;}
02466 public String getLongname(){return longname;}
02467 void setLongname(String longname){this.longname = longname;}
02468 public SftpATTRS getAttrs(){return attrs;}
02469 void setAttrs(SftpATTRS attrs) {this.attrs = attrs;}
02470 public override string ToString(){return toString();}
02471 public String toString(){ return longname; }
02472 }
02473
02474 public class InputStreamGet : InputStream
02475 {
02476 ChannelSftp sftp;
02477 SftpProgressMonitor monitor;
02478 long offset=0;
02479 bool closed=false;
02480 int rest_length=0;
02481 byte[] _data=new byte[1];
02482 byte[] rest_byte=new byte[1024];
02483 byte[] handle;
02484 Header header=new Header();
02485
02486 public InputStreamGet(
02487 ChannelSftp sftp,
02488 byte[] handle,
02489 SftpProgressMonitor monitor)
02490 {
02491 this.sftp=sftp;
02492 this.handle=handle;
02493 this.monitor=monitor;
02494 }
02495
02496 public override int ReadByte()
02497 {
02498 if(closed)return -1;
02499 int i=read(_data, 0, 1);
02500 if (i==-1) { return -1; }
02501 else
02502 {
02503 return _data[0]&0xff;
02504 }
02505 }
02506 public int Read(byte[] d)
02507 {
02508 if(closed)return -1;
02509 return Read(d, 0, d.Length);
02510 }
02511 public override int Read(byte[] d, int s, int len)
02512 {
02513 if(closed)return -1;
02514 int i;
02515 int foo;
02516 if(d==null){throw new System.NullReferenceException();}
02517 if(s<0 || len <0 || s+len>d.Length)
02518 {
02519 throw new System.IndexOutOfRangeException();
02520 }
02521 if(len==0){ return 0; }
02522
02523 if(rest_length>0)
02524 {
02525 foo=rest_length;
02526 if(foo>len) foo=len;
02527 java.System.arraycopy(rest_byte, 0, d, s, foo);
02528 if(foo!=rest_length)
02529 {
02530 java.System.arraycopy(rest_byte, foo,
02531 rest_byte, 0, rest_length-foo);
02532 }
02533 if(monitor!=null)
02534 {
02535 if(!monitor.count(foo))
02536 {
02537 close();
02538 return -1;
02539 }
02540 }
02541
02542 rest_length-=foo;
02543 return foo;
02544 }
02545
02546 if(sftp.buf.buffer.Length-13<len)
02547 {
02548 len=sftp.buf.buffer.Length-13;
02549 }
02550 if(sftp.server_version==0 && len>1024)
02551 {
02552 len=1024;
02553 }
02554
02555 try{sftp.sendREAD(handle, offset, len);}
02556 catch(Exception e){ throw new System.IO.IOException("error"); }
02557
02558 header= sftp.header(sftp.buf, header);
02559 rest_length=header.length;
02560 int type=header.type;
02561 int id=header.rid;
02562
02563 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA)
02564 {
02565 throw new System.IO.IOException("error");
02566 }
02567 if(type==SSH_FXP_STATUS)
02568 {
02569 sftp.buf.rewind();
02570 sftp.fill(sftp.buf.buffer, 0, rest_length);
02571 i=sftp.buf.getInt();
02572 rest_length=0;
02573 if(i==SSH_FX_EOF)
02574 {
02575 close();
02576 return -1;
02577 }
02578
02579 throw new System.IO.IOException("error");
02580 }
02581 sftp.buf.rewind();
02582 sftp.fill(sftp.buf.buffer, 0, 4);
02583 i=sftp.buf.getInt(); rest_length-=4;
02584
02585 offset+=rest_length;
02586 foo=i;
02587 if(foo>0)
02588 {
02589 int bar=rest_length;
02590 if(bar>len)
02591 {
02592 bar=len;
02593 }
02594 i=sftp.io.ins.read(d, s, bar);
02595 if(i<0)
02596 {
02597 return -1;
02598 }
02599 rest_length-=i;
02600
02601 if(rest_length>0)
02602 {
02603 if(rest_byte.Length<rest_length)
02604 {
02605 rest_byte=new byte[rest_length];
02606 }
02607 int _s=0;
02608 int _len=rest_length;
02609 int j;
02610 while(_len>0)
02611 {
02612 j=sftp.io.ins.read(rest_byte, _s, _len);
02613 if(j<=0)break;
02614 _s+=j;
02615 _len-=j;
02616 }
02617 }
02618
02619 if(monitor!=null)
02620 {
02621 if(!monitor.count(i))
02622 {
02623 close();
02624 return -1;
02625 }
02626 }
02627 return i;
02628 }
02629 return 0;
02630 }
02631 public override void Close()
02632 {
02633 if(closed)return;
02634 closed=true;
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645 if(monitor!=null)monitor.end();
02646 try{sftp._sendCLOSE(handle, header);}
02647 catch(Exception e){throw new System.IO.IOException("error");}
02648 }
02649 }
02650 }
02651 }