⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssh2sftp.java

📁 一个非常好的ssh客户端实现
💻 JAVA
字号:
/****************************************************************************** * * Copyright (c) 1999-2003 AppGate Network Security AB. All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code as * defined in and that are subject to the MindTerm Public Source License, * Version 2.0, (the 'License'). You may not use this file except in compliance * with the License. *  * You should have received a copy of the MindTerm Public Source License * along with this software; see the file LICENSE.  If not, write to * AppGate Network Security AB, Otterhallegatan 2, SE-41118 Goteborg, SWEDEN * *****************************************************************************/package com.mindbright.ssh2;import java.io.InputStream;import java.io.OutputStream;import java.io.IOException;import java.util.Date;import java.text.SimpleDateFormat;/** * Describes the sftp protocol. */public class SSH2SFTP {    private static final int DATA_BUFFER_SIZE = 34000;    private static final int FAILSAFE_READ_BYTES = 1024;    /**     * Describes a file.     */    public static final class FileHandle {	private byte[]        handle;	private String        name;	private boolean       isDirectory;	private boolean       isOpen;	private boolean       asyncEOF;	private int           asyncCnt;	private int           reqLeft;	private SFTPException asyncException;	private AsyncListener listener;	protected volatile long lastOffset;	public FileHandle(String name, byte[] handle, boolean isDirectory) {	    this.name           = name;	    this.handle         = handle;	    this.isDirectory    = isDirectory;	    this.isOpen         = true;	    this.asyncCnt       = 0;	    this.reqLeft        = 0;	    this.asyncException = null;	    this.lastOffset     = 0L;	}	public boolean isDirectory() {	    return isDirectory;	}	public boolean isOpen() {	    return isOpen;	}	public String getName() {	    return name;	}	public byte[] getHandle() {	    return handle;	}	public void addAsyncListener(AsyncListener listener) {	    this.listener = listener;	}	protected synchronized void asyncStart(int len) {	    asyncCnt++;	}	protected synchronized void asyncEnd(int len) {	    asyncCnt--;	    if(asyncCnt <= reqLeft) {		this.notifyAll();	    }	    if(listener != null) {		listener.progress((long)len);	    }	}	protected synchronized void asyncReadEOF() {	    asyncEOF = true;	    asyncEnd(0);	}	protected synchronized void asyncException(SFTPException e) {	    asyncException = e;	    this.notifyAll();	}	public synchronized void asyncClose() {	    if(asyncCnt > 0) {		asyncException(new SFTPAsyncAbortException());	    }	    isOpen = false;	}	public synchronized boolean asyncWait() throws SFTPException {	    return asyncWait(0);	}	public synchronized boolean asyncWait(int reqLeft)	    throws SFTPException	{	    if(this.reqLeft < reqLeft) {		this.reqLeft = reqLeft;	    }	    while(asyncCnt > reqLeft && asyncException == null && !asyncEOF) {		try {		    this.wait();		} catch (InterruptedException e) {		}	    }	    if(asyncException != null) {		throw (SFTPException)asyncException.fillInStackTrace();	    }	    boolean eof = asyncEOF;	    asyncEOF    = false;	    return eof;	}    }    /**     * An interface implemented by FTP controllers which want progress reports.     */         public static interface AsyncListener {	/**	 * Gets called periodically during the file transfer.	 *	 * @param size How many bytes have been transferred so far	 */	public void progress(long size);    }    /**     * Class describing the different file attributes.     */    public static final class FileAttributes {	char[] types = { 'p', 'c', 'd', 'b', '-', 'l', 's', };	public final static int S_IFMT   = 0170000;	public final static int S_IFSOCK = 0140000;	public final static int S_IFLNK  = 0120000;	public final static int S_IFREG  = 0100000;	public final static int S_IFBLK  = 0060000;	public final static int S_IFDIR  = 0040000;	public final static int S_IFCHR  = 0020000;	public final static int S_IFIFO  = 0010000;	public final static int S_ISUID = 0004000;	public final static int S_ISGID = 0002000;	public final static int S_IRUSR = 00400;	public final static int S_IWUSR = 00200;	public final static int S_IXUSR = 00100;	public final static int S_IRGRP = 00040;	public final static int S_IWGRP = 00020;	public final static int S_IXGRP = 00010;	public final static int S_IROTH = 00004;	public final static int S_IWOTH = 00002;	public final static int S_IXOTH = 00001;	public boolean hasName;	public boolean hasSize;	public boolean hasUserGroup;	public boolean hasPermissions;	public boolean hasModTime;	public String  name;	public String  lname;	public long    size;	public int     uid;	public int     gid;	public int     permissions;	public int     atime;	public int     mtime;	public String toString() {	    return toString(hasName ? name : "<noname>");	}        private static String rightJustify(String s, int width) {            String res = s;            while (res.length() < width)                res = " " + res;            return res;        }        	public String toString(String name) {	    StringBuffer str = new StringBuffer();	    str.append(permString());	    str.append("    1 ");	    str.append(rightJustify(Integer.toString(uid), 8));	    str.append(" ");	    str.append(rightJustify(Integer.toString(gid), 8));	    str.append(" ");	    str.append(rightJustify(Long.toString(size), 16));	    str.append(" ");	    str.append(modTimeString());	    str.append(" ");	    str.append(name);	    return str.toString();	}	public String permString() {	    StringBuffer str = new StringBuffer();	    str.append(types[(permissions & S_IFMT) >>> 13]);	    str.append(rwxString(permissions, 6));	    str.append(rwxString(permissions, 3));	    str.append(rwxString(permissions, 0));	    return str.toString();	}	public String modTimeString() {	    SimpleDateFormat df;	    long mt  = (mtime * 1000L);	    long now = System.currentTimeMillis();	    if((now - mt) > (6 * 30 * 24 * 60 * 60 * 1000L)) {		df = new SimpleDateFormat("MMM dd  yyyy");	    } else {		df = new SimpleDateFormat("MMM dd hh:mm");	    }	    return df.format(new Date(mt));	}	private String rwxString(int v, int r) {	    v >>>= r;	    String rwx = ((((v & 0x04) != 0) ? "r" : "-") +			  (((v & 0x02) != 0) ? "w" : "-"));	    if((r == 6 && isSUID()) ||	       (r == 3 && isSGID())) {		rwx += (((v & 0x01) != 0) ? "s" : "S");	    } else {		rwx += (((v & 0x01) != 0) ? "x" : "-");	    }	    return rwx;	}	public boolean isSocket() {	    return ((permissions & S_IFSOCK) == S_IFSOCK);	}	public boolean isLink() {	    return ((permissions & S_IFLNK) == S_IFLNK);	}	public boolean isFile() {	    return ((permissions & S_IFREG) == S_IFREG);	}	public boolean isBlock() {	    return ((permissions & S_IFBLK) == S_IFBLK);	}	public boolean isDirectory() {	    return ((permissions & S_IFDIR) == S_IFDIR);	}	public boolean isCharacter() {	    return ((permissions & S_IFCHR) == S_IFCHR);	}	public boolean isFifo() {	    return ((permissions & S_IFIFO) == S_IFIFO);	}	public boolean isSUID() {	    return ((permissions & S_ISUID) == S_ISUID);	}	public boolean isSGID() {	    return ((permissions & S_ISGID) == S_ISGID);	}    }    public static class SFTPException extends Exception {	public SFTPException() {	}	public SFTPException(String msg) {	    super(msg);	}    }    public static class SFTPEOFException extends SFTPException {    }    public static class SFTPNoSuchFileException extends SFTPException {    }    public static class SFTPPermissionDeniedException extends SFTPException {    }    public static class SFTPDisconnectException extends SFTPException {    }    public static class SFTPAsyncAbortException extends SFTPException {    }    /**     * Handles sftp data packets. Contains functions to read and write     * the sftp types.     */    protected static final class SFTPPacket extends SSH2DataBuffer {	private int type;	private int id;	private int len;	public SFTPPacket() {	    super(DATA_BUFFER_SIZE);	}	public void reset(int type, int id) {	    reset();	    writeInt(0); // dummy length	    writeByte(type);	    writeInt(id);	    this.type = type;	    this.id   = id;	}	public int getType() {	    return type;	}	public int getId() {	    return id;	}	public int getLength() {	    return len;	}	public void writeLong(long l) {	    writeInt((int)((l >>> 32) & 0xffffffffL));	    writeInt((int)(l & 0xffffffff));	}	public long readLong() {	    long h = (long)readInt();	    long l = (long)readInt();	    if(h < 0)		h += 0xffffffffL;	    if(l < 0)		l += 0xffffffffL;	    return (h << 32) | (l & 0xffffffff);	}	public void writeAttrs(FileAttributes attrs) {	    writeInt((attrs.hasSize ? SSH_ATTR_SIZE : 0) |		     (attrs.hasUserGroup ? SSH_ATTR_UIDGID : 0) |		     (attrs.hasPermissions ? SSH_ATTR_PERM : 0) |		     (attrs.hasModTime ? SSH_ATTR_MODTIME : 0));	    if(attrs.hasSize) {		writeLong(attrs.size);	    }	    if(attrs.hasUserGroup) {		writeInt(attrs.uid);		writeInt(attrs.gid);	    }	    if(attrs.hasPermissions) {		writeInt(attrs.permissions);	    }	    if(attrs.hasModTime) {		writeInt(attrs.atime);		writeInt(attrs.mtime);	    }	}	public FileAttributes readAttrs() {	    FileAttributes attrs = new FileAttributes();	    int            flags = readInt();	    attrs.hasSize        = ((flags & SSH_ATTR_SIZE) != 0);	    attrs.hasUserGroup   = ((flags & SSH_ATTR_UIDGID) != 0);	    attrs.hasPermissions = ((flags & SSH_ATTR_PERM) != 0);	    attrs.hasModTime     = ((flags & SSH_ATTR_MODTIME) != 0);	    if (attrs.hasSize) {		attrs.size = readLong();	    }	    if (attrs.hasUserGroup) {		attrs.uid = readInt();		attrs.gid = readInt();	    }	    if (attrs.hasPermissions) {		attrs.permissions = readInt();	    }	    if (attrs.hasModTime) {		attrs.atime = readInt();		attrs.mtime = readInt();	    }	    return attrs;	}	private void internalReadFrom(int cnt, InputStream in)	    throws SFTPException	{	    len = 5;	    try {		while(cnt < len) {		    int n;		    n = in.read(data, cnt, (len - cnt));		    if(n == -1) {			throw new SFTPDisconnectException();		    }		    cnt += n;		    if(cnt == 5) {			len  = readInt() + 4;			type = readByte();		    }		}	    } catch (IOException e) {		throw new SFTPException(e.getMessage());	    }	    len -= 5;	}	/**	 * Failsafe read method. Tries to read a packet from the given stream.	 * but does ignore stuff which does not look like a packet. The	 * algorithm is that a probable packet starts with two bytes containing	 * zeros. 	 * <p>	 * This is useful when reading the first version packet which is	 * small but may be, on broken systems, preceded by some ascii	 * characters.	 *	 * @param in Stream to read data from	 */	public void failsafeReadFrom(InputStream in) 	    throws SFTPException	{	    byte[] b = new byte[2];	    	    try {		if (2 != in.read(b, 0, 2)) {		    throw new SFTPDisconnectException();		}		for (int tries = 0; tries < FAILSAFE_READ_BYTES; tries++) {		    if (b[0] == 0 && b[1] == 0) {			data[0] = b[0];			data[1] = b[1];			internalReadFrom(2, in);			return;		    }		    b[0] = b[1];		    if (1 != in.read(b, 1, 1)) {			throw new SFTPDisconnectException();		    }		}	    } catch (IOException e) {		throw new SFTPException(e.getMessage());	    }	    throw new SFTPException("Failed to find first packet");	}	public void readFrom(InputStream in)	    throws SFTPException	{	    internalReadFrom(0, in);	}	public void writeTo(OutputStream out)	    throws SFTPException	{	    len = getWPos() - 5;	    setWPos(0);	    writeInt(len + 1);	    try {		out.write(data, 0, len + 5);	    } catch (IOException e) {		throw new SFTPException(e.getMessage());	    }	}    }    /* Version is 3 according to draft minus extension in init */    protected final static int SSH_FILEXFER_VERSION =    2;    /* Packet types. */    protected final static int SSH_FXP_INIT =            1;    protected final static int SSH_FXP_VERSION =         2;    protected final static int SSH_FXP_OPEN =            3;    protected final static int SSH_FXP_CLOSE =           4;    protected final static int SSH_FXP_READ =            5;    protected final static int SSH_FXP_WRITE =           6;    protected final static int SSH_FXP_LSTAT =           7;    protected final static int SSH_FXP_FSTAT =           8;    protected final static int SSH_FXP_SETSTAT =         9;    protected final static int SSH_FXP_FSETSTAT =       10;    protected final static int SSH_FXP_OPENDIR =        11;    protected final static int SSH_FXP_READDIR =        12;    protected final static int SSH_FXP_REMOVE =         13;    protected final static int SSH_FXP_MKDIR =          14;    protected final static int SSH_FXP_RMDIR =          15;    protected final static int SSH_FXP_REALPATH =       16;    protected final static int SSH_FXP_STAT =           17;    protected final static int SSH_FXP_RENAME =         18;    protected final static int SSH_FXP_STATUS =         101;    protected final static int SSH_FXP_HANDLE =         102;    protected final static int SSH_FXP_DATA =           103;    protected final static int SSH_FXP_NAME =           104;    protected final static int SSH_FXP_ATTRS =          105;    protected final static int SSH_FXP_EXTENDED =       200;    protected final static int SSH_FXP_EXTENDED_REPLY = 201;    /* Status/error codes. */    public final static int SSH_FX_OK =                0;    public final static int SSH_FX_EOF =               1;    public final static int SSH_FX_NO_SUCH_FILE =      2;    public final static int SSH_FX_PERMISSION_DENIED = 3;    public final static int SSH_FX_FAILURE =           4;    public final static int SSH_FX_BAD_MESSAGE =       5;    public final static int SSH_FX_NO_CONNECTION =     6;    public final static int SSH_FX_CONNECTION_LOST =   7;    public final static int SSH_FX_OP_UNSUPPORTED =    8;    /* Portable versions of O_RDONLY etc. */    public final static int SSH_FXF_READ =            0x0001;    public final static int SSH_FXF_WRITE =           0x0002;    public final static int SSH_FXF_APPEND =          0x0004;    public final static int SSH_FXF_CREAT =           0x0008;    public final static int SSH_FXF_TRUNC =           0x0010;    public final static int SSH_FXF_EXCL =            0x0020;    /* Flags indicating presence of file attributes. */    protected final static int SSH_ATTR_SIZE =         0x01;    protected final static int SSH_ATTR_UIDGID =       0x02;    protected final static int SSH_ATTR_PERM =         0x04;    protected final static int SSH_ATTR_MODTIME =      0x08;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -