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

com.feilong.lib.net.ftp.FTPSClient Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.feilong.lib.net.ftp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import com.feilong.lib.net.util.Base64;
import com.feilong.lib.net.util.SSLContextUtils;
import com.feilong.lib.net.util.SSLSocketUtils;
import com.feilong.lib.net.util.TrustManagerUtils;

/**
 * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to
 * see wire-level SSL details.
 *
 * Warning: the hostname is not verified against the certificate by default, use
 * {@link #setHostnameVerifier(HostnameVerifier)} or {@link #setEndpointCheckingEnabled(boolean)}
 * (on Java 1.7+) to enable verification. Verification is only performed on client mode connections.
 * 
 * @version $Id$
 * @since 2.0
 */
public class FTPSClient extends FTPClient{

    // From http://www.iana.org/assignments/port-numbers

    //    ftps-data   989/tcp    ftp protocol, data, over TLS/SSL
    //    ftps-data   989/udp    ftp protocol, data, over TLS/SSL
    //    ftps        990/tcp    ftp protocol, control, over TLS/SSL
    //    ftps        990/udp    ftp protocol, control, over TLS/SSL

    public static final int       DEFAULT_FTPS_DATA_PORT = 989;

    public static final int       DEFAULT_FTPS_PORT      = 990;

    /** The value that I can set in PROT command (C = Clear, P = Protected) */
    private static final String[] PROT_COMMAND_VALUE     = { "C", "E", "S", "P" };

    /** Default PROT Command */
    private static final String   DEFAULT_PROT           = "C";

    /** Default secure socket protocol name, i.e. TLS */
    private static final String   DEFAULT_PROTOCOL       = "TLS";

    /** The AUTH (Authentication/Security Mechanism) command. */
    private static final String   CMD_AUTH               = "AUTH";

    /** The ADAT (Authentication/Security Data) command. */
    private static final String   CMD_ADAT               = "ADAT";

    /** The PROT (Data Channel Protection Level) command. */
    private static final String   CMD_PROT               = "PROT";

    /** The PBSZ (Protection Buffer Size) command. */
    private static final String   CMD_PBSZ               = "PBSZ";

    /** The MIC (Integrity Protected Command) command. */
    private static final String   CMD_MIC                = "MIC";

    /** The CONF (Confidentiality Protected Command) command. */
    private static final String   CMD_CONF               = "CONF";

    /** The ENC (Privacy Protected Command) command. */
    private static final String   CMD_ENC                = "ENC";

    /** The CCC (Clear Command Channel) command. */
    private static final String   CMD_CCC                = "CCC";

    /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
    private final boolean         isImplicit;

    /** The secure socket protocol to be used, e.g. SSL/TLS. */
    private final String          protocol;

    /** The AUTH Command value */
    private String                auth                   = DEFAULT_PROTOCOL;

    /** The context object. */
    private SSLContext            context;

    /** The socket object. */
    private Socket                plainSocket;

    /** Controls whether a new SSL session may be established by this socket. Default true. */
    private boolean               isCreation             = true;

    /** The use client mode flag. */
    private boolean               isClientMode           = true;

    /** The need client auth flag. */
    private boolean               isNeedClientAuth       = false;

    /** The want client auth flag. */
    private boolean               isWantClientAuth       = false;

    /** The cipher suites */
    private String[]              suites                 = null;

    /** The protocol versions */
    private String[]              protocols              = null;

    /**
     * The FTPS {@link TrustManager} implementation, default validate only
     * {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}.
     */
    private TrustManager          trustManager           = TrustManagerUtils.getValidateServerCertificateTrustManager();

    /** The {@link KeyManager}, default null (i.e. use system default). */
    private KeyManager            keyManager             = null;

    /** The {@link HostnameVerifier} to use post-TLS, default null (i.e. no verification). */
    private HostnameVerifier      hostnameVerifier       = null;

    /** Use Java 1.7+ HTTPS Endpoint Identification Algorithim. */
    private boolean               tlsEndpointChecking;

    /**
     * Constructor for FTPSClient, calls {@link #FTPSClient(String, boolean)}.
     *
     * Sets protocol to {@link #DEFAULT_PROTOCOL} - i.e. TLS - and security mode to explicit (isImplicit = false)
     */
    public FTPSClient(){
        this(DEFAULT_PROTOCOL, false);
    }

    /**
     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS
     * Calls {@link #FTPSClient(String, boolean)}
     * 
     * @param isImplicit
     *            The security mode (Implicit/Explicit).
     */
    public FTPSClient(boolean isImplicit){
        this(DEFAULT_PROTOCOL, isImplicit);
    }

    /**
     * Constructor for FTPSClient, using explict mode, calls {@link #FTPSClient(String, boolean)}.
     *
     * @param protocol
     *            the protocol to use
     */
    public FTPSClient(String protocol){
        this(protocol, false);
    }

    /**
     * Constructor for FTPSClient allowing specification of protocol
     * and security mode. If isImplicit is true, the port is set to
     * {@link #DEFAULT_FTPS_PORT} i.e. 990.
     * The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
     * 
     * @param protocol
     *            the protocol
     * @param isImplicit
     *            The security mode(Implicit/Explicit).
     */
    public FTPSClient(String protocol, boolean isImplicit){
        super();
        this.protocol = protocol;
        this.isImplicit = isImplicit;
        if (isImplicit){
            setDefaultPort(DEFAULT_FTPS_PORT);
        }
    }

    /**
     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS
     * The default TrustManager is set from {@link TrustManagerUtils#getValidateServerCertificateTrustManager()}
     * 
     * @param isImplicit
     *            The security mode(Implicit/Explicit).
     * @param context
     *            A pre-configured SSL Context
     */
    public FTPSClient(boolean isImplicit, SSLContext context){
        this(DEFAULT_PROTOCOL, isImplicit);
        this.context = context;
    }

    /**
     * Constructor for FTPSClient, using {@link #DEFAULT_PROTOCOL} - i.e. TLS
     * and isImplicit {@code false}
     * Calls {@link #FTPSClient(boolean, SSLContext)}
     * 
     * @param context
     *            A pre-configured SSL Context
     */
    public FTPSClient(SSLContext context){
        this(false, context);
    }

    /**
     * Set AUTH command use value.
     * This processing is done before connected processing.
     * 
     * @param auth
     *            AUTH command use value.
     */
    public void setAuthValue(String auth){
        this.auth = auth;
    }

    /**
     * Return AUTH command use value.
     * 
     * @return AUTH command use value.
     */
    public String getAuthValue(){
        return this.auth;
    }

    /**
     * Because there are so many connect() methods,
     * the _connectAction_() method is provided as a means of performing
     * some action immediately after establishing a connection,
     * rather than reimplementing all of the connect() methods.
     * 
     * @throws IOException
     *             If it throw by _connectAction_.
     * @see com.feilong.lib.net.SocketClient#_connectAction_()
     */
    @Override
    protected void _connectAction_() throws IOException{
        // Implicit mode.
        if (isImplicit){
            sslNegotiation();
        }
        super._connectAction_();
        // Explicit mode.
        if (!isImplicit){
            execAUTH();
            sslNegotiation();
        }
    }

    /**
     * AUTH command.
     * 
     * @throws SSLException
     *             If it server reply code not equal "234" and "334".
     * @throws IOException
     *             If an I/O error occurs while either sending
     *             the command.
     */
    protected void execAUTH() throws SSLException,IOException{
        int replyCode = sendCommand(CMD_AUTH, auth);
        if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode){
            // replyCode = 334
            // I carry out an ADAT command.
        }else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode){
            throw new SSLException(getReplyString());
        }
    }

    /**
     * Performs a lazy init of the SSL context
     * 
     * @throws IOException
     */
    private void initSslContext() throws IOException{
        if (context == null){
            context = SSLContextUtils.createSSLContext(protocol, getKeyManager(), getTrustManager());
        }
    }

    /**
     * SSL/TLS negotiation. Acquires an SSL socket of a control
     * connection and carries out handshake processing.
     * 
     * @throws IOException
     *             If server negotiation fails
     */
    protected void sslNegotiation() throws IOException{
        plainSocket = _socket_;
        initSslContext();

        SSLSocketFactory ssf = context.getSocketFactory();
        String host = (_hostname_ != null) ? _hostname_ : getRemoteAddress().getHostAddress();
        int port = _socket_.getPort();
        SSLSocket socket = (SSLSocket) ssf.createSocket(_socket_, host, port, false);
        socket.setEnableSessionCreation(isCreation);
        socket.setUseClientMode(isClientMode);

        // client mode
        if (isClientMode){
            if (tlsEndpointChecking){
                SSLSocketUtils.enableEndpointNameVerification(socket);
            }
        }else{ // server mode
            socket.setNeedClientAuth(isNeedClientAuth);
            socket.setWantClientAuth(isWantClientAuth);
        }

        if (protocols != null){
            socket.setEnabledProtocols(protocols);
        }
        if (suites != null){
            socket.setEnabledCipherSuites(suites);
        }
        socket.startHandshake();

        // TODO the following setup appears to duplicate that in the super class methods
        _socket_ = socket;
        _controlInput_ = new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding()));
        _controlOutput_ = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), getControlEncoding()));

        if (isClientMode){
            if (hostnameVerifier != null && !hostnameVerifier.verify(host, socket.getSession())){
                throw new SSLHandshakeException("Hostname doesn't match certificate");
            }
        }
    }

    /**
     * Get the {@link KeyManager} instance.
     * 
     * @return The {@link KeyManager} instance
     */
    private KeyManager getKeyManager(){
        return keyManager;
    }

    /**
     * Set a {@link KeyManager} to use
     *
     * @param keyManager
     *            The KeyManager implementation to set.
     * @see com.feilong.lib.net.util.KeyManagerUtils
     */
    public void setKeyManager(KeyManager keyManager){
        this.keyManager = keyManager;
    }

    /**
     * Controls whether a new SSL session may be established by this socket.
     * 
     * @param isCreation
     *            The established socket flag.
     */
    public void setEnabledSessionCreation(boolean isCreation){
        this.isCreation = isCreation;
    }

    /**
     * Returns true if new SSL sessions may be established by this socket.
     * When the underlying {@link Socket} instance is not SSL-enabled (i.e. an
     * instance of {@link SSLSocket} with {@link SSLSocket}{@link #getEnableSessionCreation()}) enabled,
     * this returns False.
     * 
     * @return true - Indicates that sessions may be created;
     *         this is the default.
     *         false - indicates that an existing session must be resumed.
     */
    public boolean getEnableSessionCreation(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getEnableSessionCreation();
        }
        return false;
    }

    /**
     * Configures the socket to require client authentication.
     * 
     * @param isNeedClientAuth
     *            The need client auth flag.
     */
    public void setNeedClientAuth(boolean isNeedClientAuth){
        this.isNeedClientAuth = isNeedClientAuth;
    }

    /**
     * Returns true if the socket will require client authentication.
     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
     * 
     * @return true - If the server mode socket should request
     *         that the client authenticate itself.
     */
    public boolean getNeedClientAuth(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getNeedClientAuth();
        }
        return false;
    }

    /**
     * Configures the socket to request client authentication,
     * but only if such a request is appropriate to the cipher
     * suite negotiated.
     * 
     * @param isWantClientAuth
     *            The want client auth flag.
     */
    public void setWantClientAuth(boolean isWantClientAuth){
        this.isWantClientAuth = isWantClientAuth;
    }

    /**
     * Returns true if the socket will request client authentication.
     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
     * 
     * @return true - If the server mode socket should request
     *         that the client authenticate itself.
     */
    public boolean getWantClientAuth(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getWantClientAuth();
        }
        return false;
    }

    /**
     * Configures the socket to use client (or server) mode in its first
     * handshake.
     * 
     * @param isClientMode
     *            The use client mode flag.
     */
    public void setUseClientMode(boolean isClientMode){
        this.isClientMode = isClientMode;
    }

    /**
     * Returns true if the socket is set to use client mode
     * in its first handshake.
     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns false.
     * 
     * @return true - If the socket should start its first handshake
     *         in "client" mode.
     */
    public boolean getUseClientMode(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getUseClientMode();
        }
        return false;
    }

    /**
     * Controls which particular cipher suites are enabled for use on this
     * connection. Called before server negotiation.
     * 
     * @param cipherSuites
     *            The cipher suites.
     */
    public void setEnabledCipherSuites(String[] cipherSuites){
        suites = new String[cipherSuites.length];
        System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
    }

    /**
     * Returns the names of the cipher suites which could be enabled
     * for use on this connection.
     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
     * 
     * @return An array of cipher suite names, or null
     */
    public String[] getEnabledCipherSuites(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getEnabledCipherSuites();
        }
        return null;
    }

    /**
     * Controls which particular protocol versions are enabled for use on this
     * connection. I perform setting before a server negotiation.
     * 
     * @param protocolVersions
     *            The protocol versions.
     */
    public void setEnabledProtocols(String[] protocolVersions){
        protocols = new String[protocolVersions.length];
        System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
    }

    /**
     * Returns the names of the protocol versions which are currently
     * enabled for use on this connection.
     * When the underlying {@link Socket} is not an {@link SSLSocket} instance, returns null.
     * 
     * @return An array of protocols, or null
     */
    public String[] getEnabledProtocols(){
        if (_socket_ instanceof SSLSocket){
            return ((SSLSocket) _socket_).getEnabledProtocols();
        }
        return null;
    }

    /**
     * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
     * 
     * @param pbsz
     *            Protection Buffer Size.
     * @throws SSLException
     *             If the server reply code does not equal "200".
     * @throws IOException
     *             If an I/O error occurs while sending
     *             the command.
     * @see #parsePBSZ(long)
     */
    public void execPBSZ(long pbsz) throws SSLException,IOException{
        if (pbsz < 0 || 4294967295L < pbsz){ // 32-bit unsigned number
            throw new IllegalArgumentException();
        }
        int status = sendCommand(CMD_PBSZ, String.valueOf(pbsz));
        if (FTPReply.COMMAND_OK != status){
            throw new SSLException(getReplyString());
        }
    }

    /**
     * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
     * Issues the command and parses the response to return the negotiated value.
     *
     * @param pbsz
     *            Protection Buffer Size.
     * @throws SSLException
     *             If the server reply code does not equal "200".
     * @throws IOException
     *             If an I/O error occurs while sending
     *             the command.
     * @return the negotiated value.
     * @see #execPBSZ(long)
     * @since 3.0
     */
    public long parsePBSZ(long pbsz) throws SSLException,IOException{
        execPBSZ(pbsz);
        long minvalue = pbsz;
        String remainder = extractPrefixedData("PBSZ=", getReplyString());
        if (remainder != null){
            long replysz = Long.parseLong(remainder);
            if (replysz < minvalue){
                minvalue = replysz;
            }
        }
        return minvalue;
    }

    /**
     * PROT command.
     * 
    *
  • C - Clear
  • *
  • S - Safe(SSL protocol only)
  • *
  • E - Confidential(SSL protocol only)
  • *
  • P - Private
  • *
* N.B. the method calls * {@link #setSocketFactory(javax.net.SocketFactory)} and * {@link #setServerSocketFactory(javax.net.ServerSocketFactory)} * * @param prot * Data Channel Protection Level, if {@code null}, use {@link #DEFAULT_PROT}. * @throws SSLException * If the server reply code does not equal {@code 200}. * @throws IOException * If an I/O error occurs while sending * the command. */ public void execPROT(String prot) throws SSLException,IOException{ if (prot == null){ prot = DEFAULT_PROT; } if (!checkPROTValue(prot)){ throw new IllegalArgumentException(); } if (FTPReply.COMMAND_OK != sendCommand(CMD_PROT, prot)){ throw new SSLException(getReplyString()); } if (DEFAULT_PROT.equals(prot)){ setSocketFactory(null); setServerSocketFactory(null); }else{ setSocketFactory(new FTPSSocketFactory(context)); setServerSocketFactory(new FTPSServerSocketFactory(context)); initSslContext(); } } /** * Check the value that can be set in PROT Command value. * * @param prot * Data Channel Protection Level. * @return True - A set point is right / False - A set point is not right */ private static boolean checkPROTValue(String prot){ for (String element : PROT_COMMAND_VALUE){ if (element.equals(prot)){ return true; } } return false; } /** * Send an FTP command. * A successful CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} * instance to be assigned to a plain {@link Socket} * * @param command * The FTP command. * @return server reply. * @throws IOException * If an I/O error occurs while sending the command. * @throws SSLException * if a CCC command fails * @see com.feilong.lib.net.ftp.FTP#sendCommand(java.lang.String) */ // Would like to remove this method, but that will break any existing clients that are using CCC @Override public int sendCommand(String command,String args) throws IOException{ int repCode = super.sendCommand(command, args); /* If CCC is issued, restore socket i/o streams to unsecured versions */ if (CMD_CCC.equals(command)){ if (FTPReply.COMMAND_OK == repCode){ _socket_.close(); _socket_ = plainSocket; _controlInput_ = new BufferedReader(new InputStreamReader(_socket_.getInputStream(), getControlEncoding())); _controlOutput_ = new BufferedWriter(new OutputStreamWriter(_socket_.getOutputStream(), getControlEncoding())); }else{ throw new SSLException(getReplyString()); } } return repCode; } /** * Returns a socket of the data connection. * Wrapped as an {@link SSLSocket}, which carries out handshake processing. * * @param command * The textual representation of the FTP command to send. * @param arg * The arguments to the FTP command. * If this parameter is set to null, then the command is sent with * no arguments. * @return corresponding to the established data connection. * Null is returned if an FTP protocol error is reported at any point * during the establishment and initialization of the connection. * @throws IOException * If there is any problem with the connection. * @see FTPClient#_openDataConnection_(int, String) * @since 3.2 */ @Override protected Socket _openDataConnection_(String command,String arg) throws IOException{ Socket socket = super._openDataConnection_(command, arg); _prepareDataSocket_(socket); if (socket instanceof SSLSocket){ SSLSocket sslSocket = (SSLSocket) socket; sslSocket.setUseClientMode(isClientMode); sslSocket.setEnableSessionCreation(isCreation); // server mode if (!isClientMode){ sslSocket.setNeedClientAuth(isNeedClientAuth); sslSocket.setWantClientAuth(isWantClientAuth); } if (suites != null){ sslSocket.setEnabledCipherSuites(suites); } if (protocols != null){ sslSocket.setEnabledProtocols(protocols); } sslSocket.startHandshake(); } return socket; } /** * Performs any custom initialization for a newly created SSLSocket (before * the SSL handshake happens). * Called by {@link #_openDataConnection_(int, String)} immediately * after creating the socket. * The default implementation is a no-op * * @param socket * the socket to set up * @throws IOException * on error * @since 3.1 */ protected void _prepareDataSocket_(@SuppressWarnings("unused") Socket socket) throws IOException{ } /** * Get the currently configured {@link TrustManager}. * * @return A TrustManager instance. */ public TrustManager getTrustManager(){ return trustManager; } /** * Override the default {@link TrustManager} to use; if set to {@code null}, * the default TrustManager from the JVM will be used. * * @param trustManager * The TrustManager implementation to set, may be {@code null} * @see com.feilong.lib.net.util.TrustManagerUtils */ public void setTrustManager(TrustManager trustManager){ this.trustManager = trustManager; } /** * Get the currently configured {@link HostnameVerifier}. * The verifier is only used on client mode connections. * * @return A HostnameVerifier instance. * @since 3.4 */ public HostnameVerifier getHostnameVerifier(){ return hostnameVerifier; } /** * Override the default {@link HostnameVerifier} to use. * The verifier is only used on client mode connections. * * @param newHostnameVerifier * The HostnameVerifier implementation to set or null to disable. * @since 3.4 */ public void setHostnameVerifier(HostnameVerifier newHostnameVerifier){ hostnameVerifier = newHostnameVerifier; } /** * Return whether or not endpoint identification using the HTTPS algorithm * on Java 1.7+ is enabled. The default behaviour is for this to be disabled. * * This check is only performed on client mode connections. * * @return True if enabled, false if not. * @since 3.4 */ public boolean isEndpointCheckingEnabled(){ return tlsEndpointChecking; } /** * Automatic endpoint identification checking using the HTTPS algorithm * is supported on Java 1.7+. The default behaviour is for this to be disabled. * * This check is only performed on client mode connections. * * @param enable * Enable automatic endpoint identification checking using the HTTPS algorithm on Java 1.7+. * @since 3.4 */ public void setEndpointCheckingEnabled(boolean enable){ tlsEndpointChecking = enable; } /** * Closes the connection to the FTP server and restores * connection parameters to the default values. *

* Calls {@code setSocketFactory(null)} and {@code setServerSocketFactory(null)} * to reset the factories that may have been changed during the session, * e.g. by {@link #execPROT(String)} * * @throws IOException * If an error occurs while disconnecting. * @since 3.0 */ @Override public void disconnect() throws IOException{ super.disconnect(); if (plainSocket != null){ plainSocket.close(); } setSocketFactory(null); setServerSocketFactory(null); } /** * Send the AUTH command with the specified mechanism. * * @param mechanism * The mechanism name to send with the command. * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execAUTH(String mechanism) throws IOException{ return sendCommand(CMD_AUTH, mechanism); } /** * Send the ADAT command with the specified authentication data. * * @param data * The data to send with the command. * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execADAT(byte[] data) throws IOException{ if (data != null){ return sendCommand(CMD_ADAT, Base64.encodeBase64StringUnChunked(data)); } return sendCommand(CMD_ADAT); } /** * Send the CCC command to the server. * The CCC (Clear Command Channel) command causes the underlying {@link SSLSocket} instance to be assigned * to a plain {@link Socket} instances * * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execCCC() throws IOException{ int repCode = sendCommand(CMD_CCC); return repCode; } /** * Send the MIC command with the specified data. * * @param data * The data to send with the command. * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execMIC(byte[] data) throws IOException{ if (data != null){ return sendCommand(CMD_MIC, Base64.encodeBase64StringUnChunked(data)); } return sendCommand(CMD_MIC, ""); // perhaps "=" or just sendCommand(String)? } /** * Send the CONF command with the specified data. * * @param data * The data to send with the command. * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execCONF(byte[] data) throws IOException{ if (data != null){ return sendCommand(CMD_CONF, Base64.encodeBase64StringUnChunked(data)); } return sendCommand(CMD_CONF, ""); // perhaps "=" or just sendCommand(String)? } /** * Send the ENC command with the specified data. * * @param data * The data to send with the command. * @return server reply. * @throws IOException * If an I/O error occurs while sending * the command. * @since 3.0 */ public int execENC(byte[] data) throws IOException{ if (data != null){ return sendCommand(CMD_ENC, Base64.encodeBase64StringUnChunked(data)); } return sendCommand(CMD_ENC, ""); // perhaps "=" or just sendCommand(String)? } /** * Parses the given ADAT response line and base64-decodes the data. * * @param reply * The ADAT reply to parse. * @return the data in the reply, base64-decoded. * @since 3.0 */ public byte[] parseADATReply(String reply){ if (reply == null){ return null; } return Base64.decodeBase64(extractPrefixedData("ADAT=", reply)); } /** * Extract the data from a reply with a prefix, e.g. PBSZ=1234 => 1234 * * @param prefix * the prefix to find * @param reply * where to find the prefix * @return the remainder of the string after the prefix, or null if the prefix was not present. */ private static String extractPrefixedData(String prefix,String reply){ int idx = reply.indexOf(prefix); if (idx == -1){ return null; } // N.B. Cannot use trim before substring as leading space would affect the offset. return reply.substring(idx + prefix.length()).trim(); } // DEPRECATED - for API compatibility only - DO NOT USE /** @deprecated - not used - may be removed in a future release */ @Deprecated public static String KEYSTORE_ALGORITHM; /** @deprecated - not used - may be removed in a future release */ @Deprecated public static String TRUSTSTORE_ALGORITHM; /** @deprecated - not used - may be removed in a future release */ @Deprecated public static String PROVIDER; /** @deprecated - not used - may be removed in a future release */ @Deprecated public static String STORE_TYPE; } /* kate: indent-width 4; replace-tabs on; */





© 2015 - 2024 Weber Informatics LLC | Privacy Policy