All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.schoolwow.ssh.layer.channel.SFTPChannel Maven / Gradle / Ivy

package cn.schoolwow.ssh.layer.channel;

import cn.schoolwow.ssh.domain.SSHMessageCode;
import cn.schoolwow.ssh.domain.exception.SFTPException;
import cn.schoolwow.ssh.domain.sftp.*;
import cn.schoolwow.ssh.domain.stream.SSHString;
import cn.schoolwow.ssh.layer.SSHSession;
import cn.schoolwow.ssh.stream.SSHInputStream;
import cn.schoolwow.ssh.stream.SSHInputStreamImpl;
import cn.schoolwow.ssh.util.SSHUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SFTPChannel extends AbstractChannel {
    private Logger logger = LoggerFactory.getLogger(SFTPChannel.class);

    private volatile int fxpId = 0;

    public SFTPChannel(SSHSession sshSession) throws IOException {
        super(sshSession);
        openSessionChannel();
        sos.reset();
        sos.writeByte(SSHMessageCode.SSH_MSG_CHANNEL_REQUEST.value);
        sos.writeInt(recipientChannel);
        sos.writeSSHString(new SSHString("subsystem"));
        sos.writeBoolean(true);
        sos.writeSSHString(new SSHString("sftp"));
        sshSession.writeSSHProtocolPayload(sos.toByteArray());
        checkChannelRequestWantReply();

        //获取SFTP协议版本号
        sos.reset();
        sos.writeInt(5);
        sos.writeByte(FXPCode.SSH_FXP_INIT.value);
        sos.writeInt(3);
        logger.debug("[发送SFTP协议客户端版本号]{}",3);
        writeChannelData(sos.toByteArray());
        byte[] data = readChannelData().value;
        if(data[4]!=FXPCode.SSH_FXP_VERSION.value){
            throw new SFTPException("SFTP协议初始化失败!预期类型值:"+FXPCode.SSH_FXP_VERSION.value+",实际类型值:"+data[4]);
        }
        int version = SSHUtil.byteArray2Int(data,5,4);
        logger.debug("[接收SFTP协议服务端版本号]{}",version);
    }

    /**
     * 获取文件信息
     * @param path 文件路径
     * */
    public SFTPFileAttribute getSFTPFileAttribute(String path) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        writeFXP(FXPCode.SSH_FXP_STAT);
        SFTPFileAttribute sftpFileAttribute = handleSSH_FXP_ATTRS();
        return sftpFileAttribute;
    }

    /**
     * 设置文件属性
     * @param path 文件路径
     * @param sftpFileAttribute 文件属性(根据flag掩码设置属性,具体参阅draft-ietf-secsh-filexfer-01.txt第5章节)
     * */
    public void setSFTPFileAttribute(String path, SFTPFileAttribute sftpFileAttribute) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        if((sftpFileAttribute.flags&FILEXFERCode.SSH_FILEXFER_ATTR_SIZE.value)!=0){
            sos.writeLong(sftpFileAttribute.size);
        }
        if((sftpFileAttribute.flags&FILEXFERCode.SSH_FILEXFER_ATTR_UIDGID.value)!=0){
            sos.writeInt(sftpFileAttribute.uid);
            sos.writeInt(sftpFileAttribute.gid);
        }
        if((sftpFileAttribute.flags&FILEXFERCode.SSH_FILEXFER_ATTR_PERMISSIONS.value)!=0){
            sos.writeInt(sftpFileAttribute.permissions);
        }
        if((sftpFileAttribute.flags&FILEXFERCode.SSH_FILEXFER_ATTR_ACMODTIME.value)!=0){
            sos.writeInt(sftpFileAttribute.atime);
            sos.writeInt(sftpFileAttribute.mtime);
        }
        writeFXP(FXPCode.SSH_FXP_SETSTAT);
        readFXP(FXPCode.SSH_FXP_STATUS);
    }

    /**
     * 读取文件
     * @param path 文件路径
     * */
    public byte[] readFile(String path) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        sos.writeInt(FXFCode.SSH_FXF_READ.value);
        sos.writeInt(0);
        writeFXP(FXPCode.SSH_FXP_OPEN);
        SSHString handle = handleSSH_FXP_HANDLE();
        try {
            sos.reset();
            sos.writeSSHString(handle);
            writeFXP(FXPCode.SSH_FXP_FSTAT);
            SFTPFileAttribute sftpFileAttribute = handleSSH_FXP_ATTRS();
            sos.reset();
            sos.writeSSHString(handle);
            sos.writeLong(0);
            sos.writeInt((int) sftpFileAttribute.size);
            writeFXP(FXPCode.SSH_FXP_READ);
            SSHString data = handleSSH_FXP_DATA();
            return data.value;
        }catch (IOException e){
            throw e;
        }finally {
            closeHandle(handle);
        }
    }

    /**
     * 读取文件
     * @param path 文件路径
     * @param offset 文件偏移
     * @param len 读取长度
     * */
    public byte[] readFile(String path, long offset, int len) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        sos.writeInt(FXFCode.SSH_FXF_READ.value);
        sos.writeInt(0);
        writeFXP(FXPCode.SSH_FXP_OPEN);
        SSHString handle = handleSSH_FXP_HANDLE();
        try {
            sos.reset();
            sos.writeSSHString(handle);
            sos.writeLong(offset);
            sos.writeInt(len);
            writeFXP(FXPCode.SSH_FXP_READ);
            SSHString data = handleSSH_FXP_DATA();
            return data.value;
        }catch (IOException e){
            throw e;
        }finally {
            closeHandle(handle);
        }
    }

    /**
     * 写入文件
     * @param path 文件路径
     * @param data 写入数据
     * @return 返回状态码
     * */
    public void writeFile(String path, byte[] data) throws IOException {
        writeFile(path,0,data);
    }

    /**
     * 写入文件
     * @param path 文件路径
     * @param offset 文件偏移
     * @param data 写入数据
     * @return 返回状态码
     * */
    public void writeFile(String path, long offset, byte[] data) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        sos.writeInt(FXFCode.SSH_FXF_CREAT.value|FXFCode.SSH_FXF_WRITE.value);
        sos.writeInt(FILEXFERCode.SSH_FILEXFER_ATTR_SIZE.value);
        sos.writeLong(data.length);
        writeFXP(FXPCode.SSH_FXP_OPEN);
        SSHString handle = handleSSH_FXP_HANDLE();
        try {
            sos.reset();
            sos.writeSSHString(handle);
            sos.writeLong(offset);
            sos.writeSSHString(new SSHString(data));
            writeFXP(FXPCode.SSH_FXP_WRITE);
            readFXP(FXPCode.SSH_FXP_STATUS);
        }catch (IOException e){
            throw e;
        }finally {
            closeHandle(handle);
        }
    }

    /**
     * 追加文件
     * @param path 文件路径
     * @param data 追加数据
     * @return 返回状态码
     * */
    public void appendFile(String path, byte[] data) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        sos.writeInt(FXFCode.SSH_FXF_WRITE.value|FXFCode.SSH_FXF_CREAT.value);
        sos.writeInt(0);
        writeFXP(FXPCode.SSH_FXP_OPEN);
        SSHString handle = handleSSH_FXP_HANDLE();
        try {
            sos.reset();
            sos.writeSSHString(handle);
            writeFXP(FXPCode.SSH_FXP_FSTAT);
            SFTPFileAttribute sftpFileAttribute = handleSSH_FXP_ATTRS();
            sos.reset();
            sos.writeSSHString(handle);
            sos.writeLong(sftpFileAttribute.size);
            sos.writeSSHString(new SSHString(data));
            writeFXP(FXPCode.SSH_FXP_WRITE);
            readFXP(FXPCode.SSH_FXP_STATUS);
        }catch (IOException e){
            throw e;
        }finally {
            closeHandle(handle);
        }
    }

    /**
     * 删除文件
     * @param path 文件路径
     * @return 返回状态码
     * */
    public void deleteFile(String path) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        writeFXP(FXPCode.SSH_FXP_REMOVE);
        readFXP(FXPCode.SSH_FXP_STATUS);
    }

    /**
     * 重命名文件(文件夹)
     * @param oldPath 原文件路径
     * @param newPath 新文件路径
     * @return 返回状态码
     * */
    public void rename(String oldPath, String newPath) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(oldPath));
        sos.writeSSHString(new SSHString(newPath));
        writeFXP(FXPCode.SSH_FXP_RENAME);
        readFXP(FXPCode.SSH_FXP_STATUS);
    }

    /**
     * 创建文件夹
     * @param path 文件夹路径
     * @return 返回状态码
     * */
    public void createDirectory(String path) throws IOException {
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        sos.writeInt(0);
        writeFXP(FXPCode.SSH_FXP_MKDIR);
        readFXP(FXPCode.SSH_FXP_STATUS);
    }

    /**
     * 扫描文件夹
     * @param path 文件夹路径
     * */
    public List scanDirectory(String path) throws IOException{
        sos.reset();
        sos.writeSSHString(new SSHString(path));
        writeFXP(FXPCode.SSH_FXP_OPENDIR);
        SSHString handle = handleSSH_FXP_HANDLE();
        sos.reset();
        sos.writeSSHString(handle);
        writeFXP(FXPCode.SSH_FXP_READDIR);
        List sftpFileList = handleSSH_FXP_NAME();
        closeHandle(handle);
        return sftpFileList;
    }

    /**
     * 删除文件夹
     * 

以下情况会导致删除文件夹失败

*
    *
  • 文件夹路径不存在
  • *
  • 文件夹非空
  • *
  • 指定路径为文件
  • *
* @param path 文件夹路径 * @return 返回状态码 * */ public void deleteDirectory(String path) throws IOException { sos.reset(); sos.writeSSHString(new SSHString(path)); sos.writeInt(0); writeFXP(FXPCode.SSH_FXP_RMDIR); readFXP(FXPCode.SSH_FXP_STATUS); } /** * 读取符号连接 * @param symbolicLinkPath 符号链接路径 * @return 符号链接实际路径 * */ public String readSymbolicLinkPath(String symbolicLinkPath) throws IOException { sos.reset(); sos.writeSSHString(new SSHString(symbolicLinkPath)); writeFXP(FXPCode.SSH_FXP_READLINK); List sftpFileList = handleSSH_FXP_NAME(); if(sftpFileList.isEmpty()){ return null; } return sftpFileList.get(0).fileName; } /** * 创建符号连接 * @param symbolicLinkPath 符号链接路径 * @param targetPath 符号链接指向路径 * @return 符号链接实际路径 * */ public void createSymbolicLinkPath(String symbolicLinkPath, String targetPath) throws IOException { sos.reset(); sos.writeSSHString(new SSHString(symbolicLinkPath)); sos.writeSSHString(new SSHString(targetPath)); writeFXP(FXPCode.SSH_FXP_SYMLINK); readFXP(FXPCode.SSH_FXP_STATUS); } /** * 获取真实路径(例如输入..,返回上级目录) * @param path 文件路径 * */ public String canonicalize(String path) throws IOException { sos.reset(); sos.writeSSHString(new SSHString(path)); writeFXP(FXPCode.SSH_FXP_REALPATH); List sftpFileList = handleSSH_FXP_NAME(); if(sftpFileList.isEmpty()){ return null; } return sftpFileList.get(0).fileName; } /**处理SSH_FXP_HANDLE响应*/ private SSHString handleSSH_FXP_HANDLE() throws IOException { SSHInputStream sis = readFXP(FXPCode.SSH_FXP_HANDLE); return sis.readSSHString(); } /**处理SSH_FXP_HANDLE响应*/ private SSHString handleSSH_FXP_DATA() throws IOException { SSHInputStream sis = readFXP(FXPCode.SSH_FXP_DATA); return sis.readSSHString(); } /**处理handleSSH_FXP_NAME响应*/ private List handleSSH_FXP_NAME() throws IOException { SSHInputStream sis = readFXP(FXPCode.SSH_FXP_NAME); int count = sis.readInt(); List sftpFileList = new ArrayList<>(count); for(int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy