/*
 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.net.ftp.impl;

import java.net.*;
import java.io.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.net.ftp.*;
import sun.util.logging.PlatformLogger;


public class FtpClient extends sun.net.ftp.FtpClient {

    private static int defaultSoTimeout;
    private static int defaultConnectTimeout;
    private static final PlatformLogger logger =
             PlatformLogger.getLogger("sun.net.ftp.FtpClient");
    private Proxy proxy;
    private Socket server;
    private PrintStream out;
    private InputStream in;
    private int readTimeout = -1;
    private int connectTimeout = -1;

    /* Name of encoding to use for output */
    private static String encoding = "ISO8859_1";
    /** remember the ftp server name because we may need it */
    private InetSocketAddress serverAddr;
    private boolean replyPending = false;
    private boolean loggedIn = false;
    private boolean useCrypto = false;
    private SSLSocketFactory sslFact;
    private Socket oldSocket;
    /** Array of strings (usually 1 entry) for the last reply from the server. */
    private Vector<String> serverResponse = new Vector<String>(1);
    /** The last reply code from the ftp daemon. */
    private FtpReplyCode lastReplyCode = null;
    /** Welcome message from the server, if any. */
    private String welcomeMsg;
    /**
     * Only passive mode used in JDK. See Bug 8010784.
     */
    private final boolean passiveMode = true;
    private TransferType type = TransferType.BINARY;
    private long restartOffset = 0;
    private long lastTransSize = -1; // -1 means 'unknown size'
    private String lastFileName;
    /**
     * Static members used by the parser
     */
    private static String[] patStrings = {
        // drwxr-xr-x  1 user01        ftp   512 Jan 29 23:32 prog
        "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d\\d:\\d\\d)\\s*(\\p{Print}*)",
        // drwxr-xr-x  1 user01        ftp   512 Jan 29 1997 prog
        "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d{4})\\s*(\\p{Print}*)",
        // 04/28/2006  09:12a               3,563 genBuffer.sh
        "(\\d{2}/\\d{2}/\\d{4})\\s*(\\d{2}:\\d{2}[ap])\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)",
        // 01-29-97    11:32PM <DIR> prog
        "(\\d{2}-\\d{2}-\\d{2})\\s*(\\d{2}:\\d{2}[AP]M)\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)"
    };
    private static int[][] patternGroups = {
        // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year, 5 - permissions,
        // 6 - user, 7 - group
        {7, 4, 5, 6, 0, 1, 2, 3},
        {7, 4, 5, 0, 6, 1, 2, 3},
        {4, 3, 1, 2, 0, 0, 0, 0},
        {4, 3, 1, 2, 0, 0, 0, 0}};
    private static Pattern[] patterns;
    private static Pattern linkp = Pattern.compile("(\\p{Print}+) \\-\\> (\\p{Print}+)$");
    private DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.US);

    static {
        final int vals[] = {0, 0};
        final String encs[] = {null};

        AccessController.doPrivileged(
                new PrivilegedAction<Object>() {

                    public Object run() {
                        vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue();
                        vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue();
                        encs[0] = System.getProperty("file.encoding", "ISO8859_1");
                        return null;
                    }
                });
        if (vals[0] == 0) {
            defaultSoTimeout = -1;
        } else {
            defaultSoTimeout = vals[0];
        }

        if (vals[1] == 0) {
            defaultConnectTimeout = -1;
        } else {
            defaultConnectTimeout = vals[1];
        }

        encoding = encs[0];
        try {
            if (!isASCIISuperset(encoding)) {
                encoding = "ISO8859_1";
            }
        } catch (Exception e) {
            encoding = "ISO8859_1";
        }

        patterns = new Pattern[patStrings.length];
        for (int i = 0; i < patStrings.length; i++) {
            patterns[i] = Pattern.compile(patStrings[i]);
        }
    }

    /**
     * Test the named character encoding to verify that it converts ASCII
     * characters correctly. We have to use an ASCII based encoding, or else
     * the NetworkClients will not work correctly in EBCDIC based systems.
     * However, we cannot just use ASCII or ISO8859_1 universally, because in
     * Asian locales, non-ASCII characters may be embedded in otherwise
     * ASCII based protocols (eg. HTTP). The specifications (RFC2616, 2398)
     * are a little ambiguous in this matter. For instance, RFC2398 [part 2.1]
     * says that the HTTP request URI should be escaped using a defined
     * mechanism, but there is no way to specify in the escaped string what
     * the original character set is. It is not correct to assume that
     * UTF-8 is always used (as in URLs in HTML 4.0).  For this reason,
     * until the specifications are updated to deal with this issue more
     * comprehensively, and more importantly, HTTP servers are known to
     * support these mechanisms, we will maintain the current behavior
     * where it is possible to send non-ASCII characters in their original
     * unescaped form.
     */
    private static boolean isASCIISuperset(String encoding) throws Exception {
        String chkS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                "abcdefghijklmnopqrstuvwxyz-_.!~*'();/?:@&=+$,";

        // Expected byte sequence for string above
        byte[] chkB = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72,
            73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99,
            100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
            115, 116, 117, 118, 119, 120, 121, 122, 45, 95, 46, 33, 126, 42, 39, 40, 41, 59,
            47, 63, 58, 64, 38, 61, 43, 36, 44};

        byte[] b = chkS.getBytes(encoding);
        return java.util.Arrays.equals(b, chkB);
    }

    private class DefaultParser implements FtpDirParser {

        /**
         * Possible patterns:
         *
         *  drwxr-xr-x  1 user01        ftp   512 Jan 29 23:32 prog
         *  drwxr-xr-x  1 user01        ftp   512 Jan 29 1997 prog
         *  drwxr-xr-x  1 1             1     512 Jan 29 23:32 prog
         *  lrwxr-xr-x  1 user01        ftp   512 Jan 29 23:32 prog -> prog2000
         *  drwxr-xr-x  1 username      ftp   512 Jan 29 23:32 prog
         *  -rw-r--r--  1 jcc      staff     105009 Feb  3 15:05 test.1
         *
         *  01-29-97    11:32PM <DIR> prog
         *  04/28/2006  09:12a               3,563 genBuffer.sh
         *
         *  drwxr-xr-x  folder   0       Jan 29 23:32 prog
         *
         *  0 DIR 01-29-97 23:32 PROG
         */
        private DefaultParser() {
        }

        public FtpDirEntry parseLine(String line) {
            String fdate = null;
            String fsize = null;
            String time = null;
            String filename = null;
            String permstring = null;
            String username = null;
            String groupname = null;
            boolean dir = false;
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);

            Matcher m = null;
            for (int j = 0; j < patterns.length; j++) {
                m = patterns[j].matcher(line);
                if (m.find()) {
                    // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year,
                    // 5 - permissions, 6 - user, 7 - group
                    filename = m.group(patternGroups[j][0]);
                    fsize = m.group(patternGroups[j][1]);
                    fdate = m.group(patternGroups[j][2]);
                    if (patternGroups[j][4] > 0) {
                        fdate += (", " + m.group(patternGroups[j][4]));
                    } else if (patternGroups[j][3] > 0) {
                        fdate += (", " + String.valueOf(year));
                    }
                    if (patternGroups[j][3] > 0) {
                        time = m.group(patternGroups[j][3]);
                    }
                    if (patternGroups[j][5] > 0) {
                        permstring = m.group(patternGroups[j][5]);
                        dir = permstring.startsWith("d");
                    }
                    if (patternGroups[j][6] > 0) {
                        username = m.group(patternGroups[j][6]);
                    }
                    if (patternGroups[j][7] > 0) {
                        groupname = m.group(patternGroups[j][7]);
                    }
                    // Old DOS format
                    if ("<DIR>".equals(fsize)) {
                        dir = true;
                        fsize = null;
                    }
                }
            }

            if (filename != null) {
                Date d;
                try {
                    d = df.parse(fdate);
                } catch (Exception e) {
                    d = null;
                }
                if (d != null && time != null) {
                    int c = time.indexOf(":");
                    now.setTime(d);
                    now.set(Calendar.HOUR, Integer.parseInt(time.substring(0, c)));
                    now.set(Calendar.MINUTE, Integer.parseInt(time.substring(c + 1)));
                    d = now.getTime();
                }
                // see if it's a symbolic link, i.e. the name if followed
                // by a -> and a path
                Matcher m2 = linkp.matcher(filename);
                if (m2.find()) {
                    // Keep only the name then
                    filename = m2.group(1);
                }
                boolean[][] perms = new boolean[3][3];
                for (int i = 0; i < 3; i++) {
                    for (int j = 0; j < 3; j++) {
                        perms[i][j] = (permstring.charAt((i * 3) + j) != '-');
                    }
                }
                FtpDirEntry file = new FtpDirEntry(filename);
                file.setUser(username).setGroup(groupname);
                file.setSize(Long.parseLong(fsize)).setLastModified(d);
                file.setPermissions(perms);
                file.setType(dir ? FtpDirEntry.Type.DIR : (line.charAt(0) == 'l' ? FtpDirEntry.Type.LINK : FtpDirEntry.Type.FILE));
                return file;
            }
            return null;
        }
    }

    private class MLSxParser implements FtpDirParser {

        private SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");

        public FtpDirEntry parseLine(String line) {
            String name = null;
            int i = line.lastIndexOf(";");
            if (i > 0) {
                name = line.substring(i + 1).trim();
                line = line.substring(0, i);
            } else {
                name = line.trim();
                line = "";
            }
            FtpDirEntry file = new FtpDirEntry(name);
            while (!line.isEmpty()) {
                String s;
                i = line.indexOf(";");
                if (i > 0) {
                    s = line.substring(0, i);
                    line = line.substring(i + 1);
                } else {
                    s = line;
                    line = "";
                }
                i = s.indexOf("=");
                if (i > 0) {
                    String fact = s.substring(0, i);
                    String value = s.substring(i + 1);
                    file.addFact(fact, value);
                }
            }
            String s = file.getFact("Size");
            if (s != null) {
                file.setSize(Long.parseLong(s));
            }
            s = file.getFact("Modify");
            if (s != null) {
                Date d = null;
                try {
                    d = df.parse(s);
                } catch (ParseException ex) {
                }
                if (d != null) {
                    file.setLastModified(d);
                }
            }
            s = file.getFact("Create");
            if (s != null) {
                Date d = null;
                try {
                    d = df.parse(s);
                } catch (ParseException ex) {
                }
                if (d != null) {
                    file.setCreated(d);
                }
            }
            s = file.getFact("Type");
            if (s != null) {
                if (s.equalsIgnoreCase("file")) {
                    file.setType(FtpDirEntry.Type.FILE);
                }
                if (s.equalsIgnoreCase("dir")) {
                    file.setType(FtpDirEntry.Type.DIR);
                }
                if (s.equalsIgnoreCase("cdir")) {
                    file.setType(FtpDirEntry.Type.CDIR);
                }
                if (s.equalsIgnoreCase("pdir")) {
                    file.setType(FtpDirEntry.Type.PDIR);
                }
            }
            return file;
        }
    };
    private FtpDirParser parser = new DefaultParser();
    private FtpDirParser mlsxParser = new MLSxParser();
    private static Pattern transPat = null;

    private void getTransferSize() {
        lastTransSize = -1;
        /**
         * If it's a start of data transfer response, let's try to extract
         * the size from the response string. Usually it looks like that:
         *
         * 150 Opening BINARY mode data connection for foo (6701 bytes).
         */
        String response = getLastResponseString();
        if (transPat == null) {
            transPat = Pattern.compile("150 Opening .*\\((\\d+) bytes\\).");
        }
        Matcher m = transPat.matcher(response);
        if (m.find()) {
            String s = m.group(1);
            lastTransSize = Long.parseLong(s);
        }
    }

    /**
     * extract the created file name from the response string:
     * 226 Transfer complete (unique file name:toto.txt.1).
     * Usually happens when a STOU (store unique) command had been issued.
     */
    private void getTransferName() {
        lastFileName = null;
        String response = getLastResponseString();
        int i = response.indexOf("unique file name:");
        int e = response.lastIndexOf(')');
        if (i >= 0) {
            i += 17; // Length of "unique file name:"
            lastFileName = response.substring(i, e);
        }
    }

    /**
     * Pulls the response from the server and returns the code as a
     * number. Returns -1 on failure.
     */
    private int readServerResponse() throws IOException {
        StringBuffer replyBuf = new StringBuffer(32);
        int c;
        int continuingCode = -1;
        int code;
        String response;

        serverResponse.setSize(0);
        while (true) {
            while ((c = in.read()) != -1) {
                if (c == '\r') {
                    if ((c = in.read()) != '\n') {
                        replyBuf.append('\r');
                    }
                }
                replyBuf.append((char) c);
                if (c == '\n') {
                    break;
                }
            }
            response = replyBuf.toString();
            replyBuf.setLength(0);
            if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                logger.finest("Server [" + serverAddr + "] --> " + response);
            }

            if (response.length() == 0) {
                code = -1;
            } else {
                try {
                    code = Integer.parseInt(response.substring(0, 3));
                } catch (NumberFormatException e) {
                    code = -1;
                } catch (StringIndexOutOfBoundsException e) {
                    /* this line doesn't contain a response code, so
                    we just completely ignore it */
                    continue;
                }
            }
            serverResponse.addElement(response);
            if (continuingCode != -1) {
                /* we've seen a ###- sequence */
                if (code != continuingCode ||
                        (response.length() >= 4 && response.charAt(3) == '-')) {
                    continue;
                } else {
                    /* seen the end of code sequence */
                    continuingCode = -1;
                    break;
                }
            } else if (response.length() >= 4 && response.charAt(3) == '-') {
                continuingCode = code;
                continue;
            } else {
                break;
            }
        }

        return code;
    }

    /** Sends command <i>cmd</i> to the server. */
    private void sendServer(String cmd) {
        out.print(cmd);
        if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
            logger.finest("Server [" + serverAddr + "] <-- " + cmd);
        }
    }

    /** converts the server response into a string. */
    private String getResponseString() {
        return serverResponse.elementAt(0);
    }

    /** Returns all server response strings. */
    private Vector<String> getResponseStrings() {
        return serverResponse;
    }

    /**
     * Read the reply from the FTP server.
     *
     * @return <code>true</code> if the command was successful
     * @throws IOException if an error occurred
     */
    private boolean readReply() throws IOException {
        lastReplyCode = FtpReplyCode.find(readServerResponse());

        if (lastReplyCode.isPositivePreliminary()) {
            replyPending = true;
            return true;
        }
        if (lastReplyCode.isPositiveCompletion() || lastReplyCode.isPositiveIntermediate()) {
            if (lastReplyCode == FtpReplyCode.CLOSING_DATA_CONNECTION) {
                getTransferName();
            }
            return true;
        }
        return false;
    }

    /**
     * Sends a command to the FTP server and returns the error code
     * (which can be a "success") sent by the server.
     *
     * @param cmd
     * @return <code>true</code> if the command was successful
     * @throws IOException
     */
    private boolean issueCommand(String cmd) throws IOException {
        if (!isConnected()) {
            throw new IllegalStateException("Not connected");
        }
        if (replyPending) {
            try {
                completePending();
            } catch (sun.net.ftp.FtpProtocolException e) {
                // ignore...
            }
        }
        sendServer(cmd + "\r\n");
        return readReply();
    }

    /**
     * Send a command to the FTP server and check for success.
     *
     * @param cmd String containing the command
     *
     * @throws FtpProtocolException if an error occurred
     */
    private void issueCommandCheck(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
        if (!issueCommand(cmd)) {
            throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode());
        }
    }
    private static Pattern epsvPat = null;
    private static Pattern pasvPat = null;

    /**
     * Opens a "PASSIVE" connection with the server and returns the connected
     * <code>Socket</code>.
     *
     * @return the connected <code>Socket</code>
     * @throws IOException if the connection was unsuccessful.
     */
    private Socket openPassiveDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
        String serverAnswer;
        int port;
        InetSocketAddress dest = null;

        /**
         * Here is the idea:
         *
         * - First we want to try the new (and IPv6 compatible) EPSV command
         *   But since we want to be nice with NAT software, we'll issue the
         *   EPSV ALL command first.
         *   EPSV is documented in RFC2428
         * - If EPSV fails, then we fall back to the older, yet ok, PASV
         * - If PASV fails as well, then we throw an exception and the calling
         *   method will have to try the EPRT or PORT command
         */
        if (issueCommand("EPSV ALL")) {
            // We can safely use EPSV commands
            issueCommandCheck("EPSV");
            serverAnswer = getResponseString();

            // The response string from a EPSV command will contain the port number
            // the format will be :
            //  229 Entering Extended PASSIVE Mode (|||58210|)
            //
            // So we'll use the regular expresions package to parse the output.

            if (epsvPat == null) {
                epsvPat = Pattern.compile("^229 .* \\(\\|\\|\\|(\\d+)\\|\\)");
            }
            Matcher m = epsvPat.matcher(serverAnswer);
            if (!m.find()) {
                throw new sun.net.ftp.FtpProtocolException("EPSV failed : " + serverAnswer);
            }
            // Yay! Let's extract the port number
            String s = m.group(1);
            port = Integer.parseInt(s);
            InetAddress add = server.getInetAddress();
            if (add != null) {
                dest = new InetSocketAddress(add, port);
            } else {
                // This means we used an Unresolved address to connect in
                // the first place. Most likely because the proxy is doing
                // the name resolution for us, so let's keep using unresolved
                // address.
                dest = InetSocketAddress.createUnresolved(serverAddr.getHostName(), port);
            }
        } else {
            // EPSV ALL failed, so Let's try the regular PASV cmd
            issueCommandCheck("PASV");
            serverAnswer = getResponseString();

            // Let's parse the response String to get the IP & port to connect
            // to. The String should be in the following format :
            //
            // 227 Entering PASSIVE Mode (A1,A2,A3,A4,p1,p2)
            //
            // Note that the two parenthesis are optional
            //
            // The IP address is A1.A2.A3.A4 and the port is p1 * 256 + p2
            //
            // The regular expression is a bit more complex this time, because
            // the parenthesis are optionals and we have to use 3 groups.

            if (pasvPat == null) {
                pasvPat = Pattern.compile("227 .* \\(?(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)?");
            }
            Matcher m = pasvPat.matcher(serverAnswer);
            if (!m.find()) {
                throw new sun.net.ftp.FtpProtocolException("PASV failed : " + serverAnswer);
            }
            // Get port number out of group 2 & 3
            port = Integer.parseInt(m.group(3)) + (Integer.parseInt(m.group(2)) << 8);
            // IP address is simple
            String s = m.group(1).replace(',', '.');
            dest = new InetSocketAddress(s, port);
        }
        // Got everything, let's open the socket!
        Socket s;
        if (proxy != null) {
            if (proxy.type() == Proxy.Type.SOCKS) {
                s = AccessController.doPrivileged(
                        new PrivilegedAction<Socket>() {

                            public Socket run() {
                                return new Socket(proxy);
                            }
                        });
            } else {
                s = new Socket(Proxy.NO_PROXY);
            }
        } else {
            s = new Socket();
        }

        InetAddress serverAddress = AccessController.doPrivileged(
                new PrivilegedAction<InetAddress>() {
                    @Override
                    public InetAddress run() {
                        return server.getLocalAddress();
                    }
                });

        // Bind the socket to the same address as the control channel. This
        // is needed in case of multi-homed systems.
        s.bind(new InetSocketAddress(serverAddress, 0));
        if (connectTimeout >= 0) {
            s.connect(dest, connectTimeout);
        } else {
            if (defaultConnectTimeout > 0) {
                s.connect(dest, defaultConnectTimeout);
            } else {
                s.connect(dest);
            }
        }
        if (readTimeout >= 0) {
            s.setSoTimeout(readTimeout);
        } else if (defaultSoTimeout > 0) {
            s.setSoTimeout(defaultSoTimeout);
        }
        if (useCrypto) {
            try {
                s = sslFact.createSocket(s, dest.getHostName(), dest.getPort(), true);
            } catch (Exception e) {
                throw new sun.net.ftp.FtpProtocolException("Can't open secure data channel: " + e);
            }
        }
        if (!issueCommand(cmd)) {
            s.close();
            if (getLastReplyCode() == FtpReplyCode.FILE_UNAVAILABLE) {
                // Ensure backward compatibility
                throw new FileNotFoundException(cmd);
            }
            throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode());
        }
        return s;
    }

    /**
     * Opens a data connection with the server according to the set mode
     * (ACTIVE or PASSIVE) then send the command passed as an argument.
     *
     * @param cmd the <code>String</code> containing the command to execute
     * @return the connected <code>Socket</code>
     * @throws IOException if the connection or command failed
     */
    private Socket openDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
        Socket clientSocket;

        if (passiveMode) {
            try {
                return openPassiveDataConnection(cmd);
            } catch (sun.net.ftp.FtpProtocolException e) {
                // If Passive mode failed, fall back on PORT
                // Otherwise throw exception
                String errmsg = e.getMessage();
                if (!errmsg.startsWith("PASV") && !errmsg.startsWith("EPSV")) {
                    throw e;
                }
            }
        }
        ServerSocket portSocket;
        InetAddress myAddress;
        String portCmd;

        if (proxy != null && proxy.type() == Proxy.Type.SOCKS) {
            // We're behind a firewall and the passive mode fail,
            // since we can't accept a connection through SOCKS (yet)
            // throw an exception
            throw new sun.net.ftp.FtpProtocolException("Passive mode failed");
        }
        // Bind the ServerSocket to the same address as the control channel
        // This is needed for multi-homed systems
        portSocket = new ServerSocket(0, 1, server.getLocalAddress());
        try {
            myAddress = portSocket.getInetAddress();
            if (myAddress.isAnyLocalAddress()) {
                myAddress = server.getLocalAddress();
            }
            // Let's try the new, IPv6 compatible EPRT command
            // See RFC2428 for specifics
            // Some FTP servers (like the one on Solaris) are bugged, they
            // will accept the EPRT command but then, the subsequent command
            // (e.g. RETR) will fail, so we have to check BOTH results (the
            // EPRT cmd then the actual command) to decide whether we should
            // fall back on the older PORT command.
            portCmd = "EPRT |" + ((myAddress instanceof Inet6Address) ? "2" : "1") + "|" +
                    myAddress.getHostAddress() + "|" + portSocket.getLocalPort() + "|";
            if (!issueCommand(portCmd) || !issueCommand(cmd)) {
                // The EPRT command failed, let's fall back to good old PORT
                portCmd = "PORT ";
                byte[] addr = myAddress.getAddress();

                /* append host addr */
                for (int i = 0; i < addr.length; i++) {
                    portCmd = portCmd + (addr[i] & 0xFF) + ",";
                }

                /* append port number */
                portCmd = portCmd + ((portSocket.getLocalPort() >>> 8) & 0xff) + "," + (portSocket.getLocalPort() & 0xff);
                issueCommandCheck(portCmd);
                issueCommandCheck(cmd);
            }
            // Either the EPRT or the PORT command was successful
            // Let's create the client socket
            if (connectTimeout >= 0) {
                portSocket.setSoTimeout(connectTimeout);
            } else {
                if (defaultConnectTimeout > 0) {
                    portSocket.setSoTimeout(defaultConnectTimeout);
                }
            }
            clientSocket = portSocket.accept();
            if (readTimeout >= 0) {
                clientSocket.setSoTimeout(readTimeout);
            } else {
                if (defaultSoTimeout > 0) {
                    clientSocket.setSoTimeout(defaultSoTimeout);
                }
            }
        } finally {
            portSocket.close();
        }
        if (useCrypto) {
            try {
                clientSocket = sslFact.createSocket(clientSocket, serverAddr.getHostName(), serverAddr.getPort(), true);
            } catch (Exception ex) {
                throw new IOException(ex.getLocalizedMessage());
            }
        }
        return clientSocket;
    }

    private InputStream createInputStream(InputStream in) {
        if (type == TransferType.ASCII) {
            return new sun.net.TelnetInputStream(in, false);
        }
        return in;
    }

    private OutputStream createOutputStream(OutputStream out) {
        if (type == TransferType.ASCII) {
            return new sun.net.TelnetOutputStream(out, false);
        }
        return out;
    }

    /**
     * Creates an instance of FtpClient. The client is not connected to any
     * server yet.
     *
     */
    protected FtpClient() {
    }

    /**
     * Creates an instance of FtpClient. The client is not connected to any
     * server yet.
     *
     */
    public static sun.net.ftp.FtpClient create() {
        return new FtpClient();
    }

    /**
     * Set the transfer mode to <I>passive</I>. In that mode, data connections
     * are established by having the client connect to the server.
     * This is the recommended default mode as it will work best through
     * firewalls and NATs.
     *
     * @return This FtpClient
     * @see #setActiveMode()
     */
    public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) {

        // Only passive mode used in JDK. See Bug 8010784.
        // passiveMode = passive;
        return this;
    }

    /**
     * Gets the current transfer mode.
     *
     * @return the current <code>FtpTransferMode</code>
     */
    public boolean isPassiveModeEnabled() {
        return passiveMode;
    }

    /**
     * Sets the timeout value to use when connecting to the server,
     *
     * @param timeout the timeout value, in milliseconds, to use for the connect
     *        operation. A value of zero or less, means use the default timeout.
     *
     * @return This FtpClient
     */
    public sun.net.ftp.FtpClient setConnectTimeout(int timeout) {
        connectTimeout = timeout;
        return this;
    }

    /**
     * Returns the current connection timeout value.
     *
     * @return the value, in milliseconds, of the current connect timeout.
     * @see #setConnectTimeout(int)
     */
    public int getConnectTimeout() {
        return connectTimeout;
    }

    /**
     * Sets the timeout value to use when reading from the server,
     *
     * @param timeout the timeout value, in milliseconds, to use for the read
     *        operation. A value of zero or less, means use the default timeout.
     * @return This FtpClient
     */
    public sun.net.ftp.FtpClient setReadTimeout(int timeout) {
        readTimeout = timeout;
        return this;
    }

    /**
     * Returns the current read timeout value.
     *
     * @return the value, in milliseconds, of the current read timeout.
     * @see #setReadTimeout(int)
     */
    public int getReadTimeout() {
        return readTimeout;
    }

    public sun.net.ftp.FtpClient setProxy(Proxy p) {
        proxy = p;
        return this;
    }

    /**
     * Get the proxy of this FtpClient
     *
     * @return the <code>Proxy</code>, this client is using, or <code>null</code>
     *         if none is used.
     * @see #setProxy(Proxy)
     */
    public Proxy getProxy() {
        return proxy;
    }

    /**
     * Connects to the specified destination.
     *
     * @param dest the <code>InetSocketAddress</code> to connect to.
     * @throws IOException if the connection fails.
     */
    private void tryConnect(InetSocketAddress dest, int timeout) throws IOException {
        if (isConnected()) {
            disconnect();
        }
        server = doConnect(dest, timeout);
        try {
            out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                    true, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(encoding + "encoding not found", e);
        }
        in = new BufferedInputStream(server.getInputStream());
    }

    private Socket doConnect(InetSocketAddress dest, int timeout) throws IOException {
        Socket s;
        if (proxy != null) {
            if (proxy.type() == Proxy.Type.SOCKS) {
                s = AccessController.doPrivileged(
                        new PrivilegedAction<Socket>() {

                            public Socket run() {
                                return new Socket(proxy);
                            }
                        });
            } else {
                s = new Socket(Proxy.NO_PROXY);
            }
        } else {
            s = new Socket();
        }
        // Instance specific timeouts do have priority, that means
        // connectTimeout & readTimeout (-1 means not set)
        // Then global default timeouts
        // Then no timeout.
        if (timeout >= 0) {
            s.connect(dest, timeout);
        } else {
            if (connectTimeout >= 0) {
                s.connect(dest, connectTimeout);
            } else {
                if (defaultConnectTimeout > 0) {
                    s.connect(dest, defaultConnectTimeout);
                } else {
                    s.connect(dest);
                }
            }
        }
        if (readTimeout >= 0) {
            s.setSoTimeout(readTimeout);
        } else if (defaultSoTimeout > 0) {
            s.setSoTimeout(defaultSoTimeout);
        }
        return s;
    }

    private void disconnect() throws IOException {
        if (isConnected()) {
            server.close();
        }
        server = null;
        in = null;
        out = null;
        lastTransSize = -1;
        lastFileName = null;
        restartOffset = 0;
        welcomeMsg = null;
        lastReplyCode = null;
        serverResponse.setSize(0);
    }

    /**
     * Tests whether this client is connected or not to a server.
     *
     * @return <code>true</code> if the client is connected.
     */
    public boolean isConnected() {
        return server != null;
    }

    public SocketAddress getServerAddress() {
        return server == null ? null : server.getRemoteSocketAddress();
    }

    public sun.net.ftp.FtpClient connect(SocketAddress dest) throws sun.net.ftp.FtpProtocolException, IOException {
        return connect(dest, -1);
    }

    /**
     * Connects the FtpClient to the specified destination.
     *
     * @param dest the address of the destination server
     * @throws IOException if connection failed.
     */
    public sun.net.ftp.FtpClient connect(SocketAddress dest, int timeout) throws sun.net.ftp.FtpProtocolException, IOException {
        if (!(dest instanceof InetSocketAddress)) {
            throw new IllegalArgumentException("Wrong address type");
        }
        serverAddr = (InetSocketAddress) dest;
        tryConnect(serverAddr, timeout);
        if (!readReply()) {
            throw new sun.net.ftp.FtpProtocolException("Welcome message: " +
                    getResponseString(), lastReplyCode);
        }
        welcomeMsg = getResponseString().substring(4);
        return this;
    }

    private void tryLogin(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("USER " + user);

        /*
         * Checks for "331 User name okay, need password." answer
         */
        if (lastReplyCode == FtpReplyCode.NEED_PASSWORD) {
            if ((password != null) && (password.length > 0)) {
                issueCommandCheck("PASS " + String.valueOf(password));
            }
        }
    }

    /**
     * Attempts to log on the server with the specified user name and password.
     *
     * @param user The user name
     * @param password The password for that user
     * @return <code>true</code> if the login was successful.
     * @throws IOException if an error occurred during the transmission
     */
    public sun.net.ftp.FtpClient login(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException {
        if (!isConnected()) {
            throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
        }
        if (user == null || user.length() == 0) {
            throw new IllegalArgumentException("User name can't be null or empty");
        }
        tryLogin(user, password);

        // keep the welcome message around so we can
        // put it in the resulting HTML page.
        String l;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < serverResponse.size(); i++) {
            l = serverResponse.elementAt(i);
            if (l != null) {
                if (l.length() >= 4 && l.startsWith("230")) {
                    // get rid of the "230-" prefix
                    l = l.substring(4);
                }
                sb.append(l);
            }
        }
        welcomeMsg = sb.toString();
        loggedIn = true;
        return this;
    }

    /**
     * Attempts to log on the server with the specified user name, password and
     * account name.
     *
     * @param user The user name
     * @param password The password for that user.
     * @param account The account name for that user.
     * @return <code>true</code> if the login was successful.
     * @throws IOException if an error occurs during the transmission.
     */
    public sun.net.ftp.FtpClient login(String user, char[] password, String account) throws sun.net.ftp.FtpProtocolException, IOException {

        if (!isConnected()) {
            throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
        }
        if (user == null || user.length() == 0) {
            throw new IllegalArgumentException("User name can't be null or empty");
        }
        tryLogin(user, password);

        /*
         * Checks for "332 Need account for login." answer
         */
        if (lastReplyCode == FtpReplyCode.NEED_ACCOUNT) {
            issueCommandCheck("ACCT " + account);
        }

        // keep the welcome message around so we can
        // put it in the resulting HTML page.
        StringBuffer sb = new StringBuffer();
        if (serverResponse != null) {
            for (String l : serverResponse) {
                if (l != null) {
                    if (l.length() >= 4 && l.startsWith("230")) {
                        // get rid of the "230-" prefix
                        l = l.substring(4);
                    }
                    sb.append(l);
                }
            }
        }
        welcomeMsg = sb.toString();
        loggedIn = true;
        return this;
    }

    /**
     * Logs out the current user. This is in effect terminates the current
     * session and the connection to the server will be closed.
     *
     */
    public void close() throws IOException {
        if (isConnected()) {
            issueCommand("QUIT");
            loggedIn = false;
        }
        disconnect();
    }

    /**
     * Checks whether the client is logged in to the server or not.
     *
     * @return <code>true</code> if the client has already completed a login.
     */
    public boolean isLoggedIn() {
        return loggedIn;
    }

    /**
     * Changes to a specific directory on a remote FTP server
     *
     * @param remoteDirectory path of the directory to CD to.
     * @return <code>true</code> if the operation was successful.
     * @exception <code>FtpProtocolException</code>
     */
    public sun.net.ftp.FtpClient changeDirectory(String remoteDirectory) throws sun.net.ftp.FtpProtocolException, IOException {
        if (remoteDirectory == null || "".equals(remoteDirectory)) {
            throw new IllegalArgumentException("directory can't be null or empty");
        }

        issueCommandCheck("CWD " + remoteDirectory);
        return this;
    }

    /**
     * Changes to the parent directory, sending the CDUP command to the server.
     *
     * @return <code>true</code> if the command was successful.
     * @throws IOException
     */
    public sun.net.ftp.FtpClient changeToParentDirectory() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("CDUP");
        return this;
    }

    /**
     * Returns the server current working directory, or <code>null</code> if
     * the PWD command failed.
     *
     * @return a <code>String</code> containing the current working directory,
     *         or <code>null</code>
     * @throws IOException
     */
    public String getWorkingDirectory() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("PWD");
        /*
         * answer will be of the following format :
         *
         * 257 "/" is current directory.
         */
        String answ = getResponseString();
        if (!answ.startsWith("257")) {
            return null;
        }
        return answ.substring(5, answ.lastIndexOf('"'));
    }

    /**
     * Sets the restart offset to the specified value.  That value will be
     * sent through a <code>REST</code> command to server before a file
     * transfer and has the effect of resuming a file transfer from the
     * specified point. After a transfer the restart offset is set back to
     * zero.
     *
     * @param offset the offset in the remote file at which to start the next
     *        transfer. This must be a value greater than or equal to zero.
     * @throws IllegalArgumentException if the offset is negative.
     */
    public sun.net.ftp.FtpClient setRestartOffset(long offset) {
        if (offset < 0) {
            throw new IllegalArgumentException("offset can't be negative");
        }
        restartOffset = offset;
        return this;
    }

    /**
     * Retrieves a file from the ftp server and writes it to the specified
     * <code>OutputStream</code>.
     * If the restart offset was set, then a <code>REST</code> command will be
     * sent before the RETR in order to restart the tranfer from the specified
     * offset.
     * The <code>OutputStream</code> is not closed by this method at the end
     * of the transfer.
     *
     * @param name a <code>String<code> containing the name of the file to
     *        retreive from the server.
     * @param local the <code>OutputStream</code> the file should be written to.
     * @throws IOException if the transfer fails.
     */
    public sun.net.ftp.FtpClient getFile(String name, OutputStream local) throws sun.net.ftp.FtpProtocolException, IOException {
        int mtu = 1500;
        if (restartOffset > 0) {
            Socket s;
            try {
                s = openDataConnection("REST " + restartOffset);
            } finally {
                restartOffset = 0;
            }
            issueCommandCheck("RETR " + name);
            getTransferSize();
            InputStream remote = createInputStream(s.getInputStream());
            byte[] buf = new byte[mtu * 10];
            int l;
            while ((l = remote.read(buf)) >= 0) {
                if (l > 0) {
                    local.write(buf, 0, l);
                }
            }
            remote.close();
        } else {
            Socket s = openDataConnection("RETR " + name);
            getTransferSize();
            InputStream remote = createInputStream(s.getInputStream());
            byte[] buf = new byte[mtu * 10];
            int l;
            while ((l = remote.read(buf)) >= 0) {
                if (l > 0) {
                    local.write(buf, 0, l);
                }
            }
            remote.close();
        }
        return completePending();
    }

    /**
     * Retrieves a file from the ftp server, using the RETR command, and
     * returns the InputStream from* the established data connection.
     * {@link #completePending()} <b>has</b> to be called once the application
     * is done reading from the returned stream.
     *
     * @param name the name of the remote file
     * @return the {@link java.io.InputStream} from the data connection, or
     *         <code>null</code> if the command was unsuccessful.
     * @throws IOException if an error occurred during the transmission.
     */
    public InputStream getFileStream(String name) throws sun.net.ftp.FtpProtocolException, IOException {
        Socket s;
        if (restartOffset > 0) {
            try {
                s = openDataConnection("REST " + restartOffset);
            } finally {
                restartOffset = 0;
            }
            if (s == null) {
                return null;
            }
            issueCommandCheck("RETR " + name);
            getTransferSize();
            return createInputStream(s.getInputStream());
        }

        s = openDataConnection("RETR " + name);
        if (s == null) {
            return null;
        }
        getTransferSize();
        return createInputStream(s.getInputStream());
    }

    /**
     * Transfers a file from the client to the server (aka a <I>put</I>)
     * by sending the STOR or STOU command, depending on the
     * <code>unique</code> argument, and returns the <code>OutputStream</code>
     * from the established data connection.
     * {@link #completePending()} <b>has</b> to be called once the application
     * is finished writing to the stream.
     *
     * A new file is created at the server site if the file specified does
     * not already exist.
     *
     * If <code>unique</code> is set to <code>true</code>, the resultant file
     * is to be created under a name unique to that directory, meaning
     * it will not overwrite an existing file, instead the server will
     * generate a new, unique, file name.
     * The name of the remote file can be retrieved, after completion of the
     * transfer, by calling {@link #getLastFileName()}.
     *
     * @param name the name of the remote file to write.
     * @param unique <code>true</code> if the remote files should be unique,
     *        in which case the STOU command will be used.
     * @return the {@link java.io.OutputStream} from the data connection or
     *         <code>null</code> if the command was unsuccessful.
     * @throws IOException if an error occurred during the transmission.
     */
    public OutputStream putFileStream(String name, boolean unique)
        throws sun.net.ftp.FtpProtocolException, IOException
    {
        String cmd = unique ? "STOU " : "STOR ";
        Socket s = openDataConnection(cmd + name);
        if (s == null) {
            return null;
        }
        boolean bm = (type == TransferType.BINARY);
        return new sun.net.TelnetOutputStream(s.getOutputStream(), bm);
    }

    /**
     * Transfers a file from the client to the server (aka a <I>put</I>)
     * by sending the STOR command. The content of the <code>InputStream</code>
     * passed in argument is written into the remote file, overwriting any
     * existing data.
     *
     * A new file is created at the server site if the file specified does
     * not already exist.
     *
     * @param name the name of the remote file to write.
     * @param local the <code>InputStream</code> that points to the data to
     *        transfer.
     * @param unique <code>true</code> if the remote file should be unique
     *        (i.e. not already existing), <code>false</code> otherwise.
     * @return <code>true</code> if the transfer was successful.
     * @throws IOException if an error occurred during the transmission.
     * @see #getLastFileName()
     */
    public sun.net.ftp.FtpClient putFile(String name, InputStream local, boolean unique) throws sun.net.ftp.FtpProtocolException, IOException {
        String cmd = unique ? "STOU " : "STOR ";
        int mtu = 1500;
        if (type == TransferType.BINARY) {
            Socket s = openDataConnection(cmd + name);
            OutputStream remote = createOutputStream(s.getOutputStream());
            byte[] buf = new byte[mtu * 10];
            int l;
            while ((l = local.read(buf)) >= 0) {
                if (l > 0) {
                    remote.write(buf, 0, l);
                }
            }
            remote.close();
        }
        return completePending();
    }

    /**
     * Sends the APPE command to the server in order to transfer a data stream
     * passed in argument and append it to the content of the specified remote
     * file.
     *
     * @param name A <code>String</code> containing the name of the remote file
     *        to append to.
     * @param local The <code>InputStream</code> providing access to the data
     *        to be appended.
     * @return <code>true</code> if the transfer was successful.
     * @throws IOException if an error occurred during the transmission.
     */
    public sun.net.ftp.FtpClient appendFile(String name, InputStream local) throws sun.net.ftp.FtpProtocolException, IOException {
        int mtu = 1500;
        Socket s = openDataConnection("APPE " + name);
        OutputStream remote = createOutputStream(s.getOutputStream());
        byte[] buf = new byte[mtu * 10];
        int l;
        while ((l = local.read(buf)) >= 0) {
            if (l > 0) {
                remote.write(buf, 0, l);
            }
        }
        remote.close();
        return completePending();
    }

    /**
     * Renames a file on the server.
     *
     * @param from the name of the file being renamed
     * @param to the new name for the file
     * @throws IOException if the command fails
     */
    public sun.net.ftp.FtpClient rename(String from, String to) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("RNFR " + from);
        issueCommandCheck("RNTO " + to);
        return this;
    }

    /**
     * Deletes a file on the server.
     *
     * @param name a <code>String</code> containing the name of the file
     *        to delete.
     * @return <code>true</code> if the command was successful
     * @throws IOException if an error occurred during the exchange
     */
    public sun.net.ftp.FtpClient deleteFile(String name) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("DELE " + name);
        return this;
    }

    /**
     * Creates a new directory on the server.
     *
     * @param name a <code>String</code> containing the name of the directory
     *        to create.
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during the exchange
     */
    public sun.net.ftp.FtpClient makeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("MKD " + name);
        return this;
    }

    /**
     * Removes a directory on the server.
     *
     * @param name a <code>String</code> containing the name of the directory
     *        to remove.
     *
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during the exchange.
     */
    public sun.net.ftp.FtpClient removeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("RMD " + name);
        return this;
    }

    /**
     * Sends a No-operation command. It's useful for testing the connection
     * status or as a <I>keep alive</I> mechanism.
     *
     * @throws FtpProtocolException if the command fails
     */
    public sun.net.ftp.FtpClient noop() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("NOOP");
        return this;
    }

    /**
     * Sends the STAT command to the server.
     * This can be used while a data connection is open to get a status
     * on the current transfer, in that case the parameter should be
     * <code>null</code>.
     * If used between file transfers, it may have a pathname as argument
     * in which case it will work as the LIST command except no data
     * connection will be created.
     *
     * @param name an optional <code>String</code> containing the pathname
     *        the STAT command should apply to.
     * @return the response from the server or <code>null</code> if the
     *         command failed.
     * @throws IOException if an error occurred during the transmission.
     */
    public String getStatus(String name) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck((name == null ? "STAT" : "STAT " + name));
        /*
         * A typical response will be:
         *  213-status of t32.gif:
         * -rw-r--r--   1 jcc      staff     247445 Feb 17  1998 t32.gif
         * 213 End of Status
         *
         * or
         *
         * 211-jsn FTP server status:
         *     Version wu-2.6.2+Sun
         *     Connected to localhost (::1)
         *     Logged in as jccollet
         *     TYPE: ASCII, FORM: Nonprint; STRUcture: File; transfer MODE: Stream
         *      No data connection
         *     0 data bytes received in 0 files
         *     0 data bytes transmitted in 0 files
         *     0 data bytes total in 0 files
         *     53 traffic bytes received in 0 transfers
         *     485 traffic bytes transmitted in 0 transfers
         *     587 traffic bytes total in 0 transfers
         * 211 End of status
         *
         * So we need to remove the 1st and last line
         */
        Vector<String> resp = getResponseStrings();
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i < resp.size() - 1; i++) {
            sb.append(resp.get(i));
        }
        return sb.toString();
    }

    /**
     * Sends the FEAT command to the server and returns the list of supported
     * features in the form of strings.
     *
     * The features are the supported commands, like AUTH TLS, PROT or PASV.
     * See the RFCs for a complete list.
     *
     * Note that not all FTP servers support that command, in which case
     * the method will return <code>null</code>
     *
     * @return a <code>List</code> of <code>Strings</code> describing the
     *         supported additional features, or <code>null</code>
     *         if the command is not supported.
     * @throws IOException if an error occurs during the transmission.
     */
    public List<String> getFeatures() throws sun.net.ftp.FtpProtocolException, IOException {
        /*
         * The FEAT command, when implemented will return something like:
         *
         * 211-Features:
         *   AUTH TLS
         *   PBSZ
         *   PROT
         *   EPSV
         *   EPRT
         *   PASV
         *   REST STREAM
         *  211 END
         */
        ArrayList<String> features = new ArrayList<String>();
        issueCommandCheck("FEAT");
        Vector<String> resp = getResponseStrings();
        // Note that we start at index 1 to skip the 1st line (211-...)
        // and we stop before the last line.
        for (int i = 1; i < resp.size() - 1; i++) {
            String s = resp.get(i);
            // Get rid of leading space and trailing newline
            features.add(s.substring(1, s.length() - 1));
        }
        return features;
    }

    /**
     * sends the ABOR command to the server.
     * It tells the server to stop the previous command or transfer.
     *
     * @return <code>true</code> if the command was successful.
     * @throws IOException if an error occurred during the transmission.
     */
    public sun.net.ftp.FtpClient abort() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("ABOR");
        // TODO: Must check the ReplyCode:
        /*
         * From the RFC:
         * There are two cases for the server upon receipt of this
         * command: (1) the FTP service command was already completed,
         * or (2) the FTP service command is still in progress.
         * In the first case, the server closes the data connection
         * (if it is open) and responds with a 226 reply, indicating
         * that the abort command was successfully processed.
         * In the second case, the server aborts the FTP service in
         * progress and closes the data connection, returning a 426
         * reply to indicate that the service request terminated
         * abnormally.  The server then sends a 226 reply,
         * indicating that the abort command was successfully
         * processed.
         */


        return this;
    }

    /**
     * Some methods do not wait until completion before returning, so this
     * method can be called to wait until completion. This is typically the case
     * with commands that trigger a transfer like {@link #getFileStream(String)}.
     * So this method should be called before accessing information related to
     * such a command.
     * <p>This method will actually block reading on the command channel for a
     * notification from the server that the command is finished. Such a
     * notification often carries extra information concerning the completion
     * of the pending action (e.g. number of bytes transfered).</p>
     * <p>Note that this will return true immediately if no command or action
     * is pending</p>
     * <p>It should be also noted that most methods issuing commands to the ftp
     * server will call this method if a previous command is pending.
     * <p>Example of use:
     * <pre>
     * InputStream in = cl.getFileStream("file");
     * ...
     * cl.completePending();
     * long size = cl.getLastTransferSize();
     * </pre>
     * On the other hand, it's not necessary in a case like:
     * <pre>
     * InputStream in = cl.getFileStream("file");
     * // read content
     * ...
     * cl.logout();
     * </pre>
     * <p>Since {@link #logout()} will call completePending() if necessary.</p>
     * @return <code>true</code> if the completion was successful or if no
     *         action was pending.
     * @throws IOException
     */
    public sun.net.ftp.FtpClient completePending() throws sun.net.ftp.FtpProtocolException, IOException {
        while (replyPending) {
            replyPending = false;
            if (!readReply()) {
                throw new sun.net.ftp.FtpProtocolException(getLastResponseString(), lastReplyCode);
            }
        }
        return this;
    }

    /**
     * Reinitializes the USER parameters on the FTP server
     *
     * @throws FtpProtocolException if the command fails
     */
    public sun.net.ftp.FtpClient reInit() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("REIN");
        loggedIn = false;
        if (useCrypto) {
            if (server instanceof SSLSocket) {
                javax.net.ssl.SSLSession session = ((SSLSocket) server).getSession();
                session.invalidate();
                // Restore previous socket and streams
                server = oldSocket;
                oldSocket = null;
                try {
                    out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                            true, encoding);
                } catch (UnsupportedEncodingException e) {
                    throw new InternalError(encoding + "encoding not found", e);
                }
                in = new BufferedInputStream(server.getInputStream());
            }
        }
        useCrypto = false;
        return this;
    }

    /**
     * Changes the transfer type (binary, ascii, ebcdic) and issue the
     * proper command (e.g. TYPE A) to the server.
     *
     * @param type the <code>FtpTransferType</code> to use.
     * @return This FtpClient
     * @throws IOException if an error occurs during transmission.
     */
    public sun.net.ftp.FtpClient setType(TransferType type) throws sun.net.ftp.FtpProtocolException, IOException {
        String cmd = "NOOP";

        this.type = type;
        if (type == TransferType.ASCII) {
            cmd = "TYPE A";
        }
        if (type == TransferType.BINARY) {
            cmd = "TYPE I";
        }
        if (type == TransferType.EBCDIC) {
            cmd = "TYPE E";
        }
        issueCommandCheck(cmd);
        return this;
    }

    /**
     * Issues a LIST command to the server to get the current directory
     * listing, and returns the InputStream from the data connection.
     * {@link #completePending()} <b>has</b> to be called once the application
     * is finished writing to the stream.
     *
     * @param path the pathname of the directory to list, or <code>null</code>
     *        for the current working directory.
     * @return the <code>InputStream</code> from the resulting data connection
     * @throws IOException if an error occurs during the transmission.
     * @see #changeDirectory(String)
     * @see #listFiles(String)
     */
    public InputStream list(String path) throws sun.net.ftp.FtpProtocolException, IOException {
        Socket s;
        s = openDataConnection(path == null ? "LIST" : "LIST " + path);
        if (s != null) {
            return createInputStream(s.getInputStream());
        }
        return null;
    }

    /**
     * Issues a NLST path command to server to get the specified directory
     * content. It differs from {@link #list(String)} method by the fact that
     * it will only list the file names which would make the parsing of the
     * somewhat easier.
     *
     * {@link #completePending()} <b>has</b> to be called once the application
     * is finished writing to the stream.
     *
     * @param path a <code>String</code> containing the pathname of the
     *        directory to list or <code>null</code> for the current working
     *        directory.
     * @return the <code>InputStream</code> from the resulting data connection
     * @throws IOException if an error occurs during the transmission.
     */
    public InputStream nameList(String path) throws sun.net.ftp.FtpProtocolException, IOException {
        Socket s;
        s = openDataConnection("NLST " + path);
        if (s != null) {
            return createInputStream(s.getInputStream());
        }
        return null;
    }

    /**
     * Issues the SIZE [path] command to the server to get the size of a
     * specific file on the server.
     * Note that this command may not be supported by the server. In which
     * case -1 will be returned.
     *
     * @param path a <code>String</code> containing the pathname of the
     *        file.
     * @return a <code>long</code> containing the size of the file or -1 if
     *         the server returned an error, which can be checked with
     *         {@link #getLastReplyCode()}.
     * @throws IOException if an error occurs during the transmission.
     */
    public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOException {
        if (path == null || path.length() == 0) {
            throw new IllegalArgumentException("path can't be null or empty");
        }
        issueCommandCheck("SIZE " + path);
        if (lastReplyCode == FtpReplyCode.FILE_STATUS) {
            String s = getResponseString();
            s = s.substring(4, s.length() - 1);
            return Long.parseLong(s);
        }
        return -1;
    }
    private static String[] MDTMformats = {
        "yyyyMMddHHmmss.SSS",
        "yyyyMMddHHmmss"
    };
    private static SimpleDateFormat[] dateFormats = new SimpleDateFormat[MDTMformats.length];

    static {
        for (int i = 0; i < MDTMformats.length; i++) {
            dateFormats[i] = new SimpleDateFormat(MDTMformats[i]);
            dateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
        }
    }

    /**
     * Issues the MDTM [path] command to the server to get the modification
     * time of a specific file on the server.
     * Note that this command may not be supported by the server, in which
     * case <code>null</code> will be returned.
     *
     * @param path a <code>String</code> containing the pathname of the file.
     * @return a <code>Date</code> representing the last modification time
     *         or <code>null</code> if the server returned an error, which
     *         can be checked with {@link #getLastReplyCode()}.
     * @throws IOException if an error occurs during the transmission.
     */
    public Date getLastModified(String path) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("MDTM " + path);
        if (lastReplyCode == FtpReplyCode.FILE_STATUS) {
            String s = getResponseString().substring(4);
            Date d = null;
            for (SimpleDateFormat dateFormat : dateFormats) {
                try {
                    d = dateFormat.parse(s);
                } catch (ParseException ex) {
                }
                if (d != null) {
                    return d;
                }
            }
        }
        return null;
    }

    /**
     * Sets the parser used to handle the directory output to the specified
     * one. By default the parser is set to one that can handle most FTP
     * servers output (Unix base mostly). However it may be necessary for
     * and application to provide its own parser due to some uncommon
     * output format.
     *
     * @param p The <code>FtpDirParser</code> to use.
     * @see #listFiles(String)
     */
    public sun.net.ftp.FtpClient setDirParser(FtpDirParser p) {
        parser = p;
        return this;
    }

    private class FtpFileIterator implements Iterator<FtpDirEntry>, Closeable {

        private BufferedReader in = null;
        private FtpDirEntry nextFile = null;
        private FtpDirParser fparser = null;
        private boolean eof = false;

        public FtpFileIterator(FtpDirParser p, BufferedReader in) {
            this.in = in;
            this.fparser = p;
            readNext();
        }

        private void readNext() {
            nextFile = null;
            if (eof) {
                return;
            }
            String line = null;
            try {
                do {
                    line = in.readLine();
                    if (line != null) {
                        nextFile = fparser.parseLine(line);
                        if (nextFile != null) {
                            return;
                        }
                    }
                } while (line != null);
                in.close();
            } catch (IOException iOException) {
            }
            eof = true;
        }

        public boolean hasNext() {
            return nextFile != null;
        }

        public FtpDirEntry next() {
            FtpDirEntry ret = nextFile;
            readNext();
            return ret;
        }

        public void remove() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void close() throws IOException {
            if (in != null && !eof) {
                in.close();
            }
            eof = true;
            nextFile = null;
        }
    }

    /**
     * Issues a MLSD command to the server to get the specified directory
     * listing and applies the current parser to create an Iterator of
     * {@link java.net.ftp.FtpDirEntry}. Note that the Iterator returned is also a
     * {@link java.io.Closeable}.
     * If the server doesn't support the MLSD command, the LIST command is used
     * instead.
     *
     * {@link #completePending()} <b>has</b> to be called once the application
     * is finished iterating through the files.
     *
     * @param path the pathname of the directory to list or <code>null</code>
     *        for the current working directoty.
     * @return a <code>Iterator</code> of files or <code>null</code> if the
     *         command failed.
     * @throws IOException if an error occurred during the transmission
     * @see #setDirParser(FtpDirParser)
     * @see #changeDirectory(String)
     */
    public Iterator<FtpDirEntry> listFiles(String path) throws sun.net.ftp.FtpProtocolException, IOException {
        Socket s = null;
        BufferedReader sin = null;
        try {
            s = openDataConnection(path == null ? "MLSD" : "MLSD " + path);
        } catch (sun.net.ftp.FtpProtocolException FtpException) {
            // The server doesn't understand new MLSD command, ignore and fall
            // back to LIST
        }

        if (s != null) {
            sin = new BufferedReader(new InputStreamReader(s.getInputStream()));
            return new FtpFileIterator(mlsxParser, sin);
        } else {
            s = openDataConnection(path == null ? "LIST" : "LIST " + path);
            if (s != null) {
                sin = new BufferedReader(new InputStreamReader(s.getInputStream()));
                return new FtpFileIterator(parser, sin);
            }
        }
        return null;
    }

    private boolean sendSecurityData(byte[] buf) throws IOException {
        BASE64Encoder encoder = new BASE64Encoder();
        String s = encoder.encode(buf);
        return issueCommand("ADAT " + s);
    }

    private byte[] getSecurityData() {
        String s = getLastResponseString();
        if (s.substring(4, 9).equalsIgnoreCase("ADAT=")) {
            BASE64Decoder decoder = new BASE64Decoder();
            try {
                // Need to get rid of the leading '315 ADAT='
                // and the trailing newline
                return decoder.decodeBuffer(s.substring(9, s.length() - 1));
            } catch (IOException e) {
                //
            }
        }
        return null;
    }

    /**
     * Attempts to use Kerberos GSSAPI as an authentication mechanism with the
     * ftp server. This will issue an <code>AUTH GSSAPI</code> command, and if
     * it is accepted by the server, will followup with <code>ADAT</code>
     * command to exchange the various tokens until authentification is
     * successful. This conforms to Appendix I of RFC 2228.
     *
     * @return <code>true</code> if authentication was successful.
     * @throws IOException if an error occurs during the transmission.
     */
    public sun.net.ftp.FtpClient useKerberos() throws sun.net.ftp.FtpProtocolException, IOException {
        /*
         * Comment out for the moment since it's not in use and would create
         * needless cross-package links.
         *
        issueCommandCheck("AUTH GSSAPI");
        if (lastReplyCode != FtpReplyCode.NEED_ADAT)
        throw new sun.net.ftp.FtpProtocolException("Unexpected reply from server");
        try {
        GSSManager manager = GSSManager.getInstance();
        GSSName name = manager.createName("SERVICE:ftp@"+
        serverAddr.getHostName(), null);
        GSSContext context = manager.createContext(name, null, null,
        GSSContext.DEFAULT_LIFETIME);
        context.requestMutualAuth(true);
        context.requestReplayDet(true);
        context.requestSequenceDet(true);
        context.requestCredDeleg(true);
        byte []inToken = new byte[0];
        while (!context.isEstablished()) {
        byte[] outToken
        = context.initSecContext(inToken, 0, inToken.length);
        // send the output token if generated
        if (outToken != null) {
        if (sendSecurityData(outToken)) {
        inToken = getSecurityData();
        }
        }
        }
        loggedIn = true;
        } catch (GSSException e) {

        }
         */
        return this;
    }

    /**
     * Returns the Welcome string the server sent during initial connection.
     *
     * @return a <code>String</code> containing the message the server
     *         returned during connection or <code>null</code>.
     */
    public String getWelcomeMsg() {
        return welcomeMsg;
    }

    /**
     * Returns the last reply code sent by the server.
     *
     * @return the lastReplyCode
     */
    public FtpReplyCode getLastReplyCode() {
        return lastReplyCode;
    }

    /**
     * Returns the last response string sent by the server.
     *
     * @return the message string, which can be quite long, last returned
     *         by the server.
     */
    public String getLastResponseString() {
        StringBuffer sb = new StringBuffer();
        if (serverResponse != null) {
            for (String l : serverResponse) {
                if (l != null) {
                    sb.append(l);
                }
            }
        }
        return sb.toString();
    }

    /**
     * Returns, when available, the size of the latest started transfer.
     * This is retreived by parsing the response string received as an initial
     * response to a RETR or similar request.
     *
     * @return the size of the latest transfer or -1 if either there was no
     *         transfer or the information was unavailable.
     */
    public long getLastTransferSize() {
        return lastTransSize;
    }

    /**
     * Returns, when available, the remote name of the last transfered file.
     * This is mainly useful for "put" operation when the unique flag was
     * set since it allows to recover the unique file name created on the
     * server which may be different from the one submitted with the command.
     *
     * @return the name the latest transfered file remote name, or
     *         <code>null</code> if that information is unavailable.
     */
    public String getLastFileName() {
        return lastFileName;
    }

    /**
     * Attempts to switch to a secure, encrypted connection. This is done by
     * sending the "AUTH TLS" command.
     * <p>See <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a></p>
     * If successful this will establish a secure command channel with the
     * server, it will also make it so that all other transfers (e.g. a RETR
     * command) will be done over an encrypted channel as well unless a
     * {@link #reInit()} command or a {@link #endSecureSession()} command is issued.
     *
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during the transmission.
     * @see #endSecureSession()
     */
    public sun.net.ftp.FtpClient startSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
        if (!isConnected()) {
            throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
        }
        if (sslFact == null) {
            try {
                sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
            } catch (Exception e) {
                throw new IOException(e.getLocalizedMessage());
            }
        }
        issueCommandCheck("AUTH TLS");
        Socket s = null;
        try {
            s = sslFact.createSocket(server, serverAddr.getHostName(), serverAddr.getPort(), true);
        } catch (javax.net.ssl.SSLException ssle) {
            try {
                disconnect();
            } catch (Exception e) {
            }
            throw ssle;
        }
        // Remember underlying socket so we can restore it later
        oldSocket = server;
        server = s;
        try {
            out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                    true, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(encoding + "encoding not found", e);
        }
        in = new BufferedInputStream(server.getInputStream());

        issueCommandCheck("PBSZ 0");
        issueCommandCheck("PROT P");
        useCrypto = true;
        return this;
    }

    /**
     * Sends a <code>CCC</code> command followed by a <code>PROT C</code>
     * command to the server terminating an encrypted session and reverting
     * back to a non crypted transmission.
     *
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during transmission.
     * @see #startSecureSession()
     */
    public sun.net.ftp.FtpClient endSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
        if (!useCrypto) {
            return this;
        }

        issueCommandCheck("CCC");
        issueCommandCheck("PROT C");
        useCrypto = false;
        // Restore previous socket and streams
        server = oldSocket;
        oldSocket = null;
        try {
            out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
                    true, encoding);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(encoding + "encoding not found", e);
        }
        in = new BufferedInputStream(server.getInputStream());

        return this;
    }

    /**
     * Sends the "Allocate" (ALLO) command to the server telling it to
     * pre-allocate the specified number of bytes for the next transfer.
     *
     * @param size The number of bytes to allocate.
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during the transmission.
     */
    public sun.net.ftp.FtpClient allocate(long size) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("ALLO " + size);
        return this;
    }

    /**
     * Sends the "Structure Mount" (SMNT) command to the server. This let the
     * user mount a different file system data structure without altering his
     * login or accounting information.
     *
     * @param struct a <code>String</code> containing the name of the
     *        structure to mount.
     * @return <code>true</code> if the operation was successful.
     * @throws IOException if an error occurred during the transmission.
     */
    public sun.net.ftp.FtpClient structureMount(String struct) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("SMNT " + struct);
        return this;
    }

    /**
     * Sends a SYST (System) command to the server and returns the String
     * sent back by the server describing the operating system at the
     * server.
     *
     * @return a <code>String</code> describing the OS, or <code>null</code>
     *         if the operation was not successful.
     * @throws IOException if an error occurred during the transmission.
     */
    public String getSystem() throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("SYST");
        /*
         * 215 UNIX Type: L8 Version: SUNOS
         */
        String resp = getResponseString();
        // Get rid of the leading code and blank
        return resp.substring(4);
    }

    /**
     * Sends the HELP command to the server, with an optional command, like
     * SITE, and returns the text sent back by the server.
     *
     * @param cmd the command for which the help is requested or
     *        <code>null</code> for the general help
     * @return a <code>String</code> containing the text sent back by the
     *         server, or <code>null</code> if the command failed.
     * @throws IOException if an error occurred during transmission
     */
    public String getHelp(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("HELP " + cmd);
        /**
         *
         * HELP
         * 214-The following commands are implemented.
         *   USER    EPRT    STRU    ALLO    DELE    SYST    RMD     MDTM    ADAT
         *   PASS    EPSV    MODE    REST    CWD     STAT    PWD     PROT
         *   QUIT    LPRT    RETR    RNFR    LIST    HELP    CDUP    PBSZ
         *   PORT    LPSV    STOR    RNTO    NLST    NOOP    STOU    AUTH
         *   PASV    TYPE    APPE    ABOR    SITE    MKD     SIZE    CCC
         * 214 Direct comments to ftp-bugs@jsn.
         *
         * HELP SITE
         * 214-The following SITE commands are implemented.
         *   UMASK           HELP            GROUPS
         *   IDLE            ALIAS           CHECKMETHOD
         *   CHMOD           CDPATH          CHECKSUM
         * 214 Direct comments to ftp-bugs@jsn.
         */
        Vector<String> resp = getResponseStrings();
        if (resp.size() == 1) {
            // Single line response
            return resp.get(0).substring(4);
        }
        // on multiple lines answers, like the ones above, remove 1st and last
        // line, concat the the others.
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i < resp.size() - 1; i++) {
            sb.append(resp.get(i).substring(3));
        }
        return sb.toString();
    }

    /**
     * Sends the SITE command to the server. This is used by the server
     * to provide services specific to his system that are essential
     * to file transfer.
     *
     * @param cmd the command to be sent.
     * @return <code>true</code> if the command was successful.
     * @throws IOException if an error occurred during transmission
     */
    public sun.net.ftp.FtpClient siteCmd(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
        issueCommandCheck("SITE " + cmd);
        return this;
    }
}
