    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.net.ftp;
    018    import java.io.BufferedInputStream;
    019    import java.io.BufferedOutputStream;
    020    import java.io.BufferedReader;
    021    import java.io.BufferedWriter;
    022    import java.io.IOException;
    023    import java.io.InputStream;
    024    import java.io.InputStreamReader;
    025    import java.io.OutputStream;
    026    import java.io.OutputStreamWriter;
    027    import java.net.Inet6Address;
    028    import java.net.InetAddress;
    029    import java.net.InetSocketAddress;
    030    import java.net.ServerSocket;
    031    import java.net.Socket;
    032    import java.net.SocketException;
    033    import java.net.SocketTimeoutException;
    034    import java.net.UnknownHostException;
    035    import java.util.ArrayList;
    036    import java.util.HashMap;
    037    import java.util.HashSet;
    038    import java.util.Locale;
    039    import java.util.Properties;
    040    import java.util.Random;
    041    import java.util.Set;
    042
    043    import org.apache.commons.net.MalformedServerReplyException;
    044    import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
    045    import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
    046    import org.apache.commons.net.ftp.parser.MLSxEntryParser;
    047    import org.apache.commons.net.io.CRLFLineReader;
    048    import org.apache.commons.net.io.CopyStreamAdapter;
    049    import org.apache.commons.net.io.CopyStreamEvent;
    050    import org.apache.commons.net.io.CopyStreamListener;
    051    import org.apache.commons.net.io.FromNetASCIIInputStream;
    052    import org.apache.commons.net.io.ToNetASCIIOutputStream;
    053    import org.apache.commons.net.io.Util;
    054
    055    /***
    056     * FTPClient encapsulates all the functionality necessary to store and
    057     * retrieve files from an FTP server.  This class takes care of all
    058     * low level details of interacting with an FTP server and provides
    059     * a convenient higher level interface.  As with all classes derived
    060     * from {@link org.apache.commons.net.SocketClient},
    061     * you must first connect to the server with
    062     * {@link org.apache.commons.net.SocketClient#connect  connect }
    063     * before doing anything, and finally
    064     * {@link org.apache.commons.net.SocketClient#disconnect  disconnect }
    065     * after you're completely finished interacting with the server.
    066     * Then you need to check the FTP reply code to see if the connection
    067     * was successful.  For example:
    068     * <pre>
    069     *    boolean error = false;
    070     *    try {
    071     *      int reply;
    072     *      ftp.connect("ftp.foobar.com");
    073     *      System.out.println("Connected to " + server + ".");
    074     *      System.out.print(ftp.getReplyString());
    075     *
    076     *      // After connection attempt, you should check the reply code to verify
    077     *      // success.
    078     *      reply = ftp.getReplyCode();
    079     *
    080     *      if(!FTPReply.isPositiveCompletion(reply)) {
    081     *        ftp.disconnect();
    082     *        System.err.println("FTP server refused connection.");
    083     *        System.exit(1);
    084     *      }
    085     *      ... // transfer files
    086     *      ftp.logout();
    087     *    } catch(IOException e) {
    088     *      error = true;
    089     *      e.printStackTrace();
    090     *    } finally {
    091     *      if(ftp.isConnected()) {
    092     *        try {
    093     *          ftp.disconnect();
    094     *        } catch(IOException ioe) {
    095     *          // do nothing
    096     *        }
    097     *      }
    098     *      System.exit(error ? 1 : 0);
    099     *    }
    100     * </pre>
    101     * <p>
    102     * Immediately after connecting is the only real time you need to check the
    103     * reply code (because connect is of type void).  The convention for all the
    104     * FTP command methods in FTPClient is such that they either return a
    105     * boolean value or some other value.
    106     * The boolean methods return true on a successful completion reply from
    107     * the FTP server and false on a reply resulting in an error condition or
    108     * failure.  The methods returning a value other than boolean return a value
    109     * containing the higher level data produced by the FTP command, or null if a
    110     * reply resulted in an error condition or failure.  If you want to access
    111     * the exact FTP reply code causing a success or failure, you must call
    112     * {@link org.apache.commons.net.ftp.FTP#getReplyCode  getReplyCode } after
    113     * a success or failure.
    114     * <p>
    115     * The default settings for FTPClient are for it to use
    116     * <code> FTP.ASCII_FILE_TYPE </code>,
    117     * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    118     * <code> FTP.STREAM_TRANSFER_MODE </code>, and
    119     * <code> FTP.FILE_STRUCTURE </code>.  The only file types directly supported
    120     * are <code> FTP.ASCII_FILE_TYPE </code> and
    121     * <code> FTP.BINARY_FILE_TYPE </code>.  Because there are at least 4
    122     * different EBCDIC encodings, we have opted not to provide direct support
    123     * for EBCDIC.  To transfer EBCDIC and other unsupported file types you
    124     * must create your own filter InputStreams and OutputStreams and wrap
    125     * them around the streams returned or required by the FTPClient methods.
    126     * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
    127     * filter streams to provide transparent handling of ASCII files.  We will
    128     * consider incorporating EBCDIC support if there is enough demand.
    129     * <p>
    130     * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    131     * <code> FTP.STREAM_TRANSFER_MODE </code>, and
    132     * <code> FTP.FILE_STRUCTURE </code> are the only supported formats,
    133     * transfer modes, and file structures.
    134     * <p>
    135     * Because the handling of sockets on different platforms can differ
    136     * significantly, the FTPClient automatically issues a new PORT (or EPRT) command
    137     * prior to every transfer requiring that the server connect to the client's
    138     * data port.  This ensures identical problem-free behavior on Windows, Unix,
    139     * and Macintosh platforms.  Additionally, it relieves programmers from
    140     * having to issue the PORT (or EPRT) command themselves and dealing with platform
    141     * dependent issues.
    142     * <p>
    143     * Additionally, for security purposes, all data connections to the
    144     * client are verified to ensure that they originated from the intended
    145     * party (host and port).  If a data connection is initiated by an unexpected
    146     * party, the command will close the socket and throw an IOException.  You
    147     * may disable this behavior with
    148     * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
    149     * <p>
    150     * You should keep in mind that the FTP server may choose to prematurely
    151     * close a connection if the client has been idle for longer than a
    152     * given time period (usually 900 seconds).  The FTPClient class will detect a
    153     * premature FTP server connection closing when it receives a
    154     * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
    155     *  response to a command.
    156     * When that occurs, the FTP class method encountering that reply will throw
    157     * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
    158     * .
    159     * <code>FTPConnectionClosedException</code>
    160     * is a subclass of <code> IOException </code> and therefore need not be
    161     * caught separately, but if you are going to catch it separately, its
    162     * catch block must appear before the more general <code> IOException </code>
    163     * catch block.  When you encounter an
    164     * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
    165     * , you must disconnect the connection with
    166     * {@link #disconnect  disconnect() } to properly clean up the
    167     * system resources used by FTPClient.  Before disconnecting, you may check the
    168     * last reply code and text with
    169     * {@link org.apache.commons.net.ftp.FTP#getReplyCode  getReplyCode },
    170     * {@link org.apache.commons.net.ftp.FTP#getReplyString  getReplyString },
    171     * and
    172     * {@link org.apache.commons.net.ftp.FTP#getReplyStrings  getReplyStrings}.
    173     * You may avoid server disconnections while the client is idle by
    174     * periodically sending NOOP commands to the server.
    175     * <p>
    176     * Rather than list it separately for each method, we mention here that
    177     * every method communicating with the server and throwing an IOException
    178     * can also throw a
    179     * {@link org.apache.commons.net.MalformedServerReplyException}
    180     * , which is a subclass
    181     * of IOException.  A MalformedServerReplyException will be thrown when
    182     * the reply received from the server deviates enough from the protocol
    183     * specification that it cannot be interpreted in a useful manner despite
    184     * attempts to be as lenient as possible.
    185     * <p>
    186     * Listing API Examples
    187     * Both paged and unpaged examples of directory listings are available,
    188     * as follows:
    189     * <p>
    190     * Unpaged (whole list) access, using a parser accessible by auto-detect:
    191     * <pre>
    192     *    FTPClient f = new FTPClient();
    193     *    f.connect(server);
    194     *    f.login(username, password);
    195     *    FTPFile[] files = listFiles(directory);
    196     * </pre>
    197     * <p>
    198     * Paged access, using a parser not accessible by auto-detect.  The class
    199     * defined in the first parameter of initateListParsing should be derived
    200     * from org.apache.commons.net.FTPFileEntryParser:
    201     * <pre>
    202     *    FTPClient f = new FTPClient();
    203     *    f.connect(server);
    204     *    f.login(username, password);
    205     *    FTPListParseEngine engine =
    206     *       f.initiateListParsing("com.whatever.YourOwnParser", directory);
    207     *
    208     *    while (engine.hasNext()) {
    209     *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    210     *       //do whatever you want with these files, display them, etc.
    211     *       //expensive FTPFile objects not created until needed.
    212     *    }
    213     * </pre>
    214     * <p>
    215     * Paged access, using a parser accessible by auto-detect:
    216     * <pre>
    217     *    FTPClient f = new FTPClient();
    218     *    f.connect(server);
    219     *    f.login(username, password);
    220     *    FTPListParseEngine engine = f.initiateListParsing(directory);
    221     *
    222     *    while (engine.hasNext()) {
    223     *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    224     *       //do whatever you want with these files, display them, etc.
    225     *       //expensive FTPFile objects not created until needed.
    226     *    }
    227     * </pre>
    228     * <p>
    229     * For examples of using FTPClient on servers whose directory listings
    230     * <ul>
    231     * <li>use languages other than English</li>
    232     * <li>use date formats other than the American English "standard" <code>MM d yyyy</code></li>
    233     * <li>are in different timezones and you need accurate timestamps for dependency checking
    234     *     as in Ant</li>
    235     * </ul>see {@link  FTPClientConfig  FTPClientConfig}.
    236     * <p>
    237     * <b>Control channel keep-alive feature</b>:<br/>
    238     * During file transfers, the data connection is busy, but the control connection is idle.
    239     * FTP servers know that the control connection is in use, so won't close it through lack of activity,
    240     * but it's a lot harder for network routers to know that the control and data connections are associated
    241     * with each other.
    242     * Some routers may treat the control connection as idle, and disconnect it if the transfer over the data
    243     * connection takes longer than the allowable idle time for the router.
    244     * <br/>
    245     * One solution to this is to send a safe command (i.e. NOOP) over the control connection to reset the router's
    246     * idle timer. This is enabled as follows:
    247     * <pre>
    248     *     ftpClient.setControlKeepAliveTimeout(300); // set timeout to 5 minutes
    249     * </pre>
    250     * This will cause the file upload/download methods to send a NOOP approximately every 5 minutes.
    251     * <p>
    252     * The implementation currently uses a {@link CopyStreamListener} which is passed to the
    253     * {@link Util#copyStream(InputStream, OutputStream, int, long, CopyStreamListener, boolean)}
    254     * method, so the timing is partially dependent on how long each block transfer takes.
    255     * <p>
    256     * <b>Note:</b> this does not apply to the methods where the user is responsible for writing or reading
    257     * the data stream, i.e. {@link #retrieveFileStream(String)} , {@link #storeFileStream(String)}
    258     * and the other xxxFileStream methods
    259     * <p>
    260     *
    261     * @see #FTP_SYSTEM_TYPE
    262     * @see #SYSTEM_TYPE_PROPERTIES
    263     * @see FTP
    264     * @see FTPConnectionClosedException
    265     * @see FTPFileEntryParser
    266     * @see FTPFileEntryParserFactory
    267     * @see DefaultFTPFileEntryParserFactory
    268     * @see FTPClientConfig
    269     *
    270     * @see org.apache.commons.net.MalformedServerReplyException
    271     **/
    272    public class FTPClient extends FTP
    273    implements Configurable
    274    {
    275        /**
    276         * The system property ({@value}) which can be used to override the system type.<br/>
    277         * If defined, the value will be used to create any automatically created parsers.
    278         *
    279         * @since 3.0
    280         */
    281        public static final String FTP_SYSTEM_TYPE = "org.apache.commons.net.ftp.systemType";
    282
    283        /**
    284         * The system property ({@value}) which can be used as the default system type.<br/>
    285         * If defined, the value will be used if the SYST command fails.
    286         *
    287         * @since 3.1
    288         */
    289        public static final String FTP_SYSTEM_TYPE_DEFAULT = "org.apache.commons.net.ftp.systemType.default";
    290
    291        /**
    292         * The name of an optional systemType properties file ({@value}), which is loaded
    293         * using {@link Class#getResourceAsStream(String)}.<br/>
    294         * The entries are the systemType (as determined by {@link FTPClient#getSystemType})
    295         * and the values are the replacement type or parserClass, which is passed to
    296         * {@link FTPFileEntryParserFactory#createFileEntryParser(String)}.<br/>
    297         * For example:
    298         * <pre>
    299         * Plan 9=Unix
    300         * OS410=org.apache.commons.net.ftp.parser.OS400FTPEntryParser
    301         * </pre>
    302         *
    303         * @since 3.0
    304         */
    305        public static final String SYSTEM_TYPE_PROPERTIES = "/systemType.properties";
    306
    307        /***
    308         * A constant indicating the FTP session is expecting all transfers
    309         * to occur between the client (local) and server and that the server
    310         * should connect to the client's data port to initiate a data transfer.
    311         * This is the default data connection mode when and FTPClient instance
    312         * is created.
    313         ***/
    314        public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
    315        /***
    316         * A constant indicating the FTP session is expecting all transfers
    317         * to occur between two remote servers and that the server
    318         * the client is connected to should connect to the other server's
    319         * data port to initiate a data transfer.
    320         ***/
    321        public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
    322        /***
    323         * A constant indicating the FTP session is expecting all transfers
    324         * to occur between the client (local) and server and that the server
    325         * is in passive mode, requiring the client to connect to the
    326         * server's data port to initiate a transfer.
    327         ***/
    328        public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
    329        /***
    330         * A constant indicating the FTP session is expecting all transfers
    331         * to occur between two remote servers and that the server
    332         * the client is connected to is in passive mode, requiring the other
    333         * server to connect to the first server's data port to initiate a data
    334         * transfer.
    335         ***/
    336        public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
    337
    338        private int __dataConnectionMode, __dataTimeout;
    339        private int __passivePort;
    340        private String __passiveHost;
    341        private final Random __random;
    342        private int __activeMinPort, __activeMaxPort;
    343        private InetAddress __activeExternalHost;
    344        private InetAddress __reportActiveExternalHost; // overrides __activeExternalHost in EPRT/PORT commands
    345
    346        private int __fileType;
    347        @SuppressWarnings("unused") // fields are written, but currently not read
    348        private int __fileFormat, __fileStructure, __fileTransferMode;
    349        private boolean __remoteVerificationEnabled;
    350        private long __restartOffset;
    351        private FTPFileEntryParserFactory __parserFactory;
    352        private int __bufferSize;
    353        private boolean __listHiddenFiles;
    354        private boolean __useEPSVwithIPv4; // whether to attempt EPSV with an IPv4 connection
    355
    356        // __systemName is a cached value that should not be referenced directly
    357        // except when assigned in getSystemName and __initDefaults.
    358        private String __systemName;
    359
    360        // __entryParser is a cached value that should not be referenced directly
    361        // except when assigned in listFiles(String, String) and __initDefaults.
    362        private FTPFileEntryParser __entryParser;
    363
    364        // Key used to create the parser; necessary to ensure that the parser type is not ignored
    365        private String __entryParserKey;
    366
    367        private FTPClientConfig __configuration;
    368
    369        // Listener used by store/retrieve methods to handle keepalive
    370        private CopyStreamListener __copyStreamListener;
    371
    372        // How long to wait before sending another control keep-alive message
    373        private long __controlKeepAliveTimeout;
    374
    375        // How long to wait (ms) for keepalive message replies before continuing
    376        // Most FTP servers don't seem to support concurrent control and data connection usage
    377        private int __controlKeepAliveReplyTimeout=1000;
    378
    379        /** Pattern for PASV mode responses. Groups: (n,n,n,n),(n),(n) */
    380        private static final java.util.regex.Pattern __PARMS_PAT;
    381        static {
    382            __PARMS_PAT = java.util.regex.Pattern.compile(
    383                    "(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})");
    384        }
    385
    386        /** Controls the automatic server encoding detection (only UTF-8 supported). */
    387        private boolean __autodetectEncoding = false;
    388
    389        /** Map of FEAT responses. If null, has not been initialised. */
    390        private HashMap<String, Set<String>> __featuresMap;
    391
    392        private static class PropertiesSingleton {
    393
    394            static final Properties PROPERTIES;
    395
    396            static {
    397                InputStream resourceAsStream = FTPClient.class.getResourceAsStream(SYSTEM_TYPE_PROPERTIES);
    398                Properties p = null;
    399                if (resourceAsStream != null) {
    400                    p = new Properties();
    401                    try {
    402                        p.load(resourceAsStream);
    403                    } catch (IOException e) {
    404                    } finally {
    405                        try {
    406                            resourceAsStream.close();
    407                        } catch (IOException e) {
    408                            // Ignored
    409                        }
    410                    }
    411                }
    412                PROPERTIES = p;
    413            }
    414
    415        }
    416        private static Properties getOverrideProperties(){
    417            return PropertiesSingleton.PROPERTIES;
    418        }
    419
    420        /**
    421         * Default FTPClient constructor.  Creates a new FTPClient instance
    422         * with the data connection mode set to
    423         * <code> ACTIVE_LOCAL_DATA_CONNECTION_MODE </code>, the file type
    424         * set to <code> FTP.ASCII_FILE_TYPE </code>, the
    425         * file format set to <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    426         * the file structure set to <code> FTP.FILE_STRUCTURE </code>, and
    427         * the transfer mode set to <code> FTP.STREAM_TRANSFER_MODE </code>.
    428         * <p>
    429         * The list parsing auto-detect feature can be configured to use lenient future
    430         * dates (short dates may be up to one day in the future) as follows:
    431         * <pre>
    432         * FTPClient ftp = new FTPClient();
    433         * FTPClientConfig config = new FTPClientConfig();
    434         * config.setLenientFutureDates(true);
    435         * ftp.configure(config );
    436         * </pre>
    437         **/
    438        public FTPClient()
    439        {
    440            __initDefaults();
    441            __dataTimeout = -1;
    442            __remoteVerificationEnabled = true;
    443            __parserFactory = new DefaultFTPFileEntryParserFactory();
    444            __configuration      = null;
    445            __listHiddenFiles = false;
    446            __useEPSVwithIPv4 = false;
    447            __random = new Random();
    448        }
    449
    450
    451        private void __initDefaults()
    452        {
    453            __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
    454            __passiveHost        = null;
    455            __passivePort        = -1;
    456            __activeExternalHost = null;
    457            __reportActiveExternalHost = null;
    458            __activeMinPort = 0;
    459            __activeMaxPort = 0;
    460            __fileType           = FTP.ASCII_FILE_TYPE;
    461            __fileStructure      = FTP.FILE_STRUCTURE;
    462            __fileFormat         = FTP.NON_PRINT_TEXT_FORMAT;
    463            __fileTransferMode   = FTP.STREAM_TRANSFER_MODE;
    464            __restartOffset      = 0;
    465            __systemName         = null;
    466            __entryParser        = null;
    467            __entryParserKey    = "";
    468            __bufferSize         = Util.DEFAULT_COPY_BUFFER_SIZE;
    469            __featuresMap = null;
    470        }
    471
    472        private String __parsePathname(String reply)
    473        {
    474            int begin = reply.indexOf('"') + 1;
    475            int end = reply.indexOf('"', begin);
    476
    477            return reply.substring(begin, end);
    478        }
    479
    480
    481        protected void _parsePassiveModeReply(String reply)
    482        throws MalformedServerReplyException
    483        {
    484            java.util.regex.Matcher m = __PARMS_PAT.matcher(reply);
    485            if (!m.find()) {
    486                throw new MalformedServerReplyException(
    487                        "Could not parse passive host information.\nServer Reply: " + reply);
    488            }
    489
    490            __passiveHost = m.group(1).replace(',', '.'); // Fix up to look like IP address
    491
    492            try
    493            {
    494                int oct1 = Integer.parseInt(m.group(2));
    495                int oct2 = Integer.parseInt(m.group(3));
    496                __passivePort = (oct1 << 8) | oct2;
    497            }
    498            catch (NumberFormatException e)
    499            {
    500                throw new MalformedServerReplyException(
    501                        "Could not parse passive port information.\nServer Reply: " + reply);
    502            }
    503
    504            try {
    505                InetAddress host = InetAddress.getByName(__passiveHost);
    506                // reply is a local address, but target is not - assume NAT box changed the PASV reply
    507                if (host.isSiteLocalAddress() && !getRemoteAddress().isSiteLocalAddress()){
    508                    String hostAddress = getRemoteAddress().getHostAddress();
    509                    fireReplyReceived(0,
    510                                "[Replacing site local address "+__passiveHost+" with "+hostAddress+"]\n");
    511                    __passiveHost = hostAddress;
    512                }
    513            } catch (UnknownHostException e) { // Should not happen as we are passing in an IP address
    514                throw new MalformedServerReplyException(
    515                        "Could not parse passive host information.\nServer Reply: " + reply);
    516            }
    517        }
    518
    519        protected void _parseExtendedPassiveModeReply(String reply)
    520        throws MalformedServerReplyException
    521        {
    522            reply = reply.substring(reply.indexOf('(') + 1,
    523                    reply.indexOf(')')).trim();
    524
    525            char delim1, delim2, delim3, delim4;
    526            delim1 = reply.charAt(0);
    527            delim2 = reply.charAt(1);
    528            delim3 = reply.charAt(2);
    529            delim4 = reply.charAt(reply.length()-1);
    530
    531            if (!(delim1 == delim2) || !(delim2 == delim3)
    532                    || !(delim3 == delim4)) {
    533                throw new MalformedServerReplyException(
    534                        "Could not parse extended passive host information.\nServer Reply: " + reply);
    535            }
    536
    537            int port;
    538            try
    539            {
    540                port = Integer.parseInt(reply.substring(3, reply.length()-1));
    541            }
    542            catch (NumberFormatException e)
    543            {
    544                throw new MalformedServerReplyException(
    545                        "Could not parse extended passive host information.\nServer Reply: " + reply);
    546            }
    547
    548
    549            // in EPSV mode, the passive host address is implicit
    550            __passiveHost = getRemoteAddress().getHostAddress();
    551            __passivePort = port;
    552        }
    553
    554        private boolean __storeFile(int command, String remote, InputStream local)
    555        throws IOException
    556        {
    557            return _storeFile(FTPCommand.getCommand(command), remote, local);
    558        }
    559
    560        protected boolean _storeFile(String command, String remote, InputStream local)
    561        throws IOException
    562        {
    563            Socket socket;
    564
    565            if ((socket = _openDataConnection_(command, remote)) == null) {
    566                return false;
    567            }
    568
    569            OutputStream output = new BufferedOutputStream(socket.getOutputStream(), getBufferSize());
    570
    571            if (__fileType == ASCII_FILE_TYPE) {
    572                output = new ToNetASCIIOutputStream(output);
    573            }
    574
    575            CSL csl = null;
    576            if (__controlKeepAliveTimeout > 0) {
    577                csl = new CSL(this, __controlKeepAliveTimeout, __controlKeepAliveReplyTimeout);
    578            }
    579
    580            // Treat everything else as binary for now
    581            try
    582            {
    583                Util.copyStream(local, output, getBufferSize(),
    584                        CopyStreamEvent.UNKNOWN_STREAM_SIZE, __mergeListeners(csl),
    585                        false);
    586            }
    587            catch (IOException e)
    588            {
    589                Util.closeQuietly(socket); // ignore close errors here
    590                throw e;
    591            }
    592
    593            output.close(); // ensure the file is fully written
    594            socket.close(); // done writing the file
    595            if (csl != null) {
    596                csl.cleanUp(); // fetch any outstanding keepalive replies
    597            }
    598            // Get the transfer response
    599            boolean ok = completePendingCommand();
    600            return ok;
    601        }
    602
    603        private OutputStream __storeFileStream(int command, String remote)
    604        throws IOException
    605        {
    606            return _storeFileStream(FTPCommand.getCommand(command), remote);
    607        }
    608
    609        protected OutputStream _storeFileStream(String command, String remote)
    610        throws IOException
    611        {
    612            Socket socket;
    613
    614            if ((socket = _openDataConnection_(command, remote)) == null) {
    615                return null;
    616            }
    617
    618            OutputStream output = socket.getOutputStream();
    619            if (__fileType == ASCII_FILE_TYPE) {
    620                // We buffer ascii transfers because the buffering has to
    621                // be interposed between ToNetASCIIOutputSream and the underlying
    622                // socket output stream.  We don't buffer binary transfers
    623                // because we don't want to impose a buffering policy on the
    624                // programmer if possible.  Programmers can decide on their
    625                // own if they want to wrap the SocketOutputStream we return
    626                // for file types other than ASCII.
    627                output = new BufferedOutputStream(output,
    628                        getBufferSize());
    629                output = new ToNetASCIIOutputStream(output);
    630
    631            }
    632            return new org.apache.commons.net.io.SocketOutputStream(socket, output);
    633        }
    634
    635
    636        /**
    637         * Establishes a data connection with the FTP server, returning
    638         * a Socket for the connection if successful.  If a restart
    639         * offset has been set with {@link #setRestartOffset(long)},
    640         * a REST command is issued to the server with the offset as
    641         * an argument before establishing the data connection.  Active
    642         * mode connections also cause a local PORT command to be issued.
    643         * <p>
    644         * @param command  The int representation of the FTP command to send.
    645         * @param arg The arguments to the FTP command.  If this parameter is
    646         *             set to null, then the command is sent with no argument.
    647         * @return A Socket corresponding to the established data connection.
    648         *         Null is returned if an FTP protocol error is reported at
    649         *         any point during the establishment and initialization of
    650         *         the connection.
    651         * @exception IOException  If an I/O error occurs while either sending a
    652         *      command to the server or receiving a reply from the server.
    653         */
    654        protected Socket _openDataConnection_(int command, String arg)
    655        throws IOException
    656        {
    657            return _openDataConnection_(FTPCommand.getCommand(command), arg);
    658        }
    659
    660        /**
    661         * Establishes a data connection with the FTP server, returning
    662         * a Socket for the connection if successful.  If a restart
    663         * offset has been set with {@link #setRestartOffset(long)},
    664         * a REST command is issued to the server with the offset as
    665         * an argument before establishing the data connection.  Active
    666         * mode connections also cause a local PORT command to be issued.
    667         * <p>
    668         * @param command  The text representation of the FTP command to send.
    669         * @param arg The arguments to the FTP command.  If this parameter is
    670         *             set to null, then the command is sent with no argument.
    671         * @return A Socket corresponding to the established data connection.
    672         *         Null is returned if an FTP protocol error is reported at
    673         *         any point during the establishment and initialization of
    674         *         the connection.
    675         * @exception IOException  If an I/O error occurs while either sending a
    676         *      command to the server or receiving a reply from the server.
    677         */
    678        protected Socket _openDataConnection_(String command, String arg)
    679        throws IOException
    680        {
    681            if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
    682                    __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE) {
    683                return null;
    684            }
    685
    686            final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
    687
    688            Socket socket;
    689
    690            if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
    691            {
    692                // if no activePortRange was set (correctly) -> getActivePort() = 0
    693                // -> new ServerSocket(0) -> bind to any free local port
    694                ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress());
    695
    696                try {
    697                    // Try EPRT only if remote server is over IPv6, if not use PORT,
    698                    // because EPRT has no advantage over PORT on IPv4.
    699                    // It could even have the disadvantage,
    700                    // that EPRT will make the data connection fail, because
    701                    // today's intelligent NAT Firewalls are able to
    702                    // substitute IP addresses in the PORT command,
    703                    // but might not be able to recognize the EPRT command.
    704                    if (isInet6Address) {
    705                        if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) {
    706                            return null;
    707                        }
    708                    } else {
    709                        if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) {
    710                            return null;
    711                        }
    712                    }
    713
    714                    if ((__restartOffset > 0) && !restart(__restartOffset)) {
    715                        return null;
    716                    }
    717
    718                    if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) {
    719                        return null;
    720                    }
    721
    722                    // For now, let's just use the data timeout value for waiting for
    723                    // the data connection.  It may be desirable to let this be a
    724                    // separately configurable value.  In any case, we really want
    725                    // to allow preventing the accept from blocking indefinitely.
    726                    if (__dataTimeout >= 0) {
    727                        server.setSoTimeout(__dataTimeout);
    728                    }
    729                    socket = server.accept();
    730                } finally {
    731                    server.close();
    732                }
    733            }
    734            else
    735            { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
    736
    737                // Try EPSV command first on IPv6 - and IPv4 if enabled.
    738                // When using IPv4 with NAT it has the advantage
    739                // to work with more rare configurations.
    740                // E.g. if FTP server has a static PASV address (external network)
    741                // and the client is coming from another internal network.
    742                // In that case the data connection after PASV command would fail,
    743                // while EPSV would make the client succeed by taking just the port.
    744                boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
    745                if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE)
    746                {
    747                    _parseExtendedPassiveModeReply(_replyLines.get(0));
    748                }
    749                else
    750                {
    751                    if (isInet6Address) {
    752                        return null; // Must use EPSV for IPV6
    753                    }
    754                    // If EPSV failed on IPV4, revert to PASV
    755                    if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
    756                        return null;
    757                    }
    758                    _parsePassiveModeReply(_replyLines.get(0));
    759                }
    760
    761                socket = _socketFactory_.createSocket();
    762                socket.connect(new InetSocketAddress(__passiveHost, __passivePort), connectTimeout);
    763                if ((__restartOffset > 0) && !restart(__restartOffset))
    764                {
    765                    socket.close();
    766                    return null;
    767                }
    768
    769                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
    770                {
    771                    socket.close();
    772                    return null;
    773                }
    774            }
    775
    776            if (__remoteVerificationEnabled && !verifyRemote(socket))
    777            {
    778                socket.close();
    779
    780                throw new IOException(
    781                        "Host attempting data connection " + socket.getInetAddress().getHostAddress() +
    782                        " is not same as server " + getRemoteAddress().getHostAddress());
    783            }
    784
    785            if (__dataTimeout >= 0) {
    786                socket.setSoTimeout(__dataTimeout);
    787            }
    788
    789            return socket;
    790        }
    791
    792
    793        @Override
    794        protected void _connectAction_() throws IOException
    795        {
    796            super._connectAction_(); // sets up _input_ and _output_
    797            __initDefaults();
    798            // must be after super._connectAction_(), because otherwise we get an
    799            // Exception claiming we're not connected
    800            if ( __autodetectEncoding )
    801            {
    802                ArrayList<String> oldReplyLines = new ArrayList<String> (_replyLines);
    803                int oldReplyCode = _replyCode;
    804                if ( hasFeature("UTF8") || hasFeature("UTF-8")) // UTF8 appears to be the default
    805                {
    806                     setControlEncoding("UTF-8");
    807                     _controlInput_ =
    808                         new CRLFLineReader(new InputStreamReader(_input_, getControlEncoding()));
    809                     _controlOutput_ =
    810                        new BufferedWriter(new OutputStreamWriter(_output_, getControlEncoding()));
    811                }
    812                // restore the original reply (server greeting)
    813                _replyLines.clear();
    814                _replyLines.addAll(oldReplyLines);
    815                _replyCode = oldReplyCode;
    816            }
    817        }
    818
    819
    820        /***
    821         * Sets the timeout in milliseconds to use when reading from the
    822         * data connection.  This timeout will be set immediately after
    823         * opening the data connection.
    824         * <p>
    825         * @param  timeout The default timeout in milliseconds that is used when
    826         *        opening a data connection socket.
    827         ***/
    828        public void setDataTimeout(int timeout)
    829        {
    830            __dataTimeout = timeout;
    831        }
    832
    833        /**
    834         * set the factory used for parser creation to the supplied factory object.
    835         *
    836         * @param parserFactory
    837         *               factory object used to create FTPFileEntryParsers
    838         *
    839         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    840         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    841         */
    842        public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
    843            __parserFactory = parserFactory;
    844        }
    845
    846
    847        /***
    848         * Closes the connection to the FTP server and restores
    849         * connection parameters to the default values.
    850         * <p>
    851         * @exception IOException If an error occurs while disconnecting.
    852         ***/
    853        @Override
    854        public void disconnect() throws IOException
    855        {
    856            super.disconnect();
    857            __initDefaults();
    858        }
    859
    860
    861        /***
    862         * Enable or disable verification that the remote host taking part
    863         * of a data connection is the same as the host to which the control
    864         * connection is attached.  The default is for verification to be
    865         * enabled.  You may set this value at any time, whether the
    866         * FTPClient is currently connected or not.
    867         * <p>
    868         * @param enable True to enable verification, false to disable verification.
    869         ***/
    870        public void setRemoteVerificationEnabled(boolean enable)
    871        {
    872            __remoteVerificationEnabled = enable;
    873        }
    874
    875        /***
    876         * Return whether or not verification of the remote host participating
    877         * in data connections is enabled.  The default behavior is for
    878         * verification to be enabled.
    879         * <p>
    880         * @return True if verification is enabled, false if not.
    881         ***/
    882        public boolean isRemoteVerificationEnabled()
    883        {
    884            return __remoteVerificationEnabled;
    885        }
    886
    887        /***
    888         * Login to the FTP server using the provided username and password.
    889         * <p>
    890         * @param username The username to login under.
    891         * @param password The password to use.
    892         * @return True if successfully completed, false if not.
    893         * @exception FTPConnectionClosedException
    894         *      If the FTP server prematurely closes the connection as a result
    895         *      of the client being idle or some other reason causing the server
    896         *      to send FTP reply code 421.  This exception may be caught either
    897         *      as an IOException or independently as itself.
    898         * @exception IOException  If an I/O error occurs while either sending a
    899         *      command to the server or receiving a reply from the server.
    900         ***/
    901        public boolean login(String username, String password) throws IOException
    902        {
    903
    904            user(username);
    905
    906            if (FTPReply.isPositiveCompletion(_replyCode)) {
    907                return true;
    908            }
    909
    910            // If we get here, we either have an error code, or an intermmediate
    911            // reply requesting password.
    912            if (!FTPReply.isPositiveIntermediate(_replyCode)) {
    913                return false;
    914            }
    915
    916            return FTPReply.isPositiveCompletion(pass(password));
    917        }
    918
    919
    920        /***
    921         * Login to the FTP server using the provided username, password,
    922         * and account.  If no account is required by the server, only
    923         * the username and password, the account information is not used.
    924         * <p>
    925         * @param username The username to login under.
    926         * @param password The password to use.
    927         * @param account  The account to use.
    928         * @return True if successfully completed, false if not.
    929         * @exception FTPConnectionClosedException
    930         *      If the FTP server prematurely closes the connection as a result
    931         *      of the client being idle or some other reason causing the server
    932         *      to send FTP reply code 421.  This exception may be caught either
    933         *      as an IOException or independently as itself.
    934         * @exception IOException  If an I/O error occurs while either sending a
    935         *      command to the server or receiving a reply from the server.
    936         ***/
    937        public boolean login(String username, String password, String account)
    938        throws IOException
    939        {
    940            user(username);
    941
    942            if (FTPReply.isPositiveCompletion(_replyCode)) {
    943                return true;
    944            }
    945
    946            // If we get here, we either have an error code, or an intermmediate
    947            // reply requesting password.
    948            if (!FTPReply.isPositiveIntermediate(_replyCode)) {
    949                return false;
    950            }
    951
    952            pass(password);
    953
    954            if (FTPReply.isPositiveCompletion(_replyCode)) {
    955                return true;
    956            }
    957
    958            if (!FTPReply.isPositiveIntermediate(_replyCode)) {
    959                return false;
    960            }
    961
    962            return FTPReply.isPositiveCompletion(acct(account));
    963        }
    964
    965        /***
    966         * Logout of the FTP server by sending the QUIT command.
    967         * <p>
    968         * @return True if successfully completed, false if not.
    969         * @exception FTPConnectionClosedException
    970         *      If the FTP server prematurely closes the connection as a result
    971         *      of the client being idle or some other reason causing the server
    972         *      to send FTP reply code 421.  This exception may be caught either
    973         *      as an IOException or independently as itself.
    974         * @exception IOException  If an I/O error occurs while either sending a
    975         *      command to the server or receiving a reply from the server.
    976         ***/
    977        public boolean logout() throws IOException
    978        {
    979            return FTPReply.isPositiveCompletion(quit());
    980        }
    981
    982
    983        /***
    984         * Change the current working directory of the FTP session.
    985         * <p>
    986         * @param pathname  The new current working directory.
    987         * @return True if successfully completed, false if not.
    988         * @exception FTPConnectionClosedException
    989         *      If the FTP server prematurely closes the connection as a result
    990         *      of the client being idle or some other reason causing the server
    991         *      to send FTP reply code 421.  This exception may be caught either
    992         *      as an IOException or independently as itself.
    993         * @exception IOException  If an I/O error occurs while either sending a
    994         *      command to the server or receiving a reply from the server.
    995         ***/
    996        public boolean changeWorkingDirectory(String pathname) throws IOException
    997        {
    998            return FTPReply.isPositiveCompletion(cwd(pathname));
    999        }
    1000
    1001
    1002        /***
    1003         * Change to the parent directory of the current working directory.
    1004         * <p>
    1005         * @return True if successfully completed, false if not.
    1006         * @exception FTPConnectionClosedException
    1007         *      If the FTP server prematurely closes the connection as a result
    1008         *      of the client being idle or some other reason causing the server
    1009         *      to send FTP reply code 421.  This exception may be caught either
    1010         *      as an IOException or independently as itself.
    1011         * @exception IOException  If an I/O error occurs while either sending a
    1012         *      command to the server or receiving a reply from the server.
    1013         ***/
    1014        public boolean changeToParentDirectory() throws IOException
    1015        {
    1016            return FTPReply.isPositiveCompletion(cdup());
    1017        }
    1018
    1019
    1020        /***
    1021         * Issue the FTP SMNT command.
    1022         * <p>
    1023         * @param pathname The pathname to mount.
    1024         * @return True if successfully completed, false if not.
    1025         * @exception FTPConnectionClosedException
    1026         *      If the FTP server prematurely closes the connection as a result
    1027         *      of the client being idle or some other reason causing the server
    1028         *      to send FTP reply code 421.  This exception may be caught either
    1029         *      as an IOException or independently as itself.
    1030         * @exception IOException  If an I/O error occurs while either sending a
    1031         *      command to the server or receiving a reply from the server.
    1032         ***/
    1033        public boolean structureMount(String pathname) throws IOException
    1034        {
    1035            return FTPReply.isPositiveCompletion(smnt(pathname));
    1036        }
    1037
    1038        /***
    1039         * Reinitialize the FTP session.  Not all FTP servers support this
    1040         * command, which issues the FTP REIN command.
    1041         * <p>
    1042         * @return True if successfully completed, false if not.
    1043         * @exception FTPConnectionClosedException
    1044         *      If the FTP server prematurely closes the connection as a result
    1045         *      of the client being idle or some other reason causing the server
    1046         *      to send FTP reply code 421.  This exception may be caught either
    1047         *      as an IOException or independently as itself.
    1048         * @exception IOException  If an I/O error occurs while either sending a
    1049         *      command to the server or receiving a reply from the server.
    1050         ***/
    1051        boolean reinitialize() throws IOException
    1052        {
    1053            rein();
    1054
    1055            if (FTPReply.isPositiveCompletion(_replyCode) ||
    1056                    (FTPReply.isPositivePreliminary(_replyCode) &&
    1057                            FTPReply.isPositiveCompletion(getReply())))
    1058            {
    1059
    1060                __initDefaults();
    1061
    1062                return true;
    1063            }
    1064
    1065            return false;
    1066        }
    1067
    1068
    1069        /***
    1070         * Set the current data connection mode to
    1071         * <code>ACTIVE_LOCAL_DATA_CONNECTION_MODE</code>.  No communication
    1072         * with the FTP server is conducted, but this causes all future data
    1073         * transfers to require the FTP server to connect to the client's
    1074         * data port.  Additionally, to accommodate differences between socket
    1075         * implementations on different platforms, this method causes the
    1076         * client to issue a PORT command before every data transfer.
    1077         ***/
    1078        public void enterLocalActiveMode()
    1079        {
    1080            __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
    1081            __passiveHost = null;
    1082            __passivePort = -1;
    1083        }
    1084
    1085
    1086        /***
    1087         * Set the current data connection mode to
    1088         * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code>.  Use this
    1089         * method only for data transfers between the client and server.
    1090         * This method causes a PASV (or EPSV) command to be issued to the server
    1091         * before the opening of every data connection, telling the server to
    1092         * open a data port to which the client will connect to conduct
    1093         * data transfers.  The FTPClient will stay in
    1094         * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code> until the
    1095         * mode is changed by calling some other method such as
    1096         * {@link #enterLocalActiveMode  enterLocalActiveMode() }
    1097         * <p>
    1098         * <b>N.B.</b> currently calling any connect method will reset the mode to
    1099         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    1100         ***/
    1101        public void enterLocalPassiveMode()
    1102        {
    1103            __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
    1104            // These will be set when just before a data connection is opened
    1105            // in _openDataConnection_()
    1106            __passiveHost = null;
    1107            __passivePort = -1;
    1108        }
    1109
    1110
    1111        /***
    1112         * Set the current data connection mode to
    1113         * <code> ACTIVE_REMOTE_DATA_CONNECTION </code>.  Use this method only
    1114         * for server to server data transfers.  This method issues a PORT
    1115         * command to the server, indicating the other server and port to which
    1116         * it should connect for data transfers.  You must call this method
    1117         * before EVERY server to server transfer attempt.  The FTPClient will
    1118         * NOT automatically continue to issue PORT commands.  You also
    1119         * must remember to call
    1120         * {@link #enterLocalActiveMode  enterLocalActiveMode() } if you
    1121         * wish to return to the normal data connection mode.
    1122         * <p>
    1123         * @param host The passive mode server accepting connections for data
    1124         *             transfers.
    1125         * @param port The passive mode server's data port.
    1126         * @return True if successfully completed, false if not.
    1127         * @exception FTPConnectionClosedException
    1128         *      If the FTP server prematurely closes the connection as a result
    1129         *      of the client being idle or some other reason causing the server
    1130         *      to send FTP reply code 421.  This exception may be caught either
    1131         *      as an IOException or independently as itself.
    1132         * @exception IOException  If an I/O error occurs while either sending a
    1133         *      command to the server or receiving a reply from the server.
    1134         ***/
    1135        public boolean enterRemoteActiveMode(InetAddress host, int port)
    1136        throws IOException
    1137        {
    1138            if (FTPReply.isPositiveCompletion(port(host, port)))
    1139            {
    1140                __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
    1141                __passiveHost = null;
    1142                __passivePort = -1;
    1143                return true;
    1144            }
    1145            return false;
    1146        }
    1147
    1148        /***
    1149         * Set the current data connection mode to
    1150         * <code> PASSIVE_REMOTE_DATA_CONNECTION_MODE </code>.  Use this
    1151         * method only for server to server data transfers.
    1152         * This method issues a PASV command to the server, telling it to
    1153         * open a data port to which the active server will connect to conduct
    1154         * data transfers.  You must call this method
    1155         * before EVERY server to server transfer attempt.  The FTPClient will
    1156         * NOT automatically continue to issue PASV commands.  You also
    1157         * must remember to call
    1158         * {@link #enterLocalActiveMode  enterLocalActiveMode() } if you
    1159         * wish to return to the normal data connection mode.
    1160         * <p>
    1161         * @return True if successfully completed, false if not.
    1162         * @exception FTPConnectionClosedException
    1163         *      If the FTP server prematurely closes the connection as a result
    1164         *      of the client being idle or some other reason causing the server
    1165         *      to send FTP reply code 421.  This exception may be caught either
    1166         *      as an IOException or independently as itself.
    1167         * @exception IOException  If an I/O error occurs while either sending a
    1168         *      command to the server or receiving a reply from the server.
    1169         ***/
    1170        public boolean enterRemotePassiveMode() throws IOException
    1171        {
    1172            if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
    1173                return false;
    1174            }
    1175
    1176            __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
    1177            _parsePassiveModeReply(_replyLines.get(0));
    1178
    1179            return true;
    1180        }
    1181
    1182        /***
    1183         * Returns the hostname or IP address (in the form of a string) returned
    1184         * by the server when entering passive mode.  If not in passive mode,
    1185         * returns null.  This method only returns a valid value AFTER a
    1186         * data connection has been opened after a call to
    1187         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1188         * This is because FTPClient sends a PASV command to the server only
    1189         * just before opening a data connection, and not when you call
    1190         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1191         * <p>
    1192         * @return The passive host name if in passive mode, otherwise null.
    1193         ***/
    1194        public String getPassiveHost()
    1195        {
    1196            return __passiveHost;
    1197        }
    1198
    1199        /***
    1200         * If in passive mode, returns the data port of the passive host.
    1201         * This method only returns a valid value AFTER a
    1202         * data connection has been opened after a call to
    1203         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1204         * This is because FTPClient sends a PASV command to the server only
    1205         * just before opening a data connection, and not when you call
    1206         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1207         * <p>
    1208         * @return The data port of the passive server.  If not in passive
    1209         *         mode, undefined.
    1210         ***/
    1211        public int getPassivePort()
    1212        {
    1213            return __passivePort;
    1214        }
    1215
    1216
    1217        /***
    1218         * Returns the current data connection mode (one of the
    1219         * <code> _DATA_CONNECTION_MODE </code> constants.
    1220         * <p>
    1221         * @return The current data connection mode (one of the
    1222         * <code> _DATA_CONNECTION_MODE </code> constants.
    1223         ***/
    1224        public int getDataConnectionMode()
    1225        {
    1226            return __dataConnectionMode;
    1227        }
    1228
    1229        /**
    1230         * Get the client port for active mode.
    1231         * <p>
    1232         * @return The client port for active mode.
    1233         */
    1234        private int getActivePort()
    1235        {
    1236            if (__activeMinPort > 0 && __activeMaxPort >= __activeMinPort)
    1237            {
    1238                if (__activeMaxPort == __activeMinPort) {
    1239                    return __activeMaxPort;
    1240                }
    1241                // Get a random port between the min and max port range
    1242                return __random.nextInt(__activeMaxPort - __activeMinPort + 1) + __activeMinPort;
    1243            }
    1244            else
    1245            {
    1246                // default port
    1247                return 0;
    1248            }
    1249        }
    1250
    1251        /**
    1252         * Get the host address for active mode; allows the local address to be overridden.
    1253         * <p>
    1254         * @return __activeExternalHost if non-null, else getLocalAddress()
    1255         * @see #setActiveExternalIPAddress(String)
    1256         */
    1257        private InetAddress getHostAddress()
    1258        {
    1259            if (__activeExternalHost != null)
    1260            {
    1261                return __activeExternalHost;
    1262            }
    1263            else
    1264            {
    1265                // default local address
    1266                return getLocalAddress();
    1267            }
    1268        }
    1269
    1270        /**
    1271         * Get the reported host address for active mode EPRT/PORT commands;
    1272         * allows override of {@link #getHostAddress()}.
    1273         *
    1274         * Useful for FTP Client behind Firewall NAT.
    1275         * <p>
    1276         * @return __reportActiveExternalHost if non-null, else getHostAddress();
    1277         */
    1278        private InetAddress getReportHostAddress() {
    1279            if (__reportActiveExternalHost != null) {
    1280                return __reportActiveExternalHost ;
    1281            } else {
    1282                return getHostAddress();
    1283            }
    1284        }
    1285
    1286        /***
    1287         * Set the client side port range in active mode.
    1288         * <p>
    1289         * @param minPort The lowest available port (inclusive).
    1290         * @param maxPort The highest available port (inclusive).
    1291         * @since 2.2
    1292         ***/
    1293        public void setActivePortRange(int minPort, int maxPort)
    1294        {
    1295            this.__activeMinPort = minPort;
    1296            this.__activeMaxPort = maxPort;
    1297        }
    1298
    1299        /***
    1300         * Set the external IP address in active mode.
    1301         * Useful when there are multiple network cards.
    1302         * <p>
    1303         * @param ipAddress The external IP address of this machine.
    1304         * @throws UnknownHostException if the ipAddress cannot be resolved
    1305         * @since 2.2
    1306         ***/
    1307        public void setActiveExternalIPAddress(String ipAddress) throws UnknownHostException
    1308        {
    1309            this.__activeExternalHost = InetAddress.getByName(ipAddress);
    1310        }
    1311
    1312        /**
    1313         * Set the external IP address to report in EPRT/PORT commands in active mode.
    1314         * Useful when there are multiple network cards.
    1315         * <p>
    1316         * @param ipAddress The external IP address of this machine.
    1317         * @throws UnknownHostException if the ipAddress cannot be resolved
    1318         * @since 3.1
    1319         * @see #getReportHostAddress()
    1320         */
    1321        public void setReportActiveExternalIPAddress(String ipAddress) throws UnknownHostException
    1322        {
    1323            this.__reportActiveExternalHost = InetAddress.getByName(ipAddress);
    1324        }
    1325
    1326
    1327        /***
    1328         * Sets the file type to be transferred.  This should be one of
    1329         * <code> FTP.ASCII_FILE_TYPE </code>, <code> FTP.BINARY_FILE_TYPE</code>,
    1330         * etc.  The file type only needs to be set when you want to change the
    1331         * type.  After changing it, the new type stays in effect until you change
    1332         * it again.  The default file type is <code> FTP.ASCII_FILE_TYPE </code>
    1333         * if this method is never called.
    1334         * <p>
    1335         * <b>N.B.</b> currently calling any connect method will reset the mode to
    1336         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    1337         * @param fileType The <code> _FILE_TYPE </code> constant indcating the
    1338         *                 type of file.
    1339         * @return True if successfully completed, false if not.
    1340         * @exception FTPConnectionClosedException
    1341         *      If the FTP server prematurely closes the connection as a result
    1342         *      of the client being idle or some other reason causing the server
    1343         *      to send FTP reply code 421.  This exception may be caught either
    1344         *      as an IOException or independently as itself.
    1345         * @exception IOException  If an I/O error occurs while either sending a
    1346         *      command to the server or receiving a reply from the server.
    1347         ***/
    1348        public boolean setFileType(int fileType) throws IOException
    1349        {
    1350            if (FTPReply.isPositiveCompletion(type(fileType)))
    1351            {
    1352                __fileType = fileType;
    1353                __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
    1354                return true;
    1355            }
    1356            return false;
    1357        }
    1358
    1359
    1360        /***
    1361         * Sets the file type to be transferred and the format.  The type should be
    1362         * one of  <code> FTP.ASCII_FILE_TYPE </code>,
    1363         * <code> FTP.BINARY_FILE_TYPE </code>, etc.  The file type only needs to
    1364         * be set when you want to change the type.  After changing it, the new
    1365         * type stays in effect until you change it again.  The default file type
    1366         * is <code> FTP.ASCII_FILE_TYPE </code> if this method is never called.
    1367         * The format should be one of the FTP class <code> TEXT_FORMAT </code>
    1368         * constants, or if the type is <code> FTP.LOCAL_FILE_TYPE </code>, the
    1369         * format should be the byte size for that type.  The default format
    1370         * is <code> FTP.NON_PRINT_TEXT_FORMAT </code> if this method is never
    1371         * called.
    1372         * <p>
    1373         * <b>N.B.</b> currently calling any connect method will reset the mode to
    1374         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    1375         * <p>
    1376         * @param fileType The <code> _FILE_TYPE </code> constant indcating the
    1377         *                 type of file.
    1378         * @param formatOrByteSize  The format of the file (one of the
    1379         *              <code>_FORMAT</code> constants.  In the case of
    1380         *              <code>LOCAL_FILE_TYPE</code>, the byte size.
    1381         * <p>
    1382         * @return True if successfully completed, false if not.
    1383         * @exception FTPConnectionClosedException
    1384         *      If the FTP server prematurely closes the connection as a result
    1385         *      of the client being idle or some other reason causing the server
    1386         *      to send FTP reply code 421.  This exception may be caught either
    1387         *      as an IOException or independently as itself.
    1388         * @exception IOException  If an I/O error occurs while either sending a
    1389         *      command to the server or receiving a reply from the server.
    1390         ***/
    1391        public boolean setFileType(int fileType, int formatOrByteSize)
    1392        throws IOException
    1393        {
    1394            if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize)))
    1395            {
    1396                __fileType = fileType;
    1397                __fileFormat = formatOrByteSize;
    1398                return true;
    1399            }
    1400            return false;
    1401        }
    1402
    1403
    1404        /***
    1405         * Sets the file structure.  The default structure is
    1406         * <code> FTP.FILE_STRUCTURE </code> if this method is never called.
    1407         * <p>
    1408         * @param structure  The structure of the file (one of the FTP class
    1409         *         <code>_STRUCTURE</code> constants).
    1410         * @return True if successfully completed, false if not.
    1411         * @exception FTPConnectionClosedException
    1412         *      If the FTP server prematurely closes the connection as a result
    1413         *      of the client being idle or some other reason causing the server
    1414         *      to send FTP reply code 421.  This exception may be caught either
    1415         *      as an IOException or independently as itself.
    1416         * @exception IOException  If an I/O error occurs while either sending a
    1417         *      command to the server or receiving a reply from the server.
    1418         ***/
    1419        public boolean setFileStructure(int structure) throws IOException
    1420        {
    1421            if (FTPReply.isPositiveCompletion(stru(structure)))
    1422            {
    1423                __fileStructure = structure;
    1424                return true;
    1425            }
    1426            return false;
    1427        }
    1428
    1429
    1430        /***
    1431         * Sets the transfer mode.  The default transfer mode
    1432         * <code> FTP.STREAM_TRANSFER_MODE </code> if this method is never called.
    1433         * <p>
    1434         * @param mode  The new transfer mode to use (one of the FTP class
    1435         *         <code>_TRANSFER_MODE</code> constants).
    1436         * @return True if successfully completed, false if not.
    1437         * @exception FTPConnectionClosedException
    1438         *      If the FTP server prematurely closes the connection as a result
    1439         *      of the client being idle or some other reason causing the server
    1440         *      to send FTP reply code 421.  This exception may be caught either
    1441         *      as an IOException or independently as itself.
    1442         * @exception IOException  If an I/O error occurs while either sending a
    1443         *      command to the server or receiving a reply from the server.
    1444         ***/
    1445        public boolean setFileTransferMode(int mode) throws IOException
    1446        {
    1447            if (FTPReply.isPositiveCompletion(mode(mode)))
    1448            {
    1449                __fileTransferMode = mode;
    1450                return true;
    1451            }
    1452            return false;
    1453        }
    1454
    1455
    1456        /***
    1457         * Initiate a server to server file transfer.  This method tells the
    1458         * server to which the client is connected to retrieve a given file from
    1459         * the other server.
    1460         * <p>
    1461         * @param filename  The name of the file to retrieve.
    1462         * @return True if successfully completed, false if not.
    1463         * @exception FTPConnectionClosedException
    1464         *      If the FTP server prematurely closes the connection as a result
    1465         *      of the client being idle or some other reason causing the server
    1466         *      to send FTP reply code 421.  This exception may be caught either
    1467         *      as an IOException or independently as itself.
    1468         * @exception IOException  If an I/O error occurs while either sending a
    1469         *      command to the server or receiving a reply from the server.
    1470         ***/
    1471        public boolean remoteRetrieve(String filename) throws IOException
    1472        {
    1473            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1474                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) {
    1475                return FTPReply.isPositivePreliminary(retr(filename));
    1476            }
    1477            return false;
    1478        }
    1479
    1480
    1481        /***
    1482         * Initiate a server to server file transfer.  This method tells the
    1483         * server to which the client is connected to store a file on
    1484         * the other server using the given filename.  The other server must
    1485         * have had a <code> remoteRetrieve </code> issued to it by another
    1486         * FTPClient.
    1487         * <p>
    1488         * @param filename  The name to call the file that is to be stored.
    1489         * @return True if successfully completed, false if not.
    1490         * @exception FTPConnectionClosedException
    1491         *      If the FTP server prematurely closes the connection as a result
    1492         *      of the client being idle or some other reason causing the server
    1493         *      to send FTP reply code 421.  This exception may be caught either
    1494         *      as an IOException or independently as itself.
    1495         * @exception IOException  If an I/O error occurs while either sending a
    1496         *      command to the server or receiving a reply from the server.
    1497         ***/
    1498        public boolean remoteStore(String filename) throws IOException
    1499        {
    1500            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1501                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) {
    1502                return FTPReply.isPositivePreliminary(stor(filename));
    1503            }
    1504            return false;
    1505        }
    1506
    1507
    1508        /***
    1509         * Initiate a server to server file transfer.  This method tells the
    1510         * server to which the client is connected to store a file on
    1511         * the other server using a unique filename based on the given filename.
    1512         * The other server must have had a <code> remoteRetrieve </code> issued
    1513         * to it by another FTPClient.
    1514         * <p>
    1515         * @param filename  The name on which to base the filename of the file
    1516         *                  that is to be stored.
    1517         * @return True if successfully completed, false if not.
    1518         * @exception FTPConnectionClosedException
    1519         *      If the FTP server prematurely closes the connection as a result
    1520         *      of the client being idle or some other reason causing the server
    1521         *      to send FTP reply code 421.  This exception may be caught either
    1522         *      as an IOException or independently as itself.
    1523         * @exception IOException  If an I/O error occurs while either sending a
    1524         *      command to the server or receiving a reply from the server.
    1525         ***/
    1526        public boolean remoteStoreUnique(String filename) throws IOException
    1527        {
    1528            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1529                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) {
    1530                return FTPReply.isPositivePreliminary(stou(filename));
    1531            }
    1532            return false;
    1533        }
    1534
    1535
    1536        /***
    1537         * Initiate a server to server file transfer.  This method tells the
    1538         * server to which the client is connected to store a file on
    1539         * the other server using a unique filename.
    1540         * The other server must have had a <code> remoteRetrieve </code> issued
    1541         * to it by another FTPClient.  Many FTP servers require that a base
    1542         * filename be given from which the unique filename can be derived.  For
    1543         * those servers use the other version of <code> remoteStoreUnique</code>
    1544         * <p>
    1545         * @return True if successfully completed, false if not.
    1546         * @exception FTPConnectionClosedException
    1547         *      If the FTP server prematurely closes the connection as a result
    1548         *      of the client being idle or some other reason causing the server
    1549         *      to send FTP reply code 421.  This exception may be caught either
    1550         *      as an IOException or independently as itself.
    1551         * @exception IOException  If an I/O error occurs while either sending a
    1552         *      command to the server or receiving a reply from the server.
    1553         ***/
    1554        public boolean remoteStoreUnique() throws IOException
    1555        {
    1556            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1557                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) {
    1558                return FTPReply.isPositivePreliminary(stou());
    1559            }
    1560            return false;
    1561        }
    1562
    1563        // For server to server transfers
    1564        /***
    1565         * Initiate a server to server file transfer.  This method tells the
    1566         * server to which the client is connected to append to a given file on
    1567         * the other server.  The other server must have had a
    1568         * <code> remoteRetrieve </code> issued to it by another FTPClient.
    1569         * <p>
    1570         * @param filename  The name of the file to be appended to, or if the
    1571         *        file does not exist, the name to call the file being stored.
    1572         * <p>
    1573         * @return True if successfully completed, false if not.
    1574         * @exception FTPConnectionClosedException
    1575         *      If the FTP server prematurely closes the connection as a result
    1576         *      of the client being idle or some other reason causing the server
    1577         *      to send FTP reply code 421.  This exception may be caught either
    1578         *      as an IOException or independently as itself.
    1579         * @exception IOException  If an I/O error occurs while either sending a
    1580         *      command to the server or receiving a reply from the server.
    1581         ***/
    1582        public boolean remoteAppend(String filename) throws IOException
    1583        {
    1584            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1585                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) {
    1586                return FTPReply.isPositivePreliminary(appe(filename));
    1587            }
    1588            return false;
    1589        }
    1590
    1591        /***
    1592         * There are a few FTPClient methods that do not complete the
    1593         * entire sequence of FTP commands to complete a transaction.  These
    1594         * commands require some action by the programmer after the reception
    1595         * of a positive intermediate command.  After the programmer's code
    1596         * completes its actions, it must call this method to receive
    1597         * the completion reply from the server and verify the success of the
    1598         * entire transaction.
    1599         * <p>
    1600         * For example,
    1601         * <pre>
    1602         * InputStream input;
    1603         * OutputStream output;
    1604         * input  = new FileInputStream("foobaz.txt");
    1605         * output = ftp.storeFileStream("foobar.txt")
    1606         * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
    1607         *     input.close();
    1608         *     output.close();
    1609         *     ftp.logout();
    1610         *     ftp.disconnect();
    1611         *     System.err.println("File transfer failed.");
    1612         *     System.exit(1);
    1613         * }
    1614         * Util.copyStream(input, output);
    1615         * input.close();
    1616         * output.close();
    1617         * // Must call completePendingCommand() to finish command.
    1618         * if(!ftp.completePendingCommand()) {
    1619         *     ftp.logout();
    1620         *     ftp.disconnect();
    1621         *     System.err.println("File transfer failed.");
    1622         *     System.exit(1);
    1623         * }
    1624         * </pre>
    1625         * <p>
    1626         * @return True if successfully completed, false if not.
    1627         * @exception FTPConnectionClosedException
    1628         *      If the FTP server prematurely closes the connection as a result
    1629         *      of the client being idle or some other reason causing the server
    1630         *      to send FTP reply code 421.  This exception may be caught either
    1631         *      as an IOException or independently as itself.
    1632         * @exception IOException  If an I/O error occurs while either sending a
    1633         *      command to the server or receiving a reply from the server.
    1634         ***/
    1635        public boolean completePendingCommand() throws IOException
    1636        {
    1637            return FTPReply.isPositiveCompletion(getReply());
    1638        }
    1639
    1640
    1641        /***
    1642         * Retrieves a named file from the server and writes it to the given
    1643         * OutputStream.  This method does NOT close the given OutputStream.
    1644         * If the current file type is ASCII, line separators in the file are
    1645         * converted to the local representation.
    1646         * <p>
    1647         * Note: if you have used {@link #setRestartOffset(long)},
    1648         * the file data will start from the selected offset.
    1649         * @param remote  The name of the remote file.
    1650         * @param local   The local OutputStream to which to write the file.
    1651         * @return True if successfully completed, false if not.
    1652         * @exception FTPConnectionClosedException
    1653         *      If the FTP server prematurely closes the connection as a result
    1654         *      of the client being idle or some other reason causing the server
    1655         *      to send FTP reply code 421.  This exception may be caught either
    1656         *      as an IOException or independently as itself.
    1657         * @exception org.apache.commons.net.io.CopyStreamException
    1658         *      If an I/O error occurs while actually
    1659         *      transferring the file.  The CopyStreamException allows you to
    1660         *      determine the number of bytes transferred and the IOException
    1661         *      causing the error.  This exception may be caught either
    1662         *      as an IOException or independently as itself.
    1663         * @exception IOException  If an I/O error occurs while either sending a
    1664         *      command to the server or receiving a reply from the server.
    1665         ***/
    1666        public boolean retrieveFile(String remote, OutputStream local)
    1667        throws IOException
    1668        {
    1669            return _retrieveFile(FTPCommand.getCommand(FTPCommand.RETR), remote, local);
    1670        }
    1671
    1672        protected boolean _retrieveFile(String command, String remote, OutputStream local)
    1673        throws IOException
    1674        {
    1675            Socket socket;
    1676
    1677            if ((socket = _openDataConnection_(command, remote)) == null) {
    1678                return false;
    1679            }
    1680
    1681            InputStream input = new BufferedInputStream(socket.getInputStream(),
    1682                    getBufferSize());
    1683            if (__fileType == ASCII_FILE_TYPE) {
    1684                input = new FromNetASCIIInputStream(input);
    1685            }
    1686
    1687            CSL csl = null;
    1688            if (__controlKeepAliveTimeout > 0) {
    1689                csl = new CSL(this, __controlKeepAliveTimeout, __controlKeepAliveReplyTimeout);
    1690            }
    1691
    1692            // Treat everything else as binary for now
    1693            try
    1694            {
    1695                Util.copyStream(input, local, getBufferSize(),
    1696                        CopyStreamEvent.UNKNOWN_STREAM_SIZE, __mergeListeners(csl),
    1697                        false);
    1698            } finally {
    1699                Util.closeQuietly(socket);
    1700            }
    1701
    1702            if (csl != null) {
    1703                csl.cleanUp(); // fetch any outstanding keepalive replies
    1704            }
    1705            // Get the transfer response
    1706            boolean ok = completePendingCommand();
    1707            return ok;
    1708        }
    1709
    1710        /***
    1711         * Returns an InputStream from which a named file from the server
    1712         * can be read.  If the current file type is ASCII, the returned
    1713         * InputStream will convert line separators in the file to
    1714         * the local representation.  You must close the InputStream when you
    1715         * finish reading from it.  The InputStream itself will take care of
    1716         * closing the parent data connection socket upon being closed.  To
    1717         * finalize the file transfer you must call
    1718         * {@link #completePendingCommand  completePendingCommand } and
    1719         * check its return value to verify success.
    1720         * <p>
    1721         * Note: if you have used {@link #setRestartOffset(long)},
    1722         * the file data will start from the selected offset.
    1723         *
    1724         * @param remote  The name of the remote file.
    1725         * @return An InputStream from which the remote file can be read.  If
    1726         *      the data connection cannot be opened (e.g., the file does not
    1727         *      exist), null is returned (in which case you may check the reply
    1728         *      code to determine the exact reason for failure).
    1729         * @exception FTPConnectionClosedException
    1730         *      If the FTP server prematurely closes the connection as a result
    1731         *      of the client being idle or some other reason causing the server
    1732         *      to send FTP reply code 421.  This exception may be caught either
    1733         *      as an IOException or independently as itself.
    1734         * @exception IOException  If an I/O error occurs while either sending a
    1735         *      command to the server or receiving a reply from the server.
    1736         ***/
    1737        public InputStream retrieveFileStream(String remote) throws IOException
    1738        {
    1739            return _retrieveFileStream(FTPCommand.getCommand(FTPCommand.RETR), remote);
    1740        }
    1741
    1742        protected InputStream _retrieveFileStream(String command, String remote)
    1743        throws IOException
    1744        {
    1745            Socket socket;
    1746
    1747            if ((socket = _openDataConnection_(command, remote)) == null) {
    1748                return null;
    1749            }
    1750
    1751            InputStream input = socket.getInputStream();
    1752            if (__fileType == ASCII_FILE_TYPE) {
    1753                // We buffer ascii transfers because the buffering has to
    1754                // be interposed between FromNetASCIIOutputSream and the underlying
    1755                // socket input stream.  We don't buffer binary transfers
    1756                // because we don't want to impose a buffering policy on the
    1757                // programmer if possible.  Programmers can decide on their
    1758                // own if they want to wrap the SocketInputStream we return
    1759                // for file types other than ASCII.
    1760                input = new BufferedInputStream(input,
    1761                        getBufferSize());
    1762                input = new FromNetASCIIInputStream(input);
    1763            }
    1764            return new org.apache.commons.net.io.SocketInputStream(socket, input);
    1765        }
    1766
    1767
    1768        /***
    1769         * Stores a file on the server using the given name and taking input
    1770         * from the given InputStream.  This method does NOT close the given
    1771         * InputStream.  If the current file type is ASCII, line separators in
    1772         * the file are transparently converted to the NETASCII format (i.e.,
    1773         * you should not attempt to create a special InputStream to do this).
    1774         * <p>
    1775         * @param remote  The name to give the remote file.
    1776         * @param local   The local InputStream from which to read the file.
    1777         * @return True if successfully completed, false if not.
    1778         * @exception FTPConnectionClosedException
    1779         *      If the FTP server prematurely closes the connection as a result
    1780         *      of the client being idle or some other reason causing the server
    1781         *      to send FTP reply code 421.  This exception may be caught either
    1782         *      as an IOException or independently as itself.
    1783         * @exception org.apache.commons.net.io.CopyStreamException
    1784         *      If an I/O error occurs while actually
    1785         *      transferring the file.  The CopyStreamException allows you to
    1786         *      determine the number of bytes transferred and the IOException
    1787         *      causing the error.  This exception may be caught either
    1788         *      as an IOException or independently as itself.
    1789         * @exception IOException  If an I/O error occurs while either sending a
    1790         *      command to the server or receiving a reply from the server.
    1791         ***/
    1792        public boolean storeFile(String remote, InputStream local)
    1793        throws IOException
    1794        {
    1795            return __storeFile(FTPCommand.STOR, remote, local);
    1796        }
    1797
    1798
    1799        /***
    1800         * Returns an OutputStream through which data can be written to store
    1801         * a file on the server using the given name.  If the current file type
    1802         * is ASCII, the returned OutputStream will convert line separators in
    1803         * the file to the NETASCII format  (i.e., you should not attempt to
    1804         * create a special OutputStream to do this).  You must close the
    1805         * OutputStream when you finish writing to it.  The OutputStream itself
    1806         * will take care of closing the parent data connection socket upon being
    1807         * closed.  To finalize the file transfer you must call
    1808         * {@link #completePendingCommand  completePendingCommand } and
    1809         * check its return value to verify success.
    1810         * <p>
    1811         * @param remote  The name to give the remote file.
    1812         * @return An OutputStream through which the remote file can be written.  If
    1813         *      the data connection cannot be opened (e.g., the file does not
    1814         *      exist), null is returned (in which case you may check the reply
    1815         *      code to determine the exact reason for failure).
    1816         * @exception FTPConnectionClosedException
    1817         *      If the FTP server prematurely closes the connection as a result
    1818         *      of the client being idle or some other reason causing the server
    1819         *      to send FTP reply code 421.  This exception may be caught either
    1820         *      as an IOException or independently as itself.
    1821         * @exception IOException  If an I/O error occurs while either sending a
    1822         *      command to the server or receiving a reply from the server.
    1823         ***/
    1824        public OutputStream storeFileStream(String remote) throws IOException
    1825        {
    1826            return __storeFileStream(FTPCommand.STOR, remote);
    1827        }
    1828
    1829        /***
    1830         * Appends to a file on the server with the given name, taking input
    1831         * from the given InputStream.  This method does NOT close the given
    1832         * InputStream.  If the current file type is ASCII, line separators in
    1833         * the file are transparently converted to the NETASCII format (i.e.,
    1834         * you should not attempt to create a special InputStream to do this).
    1835         * <p>
    1836         * @param remote  The name of the remote file.
    1837         * @param local   The local InputStream from which to read the data to
    1838         *                be appended to the remote file.
    1839         * @return True if successfully completed, false if not.
    1840         * @exception FTPConnectionClosedException
    1841         *      If the FTP server prematurely closes the connection as a result
    1842         *      of the client being idle or some other reason causing the server
    1843         *      to send FTP reply code 421.  This exception may be caught either
    1844         *      as an IOException or independently as itself.
    1845         * @exception org.apache.commons.net.io.CopyStreamException
    1846         *      If an I/O error occurs while actually
    1847         *      transferring the file.  The CopyStreamException allows you to
    1848         *      determine the number of bytes transferred and the IOException
    1849         *      causing the error.  This exception may be caught either
    1850         *      as an IOException or independently as itself.
    1851         * @exception IOException  If an I/O error occurs while either sending a
    1852         *      command to the server or receiving a reply from the server.
    1853         ***/
    1854        public boolean appendFile(String remote, InputStream local)
    1855        throws IOException
    1856        {
    1857            return __storeFile(FTPCommand.APPE, remote, local);
    1858        }
    1859
    1860        /***
    1861         * Returns an OutputStream through which data can be written to append
    1862         * to a file on the server with the given name.  If the current file type
    1863         * is ASCII, the returned OutputStream will convert line separators in
    1864         * the file to the NETASCII format  (i.e., you should not attempt to
    1865         * create a special OutputStream to do this).  You must close the
    1866         * OutputStream when you finish writing to it.  The OutputStream itself
    1867         * will take care of closing the parent data connection socket upon being
    1868         * closed.  To finalize the file transfer you must call
    1869         * {@link #completePendingCommand  completePendingCommand } and
    1870         * check its return value to verify success.
    1871         * <p>
    1872         * @param remote  The name of the remote file.
    1873         * @return An OutputStream through which the remote file can be appended.
    1874         *      If the data connection cannot be opened (e.g., the file does not
    1875         *      exist), null is returned (in which case you may check the reply
    1876         *      code to determine the exact reason for failure).
    1877         * @exception FTPConnectionClosedException
    1878         *      If the FTP server prematurely closes the connection as a result
    1879         *      of the client being idle or some other reason causing the server
    1880         *      to send FTP reply code 421.  This exception may be caught either
    1881         *      as an IOException or independently as itself.
    1882         * @exception IOException  If an I/O error occurs while either sending a
    1883         *      command to the server or receiving a reply from the server.
    1884         ***/
    1885        public OutputStream appendFileStream(String remote) throws IOException
    1886        {
    1887            return __storeFileStream(FTPCommand.APPE, remote);
    1888        }
    1889
    1890        /***
    1891         * Stores a file on the server using a unique name derived from the
    1892         * given name and taking input
    1893         * from the given InputStream.  This method does NOT close the given
    1894         * InputStream.  If the current file type is ASCII, line separators in
    1895         * the file are transparently converted to the NETASCII format (i.e.,
    1896         * you should not attempt to create a special InputStream to do this).
    1897         * <p>
    1898         * @param remote  The name on which to base the unique name given to
    1899         *                the remote file.
    1900         * @param local   The local InputStream from which to read the file.
    1901         * @return True if successfully completed, false if not.
    1902         * @exception FTPConnectionClosedException
    1903         *      If the FTP server prematurely closes the connection as a result
    1904         *      of the client being idle or some other reason causing the server
    1905         *      to send FTP reply code 421.  This exception may be caught either
    1906         *      as an IOException or independently as itself.
    1907         * @exception org.apache.commons.net.io.CopyStreamException
    1908         *      If an I/O error occurs while actually
    1909         *      transferring the file.  The CopyStreamException allows you to
    1910         *      determine the number of bytes transferred and the IOException
    1911         *      causing the error.  This exception may be caught either
    1912         *      as an IOException or independently as itself.
    1913         * @exception IOException  If an I/O error occurs while either sending a
    1914         *      command to the server or receiving a reply from the server.
    1915         ***/
    1916        public boolean storeUniqueFile(String remote, InputStream local)
    1917        throws IOException
    1918        {
    1919            return __storeFile(FTPCommand.STOU, remote, local);
    1920        }
    1921
    1922
    1923        /***
    1924         * Returns an OutputStream through which data can be written to store
    1925         * a file on the server using a unique name derived from the given name.
    1926         * If the current file type
    1927         * is ASCII, the returned OutputStream will convert line separators in
    1928         * the file to the NETASCII format  (i.e., you should not attempt to
    1929         * create a special OutputStream to do this).  You must close the
    1930         * OutputStream when you finish writing to it.  The OutputStream itself
    1931         * will take care of closing the parent data connection socket upon being
    1932         * closed.  To finalize the file transfer you must call
    1933         * {@link #completePendingCommand  completePendingCommand } and
    1934         * check its return value to verify success.
    1935         * <p>
    1936         * @param remote  The name on which to base the unique name given to
    1937         *                the remote file.
    1938         * @return An OutputStream through which the remote file can be written.  If
    1939         *      the data connection cannot be opened (e.g., the file does not
    1940         *      exist), null is returned (in which case you may check the reply
    1941         *      code to determine the exact reason for failure).
    1942         * @exception FTPConnectionClosedException
    1943         *      If the FTP server prematurely closes the connection as a result
    1944         *      of the client being idle or some other reason causing the server
    1945         *      to send FTP reply code 421.  This exception may be caught either
    1946         *      as an IOException or independently as itself.
    1947         * @exception IOException  If an I/O error occurs while either sending a
    1948         *      command to the server or receiving a reply from the server.
    1949         ***/
    1950        public OutputStream storeUniqueFileStream(String remote) throws IOException
    1951        {
    1952            return __storeFileStream(FTPCommand.STOU, remote);
    1953        }
    1954
    1955        /**
    1956         * Stores a file on the server using a unique name assigned by the
    1957         * server and taking input from the given InputStream.  This method does
    1958         * NOT close the given
    1959         * InputStream.  If the current file type is ASCII, line separators in
    1960         * the file are transparently converted to the NETASCII format (i.e.,
    1961         * you should not attempt to create a special InputStream to do this).
    1962         * <p>
    1963         * @param local   The local InputStream from which to read the file.
    1964         * @return True if successfully completed, false if not.
    1965         * @exception FTPConnectionClosedException
    1966         *      If the FTP server prematurely closes the connection as a result
    1967         *      of the client being idle or some other reason causing the server
    1968         *      to send FTP reply code 421.  This exception may be caught either
    1969         *      as an IOException or independently as itself.
    1970         * @exception org.apache.commons.net.io.CopyStreamException
    1971         *      If an I/O error occurs while actually
    1972         *      transferring the file.  The CopyStreamException allows you to
    1973         *      determine the number of bytes transferred and the IOException
    1974         *      causing the error.  This exception may be caught either
    1975         *      as an IOException or independently as itself.
    1976         * @exception IOException  If an I/O error occurs while either sending a
    1977         *      command to the server or receiving a reply from the server.
    1978         */
    1979        public boolean storeUniqueFile(InputStream local) throws IOException
    1980        {
    1981            return __storeFile(FTPCommand.STOU, null, local);
    1982        }
    1983
    1984        /**
    1985         * Returns an OutputStream through which data can be written to store
    1986         * a file on the server using a unique name assigned by the server.
    1987         * If the current file type
    1988         * is ASCII, the returned OutputStream will convert line separators in
    1989         * the file to the NETASCII format  (i.e., you should not attempt to
    1990         * create a special OutputStream to do this).  You must close the
    1991         * OutputStream when you finish writing to it.  The OutputStream itself
    1992         * will take care of closing the parent data connection socket upon being
    1993         * closed.  To finalize the file transfer you must call
    1994         * {@link #completePendingCommand  completePendingCommand } and
    1995         * check its return value to verify success.
    1996         * <p>
    1997         * @return An OutputStream through which the remote file can be written.  If
    1998         *      the data connection cannot be opened (e.g., the file does not
    1999         *      exist), null is returned (in which case you may check the reply
    2000         *      code to determine the exact reason for failure).
    2001         * @exception FTPConnectionClosedException
    2002         *      If the FTP server prematurely closes the connection as a result
    2003         *      of the client being idle or some other reason causing the server
    2004         *      to send FTP reply code 421.  This exception may be caught either
    2005         *      as an IOException or independently as itself.
    2006         * @exception IOException  If an I/O error occurs while either sending a
    2007         *      command to the server or receiving a reply from the server.
    2008         */
    2009        public OutputStream storeUniqueFileStream() throws IOException
    2010        {
    2011            return __storeFileStream(FTPCommand.STOU, null);
    2012        }
    2013
    2014        /***
    2015         * Reserve a number of bytes on the server for the next file transfer.
    2016         * <p>
    2017         * @param bytes  The number of bytes which the server should allocate.
    2018         * @return True if successfully completed, false if not.
    2019         * @exception FTPConnectionClosedException
    2020         *      If the FTP server prematurely closes the connection as a result
    2021         *      of the client being idle or some other reason causing the server
    2022         *      to send FTP reply code 421.  This exception may be caught either
    2023         *      as an IOException or independently as itself.
    2024         * @exception IOException  If an I/O error occurs while either sending a
    2025         *      command to the server or receiving a reply from the server.
    2026         ***/
    2027        public boolean allocate(int bytes) throws IOException
    2028        {
    2029            return FTPReply.isPositiveCompletion(allo(bytes));
    2030        }
    2031
    2032        /**
    2033         * Query the server for supported features. The server may reply with a list of server-supported exensions.
    2034         * For example, a typical client-server interaction might be (from RFC 2389):
    2035         * <pre>
    2036            C> feat
    2037            S> 211-Extensions supported:
    2038            S>  MLST size*;create;modify*;perm;media-type
    2039            S>  SIZE
    2040            S>  COMPRESSION
    2041            S>  MDTM
    2042            S> 211 END
    2043         * </pre>
    2044         * @see <a href="http://www.faqs.org/rfcs/rfc2389.html">http://www.faqs.org/rfcs/rfc2389.html</a>
    2045         * @return True if successfully completed, false if not.
    2046         * @throws IOException
    2047         * @since 2.2
    2048         */
    2049        public boolean features() throws IOException {
    2050            return FTPReply.isPositiveCompletion(feat());
    2051        }
    2052
    2053        /**
    2054         * Query the server for a supported feature, and returns its values (if any).
    2055         * Caches the parsed response to avoid resending the command repeatedly.
    2056         *
    2057         * @return if the feature is present, returns the feature values (empty array if none)
    2058         * Returns {@code null} if the feature is not found or the command failed.
    2059         * Check {@link #getReplyCode()} or {@link #getReplyString()} if so.
    2060         * @throws IOException
    2061         * @since 3.0
    2062         */
    2063        public String[] featureValues(String feature) throws IOException {
    2064            if (!initFeatureMap()) {
    2065                return null;
    2066            }
    2067            Set<String> entries = __featuresMap.get(feature.toUpperCase(Locale.ENGLISH));
    2068            if (entries != null) {
    2069                return entries.toArray(new String[entries.size()]);
    2070            }
    2071            return null;
    2072        }
    2073
    2074        /**
    2075         * Query the server for a supported feature, and returns the its value (if any).
    2076         * Caches the parsed response to avoid resending the command repeatedly.
    2077         *
    2078         * @return if the feature is present, returns the feature value or the empty string
    2079         * if the feature exists but has no value.
    2080         * Returns {@code null} if the feature is not found or the command failed.
    2081         * Check {@link #getReplyCode()} or {@link #getReplyString()} if so.
    2082         * @throws IOException
    2083         * @since 3.0
    2084         */
    2085        public String featureValue(String feature) throws IOException {
    2086            String [] values = featureValues(feature);
    2087            if (values != null) {
    2088                return values[0];
    2089            }
    2090            return null;
    2091        }
    2092
    2093        /**
    2094         * Query the server for a supported feature.
    2095         * Caches the parsed response to avoid resending the command repeatedly.
    2096         *
    2097         * @param feature the name of the feature; it is converted to upper case.
    2098         * @return {@code true} if the feature is present, {@code false} if the feature is not present
    2099         * or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()}
    2100         * if it is necessary to distinguish these cases.
    2101         *
    2102         * @throws IOException
    2103         * @since 3.0
    2104         */
    2105        public boolean hasFeature(String feature) throws IOException {
    2106            if (!initFeatureMap()) {
    2107                return false;
    2108            }
    2109            return __featuresMap.containsKey(feature.toUpperCase(Locale.ENGLISH));
    2110        }
    2111
    2112        /**
    2113         * Query the server for a supported feature with particular value,
    2114         * for example "AUTH SSL" or "AUTH TLS".
    2115         * Caches the parsed response to avoid resending the command repeatedly.
    2116         *
    2117         * @param feature the name of the feature; it is converted to upper case.
    2118         * @param value the value to find.
    2119         *
    2120         * @return {@code true} if the feature is present, {@code false} if the feature is not present
    2121         * or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()}
    2122         * if it is necessary to distinguish these cases.
    2123         *
    2124         * @throws IOException
    2125         * @since 3.0
    2126         */
    2127        public boolean hasFeature(String feature, String value) throws IOException {
    2128            if (!initFeatureMap()) {
    2129                return false;
    2130            }
    2131            Set<String> entries = __featuresMap.get(feature.toUpperCase(Locale.ENGLISH));
    2132            if (entries != null) {
    2133                return entries.contains(value);
    2134            }
    2135            return false;
    2136        }
    2137
    2138        /*
    2139         * Create the feature map if not already created.
    2140         */
    2141        private boolean initFeatureMap() throws IOException {
    2142            if (__featuresMap == null) {
    2143                // Don't create map here, because next line may throw exception
    2144                boolean success = FTPReply.isPositiveCompletion(feat());
    2145                // we init the map here, so we don't keep trying if we know the command will fail
    2146                __featuresMap = new HashMap<String, Set<String>>();
    2147                if (!success) {
    2148                    return false;
    2149                }
    2150                for (String l : getReplyStrings()) {
    2151                    if (l.startsWith(" ")) { // it's a FEAT entry
    2152                        String key;
    2153                        String value="";
    2154                        int varsep = l.indexOf(' ', 1);
    2155                        if (varsep > 0) {
    2156                            key = l.substring(1, varsep);
    2157                            value = l.substring(varsep+1);
    2158                        } else {
    2159                            key = l.substring(1);
    2160                        }
    2161                        key = key.toUpperCase(Locale.ENGLISH);
    2162                        Set<String> entries = __featuresMap.get(key);
    2163                        if (entries == null) {
    2164                            entries = new HashSet<String>();
    2165                            __featuresMap.put(key, entries);
    2166                        }
    2167                        entries.add(value);
    2168                    }
    2169                }
    2170            }
    2171            return true;
    2172        }
    2173
    2174        /**
    2175         * Reserve space on the server for the next file transfer.
    2176         * <p>
    2177         * @param bytes  The number of bytes which the server should allocate.
    2178         * @param recordSize  The size of a file record.
    2179         * @return True if successfully completed, false if not.
    2180         * @exception FTPConnectionClosedException
    2181         *      If the FTP server prematurely closes the connection as a result
    2182         *      of the client being idle or some other reason causing the server
    2183         *      to send FTP reply code 421.  This exception may be caught either
    2184         *      as an IOException or independently as itself.
    2185         * @exception IOException  If an I/O error occurs while either sending a
    2186         *      command to the server or receiving a reply from the server.
    2187         */
    2188        public boolean allocate(int bytes, int recordSize) throws IOException
    2189        {
    2190            return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
    2191        }
    2192
    2193
    2194        /**
    2195         * Issue a command and wait for the reply.
    2196         * <p>
    2197         * Should only be used with commands that return replies on the
    2198         * command channel - do not use for LIST, NLST, MLSD etc.
    2199         * <p>
    2200         * @param command  The command to invoke
    2201         * @param params  The parameters string, may be {@code null}
    2202         * @return True if successfully completed, false if not, in which case
    2203         * call {@link #getReplyCode()} or {@link #getReplyString()}
    2204         * to get the reason.
    2205         *
    2206         * @exception IOException  If an I/O error occurs while either sending a
    2207         *      command to the server or receiving a reply from the server.
    2208         * @since 3.0
    2209         */
    2210        public boolean doCommand(String command, String params) throws IOException
    2211        {
    2212            return FTPReply.isPositiveCompletion(sendCommand(command, params));
    2213        }
    2214
    2215        /**
    2216         * Issue a command and wait for the reply, returning it as an array of strings.
    2217         * <p>
    2218         * Should only be used with commands that return replies on the
    2219         * command channel - do not use for LIST, NLST, MLSD etc.
    2220         * <p>
    2221         * @param command  The command to invoke
    2222         * @param params  The parameters string, may be {@code null}
    2223         * @return The array of replies, or {@code null} if the command failed, in which case
    2224         * call {@link #getReplyCode()} or {@link #getReplyString()}
    2225         * to get the reason.
    2226         *
    2227         * @exception IOException  If an I/O error occurs while either sending a
    2228         *      command to the server or receiving a reply from the server.
    2229         * @since 3.0
    2230         */
    2231        public String[] doCommandAsStrings(String command, String params) throws IOException
    2232        {
    2233            boolean success = FTPReply.isPositiveCompletion(sendCommand(command, params));
    2234            if (success){
    2235                return getReplyStrings();
    2236            } else {
    2237                return null;
    2238            }
    2239        }
    2240
    2241        /**
    2242         * Get file details using the MLST command
    2243         *
    2244         * @param pathname the file or directory to list, may be {@code} null
    2245         * @return the file details, may be {@code null}
    2246         * @throws IOException
    2247         * @since 3.0
    2248         */
    2249        public FTPFile mlistFile(String pathname) throws IOException
    2250        {
    2251            boolean success = FTPReply.isPositiveCompletion(sendCommand(FTPCommand.MLST, pathname));
    2252            if (success){
    2253                String entry = getReplyStrings()[1].substring(1); // skip leading space for parser
    2254                return MLSxEntryParser.parseEntry(entry);
    2255            } else {
    2256                return null;
    2257            }
    2258        }
    2259
    2260        /**
    2261         * Generate a directory listing for the current directory using the MLSD command.
    2262         *
    2263         * @return the array of file entries
    2264         * @throws IOException
    2265         * @since 3.0
    2266         */
    2267        public FTPFile[] mlistDir() throws IOException
    2268        {
    2269            return mlistDir(null);
    2270        }
    2271
    2272        /**
    2273         * Generate a directory listing using the MLSD command.
    2274         *
    2275         * @param pathname the directory name, may be {@code null}
    2276         * @return the array of file entries
    2277         * @throws IOException
    2278         * @since 3.0
    2279         */
    2280        public FTPFile[] mlistDir(String pathname) throws IOException
    2281        {
    2282            FTPListParseEngine engine = initiateMListParsing( pathname);
    2283            return engine.getFiles();
    2284        }
    2285
    2286        /**
    2287         * Generate a directory listing using the MLSD command.
    2288         *
    2289         * @param pathname the directory name, may be {@code null}
    2290         * @param filter the filter to apply to the responses
    2291         * @return the array of file entries
    2292         * @throws IOException
    2293         * @since 3.0
    2294         */
    2295        public FTPFile[] mlistDir(String pathname, FTPFileFilter filter) throws IOException
    2296        {
    2297            FTPListParseEngine engine = initiateMListParsing( pathname);
    2298            return engine.getFiles(filter);
    2299        }
    2300
    2301        /***
    2302         * Restart a <code>STREAM_TRANSFER_MODE</code> file transfer starting
    2303         * from the given offset.  This will only work on FTP servers supporting
    2304         * the REST comand for the stream transfer mode.  However, most FTP
    2305         * servers support this.  Any subsequent file transfer will start
    2306         * reading or writing the remote file from the indicated offset.
    2307         * <p>
    2308         * @param offset  The offset into the remote file at which to start the
    2309         *           next file transfer.
    2310         * @return True if successfully completed, false if not.
    2311         * @exception FTPConnectionClosedException
    2312         *      If the FTP server prematurely closes the connection as a result
    2313         *      of the client being idle or some other reason causing the server
    2314         *      to send FTP reply code 421.  This exception may be caught either
    2315         *      as an IOException or independently as itself.
    2316         * @exception IOException  If an I/O error occurs while either sending a
    2317         *      command to the server or receiving a reply from the server.
    2318         ***/
    2319        protected boolean restart(long offset) throws IOException
    2320        {
    2321            __restartOffset = 0;
    2322            return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
    2323        }
    2324
    2325        /***
    2326         * Sets the restart offset.  The restart command is sent to the server
    2327         * only before sending the file transfer command.  When this is done,
    2328         * the restart marker is reset to zero.
    2329         * <p>
    2330         * @param offset  The offset into the remote file at which to start the
    2331         *           next file transfer.  This must be a value greater than or
    2332         *           equal to zero.
    2333         ***/
    2334        public void setRestartOffset(long offset)
    2335        {
    2336            if (offset >= 0) {
    2337                __restartOffset = offset;
    2338            }
    2339        }
    2340
    2341        /***
    2342         * Fetches the restart offset.
    2343         * <p>
    2344         * @return offset  The offset into the remote file at which to start the
    2345         *           next file transfer.
    2346         ***/
    2347        public long getRestartOffset()
    2348        {
    2349            return __restartOffset;
    2350        }
    2351
    2352
    2353
    2354        /***
    2355         * Renames a remote file.
    2356         * <p>
    2357         * @param from  The name of the remote file to rename.
    2358         * @param to    The new name of the remote file.
    2359         * @return True if successfully completed, false if not.
    2360         * @exception FTPConnectionClosedException
    2361         *      If the FTP server prematurely closes the connection as a result
    2362         *      of the client being idle or some other reason causing the server
    2363         *      to send FTP reply code 421.  This exception may be caught either
    2364         *      as an IOException or independently as itself.
    2365         * @exception IOException  If an I/O error occurs while either sending a
    2366         *      command to the server or receiving a reply from the server.
    2367         ***/
    2368        public boolean rename(String from, String to) throws IOException
    2369        {
    2370            if (!FTPReply.isPositiveIntermediate(rnfr(from))) {
    2371                return false;
    2372            }
    2373
    2374            return FTPReply.isPositiveCompletion(rnto(to));
    2375        }
    2376
    2377
    2378        /***
    2379         * Abort a transfer in progress.
    2380         * <p>
    2381         * @return True if successfully completed, false if not.
    2382         * @exception FTPConnectionClosedException
    2383         *      If the FTP server prematurely closes the connection as a result
    2384         *      of the client being idle or some other reason causing the server
    2385         *      to send FTP reply code 421.  This exception may be caught either
    2386         *      as an IOException or independently as itself.
    2387         * @exception IOException  If an I/O error occurs while either sending a
    2388         *      command to the server or receiving a reply from the server.
    2389         ***/
    2390        public boolean abort() throws IOException
    2391        {
    2392            return FTPReply.isPositiveCompletion(abor());
    2393        }
    2394
    2395        /***
    2396         * Deletes a file on the FTP server.
    2397         * <p>
    2398         * @param pathname   The pathname of the file to be deleted.
    2399         * @return True if successfully completed, false if not.
    2400         * @exception FTPConnectionClosedException
    2401         *      If the FTP server prematurely closes the connection as a result
    2402         *      of the client being idle or some other reason causing the server
    2403         *      to send FTP reply code 421.  This exception may be caught either
    2404         *      as an IOException or independently as itself.
    2405         * @exception IOException  If an I/O error occurs while either sending a
    2406         *      command to the server or receiving a reply from the server.
    2407         ***/
    2408        public boolean deleteFile(String pathname) throws IOException
    2409        {
    2410            return FTPReply.isPositiveCompletion(dele(pathname));
    2411        }
    2412
    2413
    2414        /***
    2415         * Removes a directory on the FTP server (if empty).
    2416         * <p>
    2417         * @param pathname  The pathname of the directory to remove.
    2418         * @return True if successfully completed, false if not.
    2419         * @exception FTPConnectionClosedException
    2420         *      If the FTP server prematurely closes the connection as a result
    2421         *      of the client being idle or some other reason causing the server
    2422         *      to send FTP reply code 421.  This exception may be caught either
    2423         *      as an IOException or independently as itself.
    2424         * @exception IOException  If an I/O error occurs while either sending a
    2425         *      command to the server or receiving a reply from the server.
    2426         ***/
    2427        public boolean removeDirectory(String pathname) throws IOException
    2428        {
    2429            return FTPReply.isPositiveCompletion(rmd(pathname));
    2430        }
    2431
    2432
    2433        /***
    2434         * Creates a new subdirectory on the FTP server in the current directory
    2435         * (if a relative pathname is given) or where specified (if an absolute
    2436         * pathname is given).
    2437         * <p>
    2438         * @param pathname The pathname of the directory to create.
    2439         * @return True if successfully completed, false if not.
    2440         * @exception FTPConnectionClosedException
    2441         *      If the FTP server prematurely closes the connection as a result
    2442         *      of the client being idle or some other reason causing the server
    2443         *      to send FTP reply code 421.  This exception may be caught either
    2444         *      as an IOException or independently as itself.
    2445         * @exception IOException  If an I/O error occurs while either sending a
    2446         *      command to the server or receiving a reply from the server.
    2447         ***/
    2448        public boolean makeDirectory(String pathname) throws IOException
    2449        {
    2450            return FTPReply.isPositiveCompletion(mkd(pathname));
    2451        }
    2452
    2453
    2454        /***
    2455         * Returns the pathname of the current working directory.
    2456         * <p>
    2457         * @return The pathname of the current working directory.  If it cannot
    2458         *         be obtained, returns null.
    2459         * @exception FTPConnectionClosedException
    2460         *      If the FTP server prematurely closes the connection as a result
    2461         *      of the client being idle or some other reason causing the server
    2462         *      to send FTP reply code 421.  This exception may be caught either
    2463         *      as an IOException or independently as itself.
    2464         * @exception IOException  If an I/O error occurs while either sending a
    2465         *      command to the server or receiving a reply from the server.
    2466         ***/
    2467        public String printWorkingDirectory() throws IOException
    2468        {
    2469            if (pwd() != FTPReply.PATHNAME_CREATED) {
    2470                return null;
    2471            }
    2472
    2473            return __parsePathname(_replyLines.get( _replyLines.size() - 1));
    2474        }
    2475
    2476
    2477        /**
    2478         * Send a site specific command.
    2479         * @param arguments The site specific command and arguments.
    2480         * @return True if successfully completed, false if not.
    2481         * @exception FTPConnectionClosedException
    2482         *      If the FTP server prematurely closes the connection as a result
    2483         *      of the client being idle or some other reason causing the server
    2484         *      to send FTP reply code 421.  This exception may be caught either
    2485         *      as an IOException or independently as itself.
    2486         * @exception IOException  If an I/O error occurs while either sending a
    2487         *      command to the server or receiving a reply from the server.
    2488         */
    2489        public boolean sendSiteCommand(String arguments) throws IOException
    2490        {
    2491            return FTPReply.isPositiveCompletion(site(arguments));
    2492        }
    2493
    2494
    2495        /***
    2496         * Fetches the system type from the server and returns the string.
    2497         * This value is cached for the duration of the connection after the
    2498         * first call to this method.  In other words, only the first time
    2499         * that you invoke this method will it issue a SYST command to the
    2500         * FTP server.  FTPClient will remember the value and return the
    2501         * cached value until a call to disconnect.
    2502         * <p>
    2503         * If the SYST command fails, and the system property
    2504         * {@link #FTP_SYSTEM_TYPE_DEFAULT} is defined, then this is used instead.
    2505         * @return The system type obtained from the server. Never null.
    2506         * @exception FTPConnectionClosedException
    2507         *      If the FTP server prematurely closes the connection as a result
    2508         *      of the client being idle or some other reason causing the server
    2509         *      to send FTP reply code 421.  This exception may be caught either
    2510         *      as an IOException or independently as itself.
    2511         * @exception IOException  If an I/O error occurs while either sending a
    2512         *  command to the server or receiving a reply from the server (and the default
    2513         *  system type property is not defined)
    2514         *  @since 2.2
    2515         ***/
    2516        public String getSystemType() throws IOException
    2517        {
    2518            //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
    2519            // Technically, we should expect a NAME_SYSTEM_TYPE response, but
    2520            // in practice FTP servers deviate, so we soften the condition to
    2521            // a positive completion.
    2522            if (__systemName == null){
    2523                if (FTPReply.isPositiveCompletion(syst())) {
    2524                    // Assume that response is not empty here (cannot be null)
    2525                    __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
    2526                } else {
    2527                    // Check if the user has provided a default for when the SYST command fails
    2528                    String systDefault = System.getProperty(FTP_SYSTEM_TYPE_DEFAULT);
    2529                    if (systDefault != null) {
    2530                        __systemName = systDefault;
    2531                    } else {
    2532                        throw new IOException("Unable to determine system type - response: " + getReplyString());
    2533                    }
    2534                }
    2535            }
    2536            return __systemName;
    2537        }
    2538
    2539
    2540        /***
    2541         * Fetches the system help information from the server and returns the
    2542         * full string.
    2543         * <p>
    2544         * @return The system help string obtained from the server.  null if the
    2545         *       information could not be obtained.
    2546         * @exception FTPConnectionClosedException
    2547         *      If the FTP server prematurely closes the connection as a result
    2548         *      of the client being idle or some other reason causing the server
    2549         *      to send FTP reply code 421.  This exception may be caught either
    2550         *      as an IOException or independently as itself.
    2551         * @exception IOException  If an I/O error occurs while either sending a
    2552         *  command to the server or receiving a reply from the server.
    2553         ***/
    2554        public String listHelp() throws IOException
    2555        {
    2556            if (FTPReply.isPositiveCompletion(help())) {
    2557                return getReplyString();
    2558            }
    2559            return null;
    2560        }
    2561
    2562
    2563        /**
    2564         * Fetches the help information for a given command from the server and
    2565         * returns the full string.
    2566         * @param command The command on which to ask for help.
    2567         * @return The command help string obtained from the server.  null if the
    2568         *       information could not be obtained.
    2569         * @exception FTPConnectionClosedException
    2570         *      If the FTP server prematurely closes the connection as a result
    2571         *      of the client being idle or some other reason causing the server
    2572         *      to send FTP reply code 421.  This exception may be caught either
    2573         *      as an IOException or independently as itself.
    2574         * @exception IOException  If an I/O error occurs while either sending a
    2575         *  command to the server or receiving a reply from the server.
    2576         */
    2577        public String listHelp(String command) throws IOException
    2578        {
    2579            if (FTPReply.isPositiveCompletion(help(command))) {
    2580                return getReplyString();
    2581            }
    2582            return null;
    2583        }
    2584
    2585
    2586        /***
    2587         * Sends a NOOP command to the FTP server.  This is useful for preventing
    2588         * server timeouts.
    2589         * <p>
    2590         * @return True if successfully completed, false if not.
    2591         * @exception FTPConnectionClosedException
    2592         *      If the FTP server prematurely closes the connection as a result
    2593         *      of the client being idle or some other reason causing the server
    2594         *      to send FTP reply code 421.  This exception may be caught either
    2595         *      as an IOException or independently as itself.
    2596         * @exception IOException  If an I/O error occurs while either sending a
    2597         *      command to the server or receiving a reply from the server.
    2598         ***/
    2599        public boolean sendNoOp() throws IOException
    2600        {
    2601            return FTPReply.isPositiveCompletion(noop());
    2602        }
    2603
    2604
    2605        /***
    2606         * Obtain a list of filenames in a directory (or just the name of a given
    2607         * file, which is not particularly useful).  This information is obtained
    2608         * through the NLST command.  If the given pathname is a directory and
    2609         * contains no files,  a zero length array is returned only
    2610         * if the FTP server returned a positive completion code, otherwise
    2611         * null is returned (the FTP server returned a 550 error No files found.).
    2612         * If the directory is not empty, an array of filenames in the directory is
    2613         * returned. If the pathname corresponds
    2614         * to a file, only that file will be listed.  The server may or may not
    2615         * expand glob expressions.
    2616         * <p>
    2617         * @param pathname  The file or directory to list.
    2618         * @return The list of filenames contained in the given path.  null if
    2619         *     the list could not be obtained.  If there are no filenames in
    2620         *     the directory, a zero-length array is returned.
    2621         * @exception FTPConnectionClosedException
    2622         *      If the FTP server prematurely closes the connection as a result
    2623         *      of the client being idle or some other reason causing the server
    2624         *      to send FTP reply code 421.  This exception may be caught either
    2625         *      as an IOException or independently as itself.
    2626         * @exception IOException  If an I/O error occurs while either sending a
    2627         *      command to the server or receiving a reply from the server.
    2628         ***/
    2629        public String[] listNames(String pathname) throws IOException
    2630        {
    2631            Socket socket;
    2632
    2633            if ((socket = _openDataConnection_(FTPCommand.NLST, getListArguments(pathname))) == null) {
    2634                return null;
    2635            }
    2636
    2637            BufferedReader reader =
    2638                new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding()));
    2639
    2640            ArrayList<String> results = new ArrayList<String>();
    2641            String line;
    2642            while ((line = reader.readLine()) != null) {
    2643                results.add(line);
    2644            }
    2645
    2646            reader.close();
    2647            socket.close();
    2648
    2649            if (completePendingCommand())
    2650            {
    2651                String[] names = new String[ results.size() ];
    2652                return results.toArray(names);
    2653            }
    2654
    2655            return null;
    2656        }
    2657
    2658
    2659        /***
    2660         * Obtain a list of filenames in the current working directory
    2661         * This information is obtained through the NLST command.  If the current
    2662         * directory contains no files, a zero length array is returned only
    2663         * if the FTP server returned a positive completion code, otherwise,
    2664         * null is returned (the FTP server returned a 550 error No files found.).
    2665         * If the directory is not empty, an array of filenames in the directory is
    2666         * returned.
    2667         * <p>
    2668         * @return The list of filenames contained in the current working
    2669         *     directory.  null if the list could not be obtained.
    2670         *     If there are no filenames in the directory, a zero-length array
    2671         *     is returned.
    2672         * @exception FTPConnectionClosedException
    2673         *      If the FTP server prematurely closes the connection as a result
    2674         *      of the client being idle or some other reason causing the server
    2675         *      to send FTP reply code 421.  This exception may be caught either
    2676         *      as an IOException or independently as itself.
    2677         * @exception IOException  If an I/O error occurs while either sending a
    2678         *      command to the server or receiving a reply from the server.
    2679         ***/
    2680        public String[] listNames() throws IOException
    2681        {
    2682            return listNames(null);
    2683        }
    2684
    2685
    2686
    2687        /**
    2688         * Using the default system autodetect mechanism, obtain a
    2689         * list of file information for the current working directory
    2690         * or for just a single file.
    2691         * <p>
    2692         * This information is obtained through the LIST command.  The contents of
    2693         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2694         * used.
    2695         * <p>
    2696         * @param pathname  The file or directory to list.  Since the server may
    2697         *                  or may not expand glob expressions, using them here
    2698         *                  is not recommended and may well cause this method to
    2699         *                  fail.
    2700         *
    2701         * @return The list of file information contained in the given path in
    2702         *         the format determined by the autodetection mechanism
    2703         * @exception FTPConnectionClosedException
    2704         *                   If the FTP server prematurely closes the connection
    2705         *                   as a result of the client being idle or some other
    2706         *                   reason causing the server to send FTP reply code 421.
    2707         *                   This exception may be caught either as an IOException
    2708         *                   or independently as itself.
    2709         * @exception IOException
    2710         *                   If an I/O error occurs while either sending a
    2711         *                   command to the server or receiving a reply
    2712         *                   from the server.
    2713         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2714         *                   Thrown if the parserKey parameter cannot be
    2715         *                   resolved by the selected parser factory.
    2716         *                   In the DefaultFTPEntryParserFactory, this will
    2717         *                   happen when parserKey is neither
    2718         *                   the fully qualified class name of a class
    2719         *                   implementing the interface
    2720         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2721         *                   nor a string containing one of the recognized keys
    2722         *                   mapping to such a parser or if class loader
    2723         *                   security issues prevent its being loaded.
    2724         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2725         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2726         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2727         */
    2728        public FTPFile[] listFiles(String pathname)
    2729        throws IOException
    2730        {
    2731            FTPListParseEngine engine = initiateListParsing((String) null, pathname);
    2732            return engine.getFiles();
    2733
    2734        }
    2735
    2736        /**
    2737         * Using the default system autodetect mechanism, obtain a
    2738         * list of file information for the current working directory.
    2739         * <p>
    2740         * This information is obtained through the LIST command.  The contents of
    2741         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2742         * used.
    2743         * <p>
    2744         * @return The list of file information contained in the current directory
    2745         *         in the format determined by the autodetection mechanism.
    2746         *         <p><b>
    2747         *         NOTE:</b> This array may contain null members if any of the
    2748         *         individual file listings failed to parse.  The caller should
    2749         *         check each entry for null before referencing it.
    2750         * @exception FTPConnectionClosedException
    2751         *                   If the FTP server prematurely closes the connection
    2752         *                   as a result of the client being idle or some other
    2753         *                   reason causing the server to send FTP reply code 421.
    2754         *                   This exception may be caught either as an IOException
    2755         *                   or independently as itself.
    2756         * @exception IOException
    2757         *                   If an I/O error occurs while either sending a
    2758         *                   command to the server or receiving a reply
    2759         *                   from the server.
    2760         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2761         *                   Thrown if the parserKey parameter cannot be
    2762         *                   resolved by the selected parser factory.
    2763         *                   In the DefaultFTPEntryParserFactory, this will
    2764         *                   happen when parserKey is neither
    2765         *                   the fully qualified class name of a class
    2766         *                   implementing the interface
    2767         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2768         *                   nor a string containing one of the recognized keys
    2769         *                   mapping to such a parser or if class loader
    2770         *                   security issues prevent its being loaded.
    2771         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2772         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2773         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2774         */
    2775        public FTPFile[] listFiles()
    2776        throws IOException
    2777        {
    2778            return listFiles((String) null);
    2779        }
    2780
    2781        /**
    2782         * Version of {@link #listFiles(String)} which allows a filter to be provided.
    2783         * For example: <code>listFiles("site", FTPFileFilters.DIRECTORY);</code>
    2784         * @param pathname the initial path, may be null
    2785         * @param filter the filter, non-null
    2786         * @return the list of FTPFile entries.
    2787         * @throws IOException
    2788         * @since 2.2
    2789         */
    2790        public FTPFile[] listFiles(String pathname, FTPFileFilter filter)
    2791        throws IOException
    2792        {
    2793            FTPListParseEngine engine = initiateListParsing((String) null, pathname);
    2794            return engine.getFiles(filter);
    2795
    2796        }
    2797
    2798        /**
    2799         * Using the default system autodetect mechanism, obtain a
    2800         * list of directories contained in the current working directory.
    2801         * <p>
    2802         * This information is obtained through the LIST command.  The contents of
    2803         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2804         * used.
    2805         * <p>
    2806         * @return The list of directories contained in the current directory
    2807         *         in the format determined by the autodetection mechanism.
    2808         *
    2809         * @exception FTPConnectionClosedException
    2810         *                   If the FTP server prematurely closes the connection
    2811         *                   as a result of the client being idle or some other
    2812         *                   reason causing the server to send FTP reply code 421.
    2813         *                   This exception may be caught either as an IOException
    2814         *                   or independently as itself.
    2815         * @exception IOException
    2816         *                   If an I/O error occurs while either sending a
    2817         *                   command to the server or receiving a reply
    2818         *                   from the server.
    2819         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2820         *                   Thrown if the parserKey parameter cannot be
    2821         *                   resolved by the selected parser factory.
    2822         *                   In the DefaultFTPEntryParserFactory, this will
    2823         *                   happen when parserKey is neither
    2824         *                   the fully qualified class name of a class
    2825         *                   implementing the interface
    2826         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2827         *                   nor a string containing one of the recognized keys
    2828         *                   mapping to such a parser or if class loader
    2829         *                   security issues prevent its being loaded.
    2830         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2831         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2832         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2833         * @since 3.0
    2834         */
    2835        public FTPFile[] listDirectories() throws IOException {
    2836            return listDirectories((String) null);
    2837        }
    2838
    2839        /**
    2840         * Using the default system autodetect mechanism, obtain a
    2841         * list of directories contained in the specified directory.
    2842         * <p>
    2843         * This information is obtained through the LIST command.  The contents of
    2844         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2845         * used.
    2846         * <p>
    2847         * @return The list of directories contained in the specified directory
    2848         *         in the format determined by the autodetection mechanism.
    2849         *
    2850         * @exception FTPConnectionClosedException
    2851         *                   If the FTP server prematurely closes the connection
    2852         *                   as a result of the client being idle or some other
    2853         *                   reason causing the server to send FTP reply code 421.
    2854         *                   This exception may be caught either as an IOException
    2855         *                   or independently as itself.
    2856         * @exception IOException
    2857         *                   If an I/O error occurs while either sending a
    2858         *                   command to the server or receiving a reply
    2859         *                   from the server.
    2860         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2861         *                   Thrown if the parserKey parameter cannot be
    2862         *                   resolved by the selected parser factory.
    2863         *                   In the DefaultFTPEntryParserFactory, this will
    2864         *                   happen when parserKey is neither
    2865         *                   the fully qualified class name of a class
    2866         *                   implementing the interface
    2867         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2868         *                   nor a string containing one of the recognized keys
    2869         *                   mapping to such a parser or if class loader
    2870         *                   security issues prevent its being loaded.
    2871         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2872         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2873         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2874         * @since 3.0
    2875         */
    2876        public FTPFile[] listDirectories(String parent) throws IOException {
    2877            return listFiles(parent, FTPFileFilters.DIRECTORIES);
    2878        }
    2879
    2880        /**
    2881         * Using the default autodetect mechanism, initialize an FTPListParseEngine
    2882         * object containing a raw file information for the current working
    2883         * directory on the server
    2884         * This information is obtained through the LIST command.  This object
    2885         * is then capable of being iterated to return a sequence of FTPFile
    2886         * objects with information filled in by the
    2887         * <code> FTPFileEntryParser </code> used.
    2888         * <p>
    2889         * This method differs from using the listFiles() methods in that
    2890         * expensive FTPFile objects are not created until needed which may be
    2891         * an advantage on large lists.
    2892         *
    2893         * @return A FTPListParseEngine object that holds the raw information and
    2894         * is capable of providing parsed FTPFile objects, one for each file
    2895         * containing information contained in the given path in the format
    2896         * determined by the <code> parser </code> parameter.   Null will be
    2897         * returned if a data connection cannot be opened.  If the current working
    2898         * directory contains no files, an empty array will be the return.
    2899         *
    2900         * @exception FTPConnectionClosedException
    2901         *                   If the FTP server prematurely closes the connection as a result
    2902         *                   of the client being idle or some other reason causing the server
    2903         *                   to send FTP reply code 421.  This exception may be caught either
    2904         *                   as an IOException or independently as itself.
    2905         * @exception IOException
    2906         *                   If an I/O error occurs while either sending a
    2907         *                   command to the server or receiving a reply from the server.
    2908         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2909         *                   Thrown if the autodetect mechanism cannot
    2910         *                   resolve the type of system we are connected with.
    2911         * @see FTPListParseEngine
    2912         */
    2913        public FTPListParseEngine initiateListParsing()
    2914        throws IOException
    2915        {
    2916            return initiateListParsing((String) null);
    2917        }
    2918
    2919        /**
    2920         * Using the default autodetect mechanism, initialize an FTPListParseEngine
    2921         * object containing a raw file information for the supplied directory.
    2922         * This information is obtained through the LIST command.  This object
    2923         * is then capable of being iterated to return a sequence of FTPFile
    2924         * objects with information filled in by the
    2925         * <code> FTPFileEntryParser </code> used.
    2926         * <p>
    2927         * The server may or may not expand glob expressions.  You should avoid
    2928         * using glob expressions because the return format for glob listings
    2929         * differs from server to server and will likely cause this method to fail.
    2930         * <p>
    2931         * This method differs from using the listFiles() methods in that
    2932         * expensive FTPFile objects are not created until needed which may be
    2933         * an advantage on large lists.
    2934         * <p>
    2935         * <pre>
    2936         *    FTPClient f=FTPClient();
    2937         *    f.connect(server);
    2938         *    f.login(username, password);
    2939         *    FTPListParseEngine engine = f.initiateListParsing(directory);
    2940         *
    2941         *    while (engine.hasNext()) {
    2942         *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    2943         *       //do whatever you want with these files, display them, etc.
    2944         *       //expensive FTPFile objects not created until needed.
    2945         *    }
    2946         * </pre>
    2947         *
    2948         * @return A FTPListParseEngine object that holds the raw information and
    2949         * is capable of providing parsed FTPFile objects, one for each file
    2950         * containing information contained in the given path in the format
    2951         * determined by the <code> parser </code> parameter.   Null will be
    2952         * returned if a data connection cannot be opened.  If the current working
    2953         * directory contains no files, an empty array will be the return.
    2954         *
    2955         * @exception FTPConnectionClosedException
    2956         *                   If the FTP server prematurely closes the connection as a result
    2957         *                   of the client being idle or some other reason causing the server
    2958         *                   to send FTP reply code 421.  This exception may be caught either
    2959         *                   as an IOException or independently as itself.
    2960         * @exception IOException
    2961         *                   If an I/O error occurs while either sending a
    2962         *                   command to the server or receiving a reply from the server.
    2963         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    2964         *                   Thrown if the autodetect mechanism cannot
    2965         *                   resolve the type of system we are connected with.
    2966         * @see FTPListParseEngine
    2967         */
    2968        public FTPListParseEngine initiateListParsing(
    2969                String pathname)
    2970        throws IOException
    2971        {
    2972            return initiateListParsing((String) null, pathname);
    2973        }
    2974
    2975        /**
    2976         * Using the supplied parser key, initialize an FTPListParseEngine
    2977         * object containing a raw file information for the supplied directory.
    2978         * This information is obtained through the LIST command.  This object
    2979         * is then capable of being iterated to return a sequence of FTPFile
    2980         * objects with information filled in by the
    2981         * <code> FTPFileEntryParser </code> used.
    2982         * <p>
    2983         * The server may or may not expand glob expressions.  You should avoid
    2984         * using glob expressions because the return format for glob listings
    2985         * differs from server to server and will likely cause this method to fail.
    2986         * <p>
    2987         * This method differs from using the listFiles() methods in that
    2988         * expensive FTPFile objects are not created until needed which may be
    2989         * an advantage on large lists.
    2990         *
    2991         * @param parserKey A string representing a designated code or fully-qualified
    2992         * class name of an  <code> FTPFileEntryParser </code> that should be
    2993         *               used to parse each server file listing.
    2994         *               May be {@code null}, in which case the code checks first
    2995         *               the system property {@link #FTP_SYSTEM_TYPE}, and if that is
    2996         *               not defined the SYST command is used to provide the value.
    2997         *               To allow for arbitrary system types, the return from the
    2998         *               SYST command is used to look up an alias for the type in the
    2999         *               {@link #SYSTEM_TYPE_PROPERTIES} properties file if it is available.
    3000         *
    3001         * @return A FTPListParseEngine object that holds the raw information and
    3002         * is capable of providing parsed FTPFile objects, one for each file
    3003         * containing information contained in the given path in the format
    3004         * determined by the <code> parser </code> parameter.   Null will be
    3005         * returned if a data connection cannot be opened.  If the current working
    3006         * directory contains no files, an empty array will be the return.
    3007         *
    3008         * @exception FTPConnectionClosedException
    3009         *                   If the FTP server prematurely closes the connection as a result
    3010         *                   of the client being idle or some other reason causing the server
    3011         *                   to send FTP reply code 421.  This exception may be caught either
    3012         *                   as an IOException or independently as itself.
    3013         * @exception IOException
    3014         *                   If an I/O error occurs while either sending a
    3015         *                   command to the server or receiving a reply from the server.
    3016         * @exception org.apache.commons.net.ftp.parser.ParserInitializationException
    3017         *                   Thrown if the parserKey parameter cannot be
    3018         *                   resolved by the selected parser factory.
    3019         *                   In the DefaultFTPEntryParserFactory, this will
    3020         *                   happen when parserKey is neither
    3021         *                   the fully qualified class name of a class
    3022         *                   implementing the interface
    3023         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    3024         *                   nor a string containing one of the recognized keys
    3025         *                   mapping to such a parser or if class loader
    3026         *                   security issues prevent its being loaded.
    3027         * @see FTPListParseEngine
    3028         */
    3029        public FTPListParseEngine initiateListParsing(
    3030                String parserKey, String pathname)
    3031        throws IOException
    3032        {
    3033            // We cache the value to avoid creation of a new object every
    3034            // time a file listing is generated.
    3035            if(__entryParser == null ||  ! __entryParserKey.equals(parserKey)) {
    3036                if (null != parserKey) {
    3037                    // if a parser key was supplied in the parameters,
    3038                    // use that to create the parser
    3039                    __entryParser =
    3040                        __parserFactory.createFileEntryParser(parserKey);
    3041                    __entryParserKey = parserKey;
    3042
    3043                } else {
    3044                    // if no parserKey was supplied, check for a configuration
    3045                    // in the params, and if non-null, use that.
    3046                    if (null != __configuration) {
    3047                        __entryParser =
    3048                            __parserFactory.createFileEntryParser(__configuration);
    3049                        __entryParserKey = __configuration.getServerSystemKey();
    3050                    } else {
    3051                        // if a parserKey hasn't been supplied, and a configuration
    3052                        // hasn't been supplied, and the override property is not set
    3053                        // then autodetect by calling
    3054                        // the SYST command and use that to choose the parser.
    3055                        String systemType = System.getProperty(FTP_SYSTEM_TYPE);
    3056                        if (systemType == null) {
    3057                            systemType = getSystemType(); // cannot be null
    3058                            Properties override = getOverrideProperties();
    3059                            if (override != null) {
    3060                                String newType = override.getProperty(systemType);
    3061                                if (newType != null) {
    3062                                    systemType = newType;
    3063                                }
    3064                            }
    3065                        }
    3066                        __entryParser = __parserFactory.createFileEntryParser(systemType);
    3067                        __entryParserKey = systemType;
    3068                    }
    3069                }
    3070            }
    3071
    3072            return initiateListParsing(__entryParser, pathname);
    3073
    3074        }
    3075
    3076        /**
    3077         * private method through which all listFiles() and
    3078         * initiateListParsing methods pass once a parser is determined.
    3079         *
    3080         * @exception FTPConnectionClosedException
    3081         *                   If the FTP server prematurely closes the connection as a result
    3082         *                   of the client being idle or some other reason causing the server
    3083         *                   to send FTP reply code 421.  This exception may be caught either
    3084         *                   as an IOException or independently as itself.
    3085         * @exception IOException
    3086         *                   If an I/O error occurs while either sending a
    3087         *                   command to the server or receiving a reply from the server.
    3088         * @see FTPListParseEngine
    3089         */
    3090        private FTPListParseEngine initiateListParsing(
    3091                FTPFileEntryParser parser, String pathname)
    3092        throws IOException
    3093        {
    3094            Socket socket;
    3095
    3096            FTPListParseEngine engine = new FTPListParseEngine(parser);
    3097            if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null)
    3098            {
    3099                return engine;
    3100            }
    3101
    3102            try {
    3103                engine.readServerList(socket.getInputStream(), getControlEncoding());
    3104            }
    3105            finally {
    3106                Util.closeQuietly(socket);
    3107            }
    3108
    3109            completePendingCommand();
    3110            return engine;
    3111        }
    3112
    3113        /**
    3114         * Initiate list parsing for MLSD listings.
    3115         *
    3116         * @param pathname
    3117         * @return the engine
    3118         * @throws IOException
    3119         */
    3120        private FTPListParseEngine initiateMListParsing(String pathname) throws IOException
    3121        {
    3122            Socket socket;
    3123            FTPListParseEngine engine = new FTPListParseEngine(MLSxEntryParser.getInstance());
    3124            if ((socket = _openDataConnection_(FTPCommand.MLSD, pathname)) == null)
    3125            {
    3126                return engine;
    3127            }
    3128
    3129            try {
    3130                engine.readServerList(socket.getInputStream(), getControlEncoding());
    3131            }
    3132            finally {
    3133                Util.closeQuietly(socket);
    3134                completePendingCommand();
    3135            }
    3136            return engine;
    3137        }
    3138
    3139        /**
    3140         * @since 2.0
    3141         */
    3142        protected String getListArguments(String pathname) {
    3143            if (getListHiddenFiles())
    3144            {
    3145                if (pathname != null)
    3146                {
    3147                    StringBuilder sb = new StringBuilder(pathname.length() + 3);
    3148                    sb.append("-a ");
    3149                    sb.append(pathname);
    3150                    return sb.toString();
    3151                }
    3152                else
    3153                {
    3154                    return "-a";
    3155                }
    3156            }
    3157
    3158            return pathname;
    3159        }
    3160
    3161
    3162        /***
    3163         * Issue the FTP STAT command to the server.
    3164         * <p>
    3165         * @return The status information returned by the server.
    3166         * @exception FTPConnectionClosedException
    3167         *      If the FTP server prematurely closes the connection as a result
    3168         *      of the client being idle or some other reason causing the server
    3169         *      to send FTP reply code 421.  This exception may be caught either
    3170         *      as an IOException or independently as itself.
    3171         * @exception IOException  If an I/O error occurs while either sending a
    3172         *      command to the server or receiving a reply from the server.
    3173         ***/
    3174        public String getStatus() throws IOException
    3175        {
    3176            if (FTPReply.isPositiveCompletion(stat())) {
    3177                return getReplyString();
    3178            }
    3179            return null;
    3180        }
    3181
    3182
    3183        /***
    3184         * Issue the FTP STAT command to the server for a given pathname.  This
    3185         * should produce a listing of the file or directory.
    3186         * <p>
    3187         * @return The status information returned by the server.
    3188         * @exception FTPConnectionClosedException
    3189         *      If the FTP server prematurely closes the connection as a result
    3190         *      of the client being idle or some other reason causing the server
    3191         *      to send FTP reply code 421.  This exception may be caught either
    3192         *      as an IOException or independently as itself.
    3193         * @exception IOException  If an I/O error occurs while either sending a
    3194         *      command to the server or receiving a reply from the server.
    3195         ***/
    3196        public String getStatus(String pathname) throws IOException
    3197        {
    3198            if (FTPReply.isPositiveCompletion(stat(pathname))) {
    3199                return getReplyString();
    3200            }
    3201            return null;
    3202        }
    3203
    3204
    3205        /**
    3206         * Issue the FTP MDTM command (not supported by all servers to retrieve the last
    3207         * modification time of a file. The modification string should be in the
    3208         * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in
    3209         * GMT, but not all FTP servers honour this.
    3210         *
    3211         * @param pathname The file path to query.
    3212         * @return A string representing the last file modification time in <code>YYYYMMDDhhmmss</code> format.
    3213         * @throws IOException if an I/O error occurs.
    3214         * @since 2.0
    3215         */
    3216        public String getModificationTime(String pathname) throws IOException {
    3217            if (FTPReply.isPositiveCompletion(mdtm(pathname))) {
    3218                return getReplyString();
    3219            }
    3220            return null;
    3221        }
    3222
    3223
    3224        /**
    3225         * Issue the FTP MFMT command (not supported by all servers) which sets the last
    3226         * modified time of a file.
    3227         *
    3228         * The timestamp should be in the form <code>YYYYMMDDhhmmss</code>. It should also
    3229         * be in GMT, but not all servers honour this.
    3230         *
    3231         * An FTP server would indicate its support of this feature by including "MFMT"
    3232         * in its response to the FEAT command, which may be retrieved by FTPClient.features()
    3233         *
    3234         * @param pathname The file path for which last modified time is to be changed.
    3235         * @param timeval The timestamp to set to, in <code>YYYYMMDDhhmmss</code> format.
    3236         * @return true if successfully set, false if not
    3237         * @throws IOException if an I/O error occurs.
    3238         * @since 2.2
    3239         * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
    3240         */
    3241        public boolean setModificationTime(String pathname, String timeval) throws IOException {
    3242            return (FTPReply.isPositiveCompletion(mfmt(pathname, timeval)));
    3243        }
    3244
    3245
    3246        /**
    3247         * Set the internal buffer size.
    3248         *
    3249         * @param bufSize The size of the buffer
    3250         */
    3251        public void setBufferSize(int bufSize) {
    3252            __bufferSize = bufSize;
    3253        }
    3254
    3255        /**
    3256         * Retrieve the current internal buffer size.
    3257         * @return The current buffer size.
    3258         */
    3259        public int getBufferSize() {
    3260            return __bufferSize;
    3261        }
    3262
    3263
    3264        /**
    3265         * Implementation of the {@link Configurable Configurable} interface.
    3266         * In the case of this class, configuring merely makes the config object available for the
    3267         * factory methods that construct parsers.
    3268         * @param config {@link FTPClientConfig FTPClientConfig} object used to
    3269         * provide non-standard configurations to the parser.
    3270         * @since 1.4
    3271         */
    3272        public void configure(FTPClientConfig config) {
    3273            this.__configuration = config;
    3274        }
    3275
    3276        /**
    3277         * You can set this to true if you would like to get hidden files when {@link #listFiles} too.
    3278         * A <code>LIST -a</code> will be issued to the ftp server.
    3279         * It depends on your ftp server if you need to call this method, also dont expect to get rid
    3280         * of hidden files if you call this method with "false".
    3281         *
    3282         * @param listHiddenFiles true if hidden files should be listed
    3283         * @since 2.0
    3284         */
    3285        public void setListHiddenFiles(boolean listHiddenFiles) {
    3286            this.__listHiddenFiles = listHiddenFiles;
    3287        }
    3288
    3289        /**
    3290         * @see #setListHiddenFiles(boolean)
    3291         * @return the current state
    3292         * @since 2.0
    3293         */
    3294        public boolean getListHiddenFiles() {
    3295            return this.__listHiddenFiles;
    3296        }
    3297
    3298        /**
    3299         * Whether should attempt to use EPSV with IPv4.
    3300         * Default (if not set) is <code>false</code>
    3301         * @return true if should attempt EPSV
    3302         * @since 2.2
    3303         */
    3304        public boolean isUseEPSVwithIPv4() {
    3305            return __useEPSVwithIPv4;
    3306        }
    3307
    3308
    3309        /**
    3310         * Set whether to use EPSV with IPv4.
    3311         * Might be worth enabling in some circumstances.
    3312         *
    3313         * For example, when using IPv4 with NAT it
    3314         * may work with some rare configurations.
    3315         * E.g. if FTP server has a static PASV address (external network)
    3316         * and the client is coming from another internal network.
    3317         * In that case the data connection after PASV command would fail,
    3318         * while EPSV would make the client succeed by taking just the port.
    3319         *
    3320         * @param selected value to set.
    3321         * @since 2.2
    3322         */
    3323        public void setUseEPSVwithIPv4(boolean selected) {
    3324            this.__useEPSVwithIPv4 = selected;
    3325        }
    3326
    3327        /**
    3328         * Set the listener to be used when performing store/retrieve operations.
    3329         * The default value (if not set) is {@code null}.
    3330         *
    3331         * @param listener to be used, may be {@code null} to disable
    3332         * @since 3.0
    3333         */
    3334        public void setCopyStreamListener(CopyStreamListener listener){
    3335            __copyStreamListener = listener;
    3336        }
    3337
    3338        /**
    3339         * Obtain the currently active listener.
    3340         *
    3341         * @return the listener, may be {@code null}
    3342         * @since 3.0
    3343         */
    3344        public CopyStreamListener getCopyStreamListener(){
    3345            return __copyStreamListener;
    3346        }
    3347
    3348        /**
    3349         * Set the time to wait between sending control connection keepalive messages
    3350         * when processing file upload or download.
    3351         *
    3352         * @param controlIdle the wait (in secs) between keepalive messages. Zero (or less) disables.
    3353         * @since 3.0
    3354         * @see #setControlKeepAliveReplyTimeout(int)
    3355         */
    3356        public void setControlKeepAliveTimeout(long controlIdle){
    3357            __controlKeepAliveTimeout = controlIdle * 1000;
    3358        }
    3359
    3360        /**
    3361         * Get the time to wait between sending control connection keepalive messages.
    3362         * @return the number of seconds between keepalive messages.
    3363         * @since 3.0
    3364         */
    3365        public long getControlKeepAliveTimeout() {
    3366            return __controlKeepAliveTimeout / 1000;
    3367        }
    3368
    3369        /**
    3370         * Set how long to wait for control keep-alive message replies.
    3371         *
    3372         * @param timeout number of milliseconds to wait (defaults to 1000)
    3373         * @since 3.0
    3374         * @see #setControlKeepAliveTimeout(long)
    3375         */
    3376        public void setControlKeepAliveReplyTimeout(int timeout) {
    3377            __controlKeepAliveReplyTimeout = timeout;
    3378        }
    3379
    3380        /**
    3381         * Get how long to wait for control keep-alive message replies.
    3382         * @since 3.0
    3383         */
    3384        public int getControlKeepAliveReplyTimeout() {
    3385            return __controlKeepAliveReplyTimeout;
    3386        }
    3387
    3388        // @since 3.0
    3389        private static class CSL implements CopyStreamListener {
    3390
    3391            private final FTPClient parent;
    3392            private final long idle;
    3393            private final int currentSoTimeout;
    3394
    3395            private long time = System.currentTimeMillis();
    3396            private int notAcked;
    3397
    3398            CSL(FTPClient parent, long idleTime, int maxWait) throws SocketException {
    3399                this.idle = idleTime;
    3400                this.parent = parent;
    3401                this.currentSoTimeout = parent.getSoTimeout();
    3402                parent.setSoTimeout(maxWait);
    3403            }
    3404
    3405            public void bytesTransferred(CopyStreamEvent event) {
    3406                bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
    3407            }
    3408
    3409            public void bytesTransferred(long totalBytesTransferred,
    3410                    int bytesTransferred, long streamSize) {
    3411                long now = System.currentTimeMillis();
    3412                if (now - time > idle) {
    3413                    try {
    3414                        parent.__noop();
    3415                    } catch (SocketTimeoutException e) {
    3416                        notAcked++;
    3417                    } catch (IOException e) {
    3418                    }
    3419                    time = now;
    3420                }
    3421            }
    3422
    3423            void cleanUp() throws IOException {
    3424                while(notAcked-- > 0) {
    3425                    parent.__getReplyNoReport();
    3426                }
    3427                parent.setSoTimeout(currentSoTimeout);
    3428            }
    3429
    3430        }
    3431
    3432        /**
    3433         * Merge two copystream listeners, either or both of which may be null.
    3434         *
    3435         * @param local the listener used by this class, may be null
    3436         * @return a merged listener or a single listener or null
    3437         * @since 3.0
    3438         */
    3439        private CopyStreamListener __mergeListeners(CopyStreamListener local) {
    3440            if (local == null) {
    3441                return __copyStreamListener;
    3442            }
    3443            if (__copyStreamListener == null) {
    3444                return local;
    3445            }
    3446            // Both are non-null
    3447            CopyStreamAdapter merged = new CopyStreamAdapter();
    3448            merged.addCopyStreamListener(local);
    3449            merged.addCopyStreamListener(__copyStreamListener);
    3450            return merged;
    3451        }
    3452
    3453        /**
    3454         * Enables or disables automatic server encoding detection (only UTF-8 supported).
    3455         * @param autodetect If true, automatic server encoding detection will be enabled.
    3456         */
    3457        public void setAutodetectUTF8(boolean autodetect)
    3458        {
    3459            __autodetectEncoding = autodetect;
    3460        }
    3461
    3462        /**
    3463         * Tells if automatic server encoding detection is enabled or disabled.
    3464         * @return true, if automatic server encoding detection is enabled.
    3465         */
    3466        public boolean getAutodetectUTF8()
    3467        {
    3468            return __autodetectEncoding;
    3469        }
    3470
    3471        // DEPRECATED METHODS - for API compatibility only - DO NOT USE
    3472
    3473        /**
    3474         * @deprecated use {@link #getSystemType()} instead
    3475         */
    3476        @Deprecated
    3477        public String getSystemName() throws IOException
    3478        {
    3479            if (__systemName == null && FTPReply.isPositiveCompletion(syst())) {
    3480                __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
    3481            }
    3482            return __systemName;
    3483        }
    3484    }
    3485
    3486    /* Emacs configuration
    3487     * Local variables:        **
    3488     * mode:             java  **
    3489     * c-basic-offset:   4     **
    3490     * indent-tabs-mode: nil   **
    3491     * End:                    **
    3492     */
    3493    /* kate: indent-width 4; replace-tabs on; */