1 2 package ch.ethz.ssh2; 3 4 import java.io.BufferedOutputStream ; 5 import java.io.IOException ; 6 import java.io.InputStream ; 7 import java.io.OutputStream ; 8 import java.io.PrintStream ; 9 import java.nio.charset.Charset ; 10 import java.util.HashMap ; 11 import java.util.Vector ; 12 13 import ch.ethz.ssh2.packets.TypesReader; 14 import ch.ethz.ssh2.packets.TypesWriter; 15 import ch.ethz.ssh2.sftp.AttribFlags; 16 import ch.ethz.ssh2.sftp.ErrorCodes; 17 import ch.ethz.ssh2.sftp.Packet; 18 19 60 public class SFTPv3Client 61 { 62 final Connection conn; 63 final Session sess; 64 final PrintStream debug; 65 66 boolean flag_closed = false; 67 68 InputStream is; 69 OutputStream os; 70 71 int protocol_version = 0; 72 HashMap server_extensions = new HashMap (); 73 74 int next_request_id = 1000; 75 76 String charsetName = null; 77 78 88 public SFTPv3Client(Connection conn, PrintStream debug) throws IOException 89 { 90 if (conn == null) 91 throw new IllegalArgumentException ("Cannot accept null argument!"); 92 93 this.conn = conn; 94 this.debug = debug; 95 96 if (debug != null) 97 debug.println("Opening session and starting SFTP subsystem."); 98 99 sess = conn.openSession(); 100 sess.startSubSystem("sftp"); 101 102 is = sess.getStdout(); 103 os = new BufferedOutputStream (sess.getStdin(), 2048); 104 105 if ((is == null) || (os == null)) 106 throw new IOException ("There is a problem with the streams of the underlying channel."); 107 108 init(); 109 } 110 111 117 public SFTPv3Client(Connection conn) throws IOException 118 { 119 this(conn, null); 120 } 121 122 141 public void setCharset(String charset) throws IOException 142 { 143 if (charset == null) 144 { 145 charsetName = charset; 146 return; 147 } 148 149 try 150 { 151 Charset.forName(charset); 152 } 153 catch (Exception e) 154 { 155 throw (IOException ) new IOException ("This charset is not supported").initCause(e); 156 } 157 charsetName = charset; 158 } 159 160 167 public String getCharset() 168 { 169 return charsetName; 170 } 171 172 private final void checkHandleValidAndOpen(SFTPv3FileHandle handle) throws IOException 173 { 174 if (handle.client != this) 175 throw new IOException ("The file handle was created with another SFTPv3FileHandle instance."); 176 177 if (handle.isClosed == true) 178 throw new IOException ("The file handle is closed."); 179 } 180 181 private final void sendMessage(int type, int requestId, byte[] msg, int off, int len) throws IOException 182 { 183 int msglen = len + 1; 184 185 if (type != Packet.SSH_FXP_INIT) 186 msglen += 4; 187 188 os.write(msglen >> 24); 189 os.write(msglen >> 16); 190 os.write(msglen >> 8); 191 os.write(msglen); 192 os.write(type); 193 194 if (type != Packet.SSH_FXP_INIT) 195 { 196 os.write(requestId >> 24); 197 os.write(requestId >> 16); 198 os.write(requestId >> 8); 199 os.write(requestId); 200 } 201 202 os.write(msg, off, len); 203 os.flush(); 204 } 205 206 private final void sendMessage(int type, int requestId, byte[] msg) throws IOException 207 { 208 sendMessage(type, requestId, msg, 0, msg.length); 209 } 210 211 private final void readBytes(byte[] buff, int pos, int len) throws IOException 212 { 213 while (len > 0) 214 { 215 int count = is.read(buff, pos, len); 216 if (count < 0) 217 throw new IOException ("Unexpected end of sftp stream."); 218 if ((count == 0) || (count > len)) 219 throw new IOException ("Underlying stream implementation is bogus!"); 220 len -= count; 221 pos += count; 222 } 223 } 224 225 236 private final byte[] receiveMessage(int maxlen) throws IOException 237 { 238 byte[] msglen = new byte[4]; 239 240 readBytes(msglen, 0, 4); 241 242 int len = (((msglen[0] & 0xff) << 24) | ((msglen[1] & 0xff) << 16) | ((msglen[2] & 0xff) << 8) | (msglen[3] & 0xff)); 243 244 if ((len > maxlen) || (len <= 0)) 245 throw new IOException ("Illegal sftp packet len: " + len); 246 247 byte[] msg = new byte[len]; 248 249 readBytes(msg, 0, len); 250 251 return msg; 252 } 253 254 private final int generateNextRequestID() 255 { 256 synchronized (this) 257 { 258 return next_request_id++; 259 } 260 } 261 262 private final void closeHandle(byte[] handle) throws IOException 263 { 264 int req_id = generateNextRequestID(); 265 266 TypesWriter tw = new TypesWriter(); 267 tw.writeString(handle, 0, handle.length); 268 269 sendMessage(Packet.SSH_FXP_CLOSE, req_id, tw.getBytes()); 270 271 expectStatusOKMessage(req_id); 272 } 273 274 private SFTPv3FileAttributes readAttrs(TypesReader tr) throws IOException 275 { 276 290 291 SFTPv3FileAttributes fa = new SFTPv3FileAttributes(); 292 293 int flags = tr.readUINT32(); 294 295 if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) 296 { 297 if (debug != null) 298 debug.println("SSH_FILEXFER_ATTR_SIZE"); 299 fa.size = new Long (tr.readUINT64()); 300 } 301 302 if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID) != 0) 303 { 304 if (debug != null) 305 debug.println("SSH_FILEXFER_ATTR_V3_UIDGID"); 306 fa.uid = new Integer (tr.readUINT32()); 307 fa.gid = new Integer (tr.readUINT32()); 308 } 309 310 if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) 311 { 312 if (debug != null) 313 debug.println("SSH_FILEXFER_ATTR_PERMISSIONS"); 314 fa.permissions = new
|