    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.IOException;
    022    import java.io.InputStream;
    023    import java.io.InputStreamReader;
    024    import java.io.OutputStream;
    025    import java.net.Inet6Address;
    026    import java.net.InetAddress;
    027    import java.net.ServerSocket;
    028    import java.net.Socket;
    029    import java.net.UnknownHostException;
    030    import java.util.ArrayList;
    031    import java.util.Random;
    032
    033    import org.apache.commons.net.MalformedServerReplyException;
    034    import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
    035    import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
    036    import org.apache.commons.net.ftp.parser.ParserInitializationException;
    037    import org.apache.commons.net.io.CopyStreamEvent;
    038    import org.apache.commons.net.io.CopyStreamException;
    039    import org.apache.commons.net.io.FromNetASCIIInputStream;
    040    import org.apache.commons.net.io.ToNetASCIIOutputStream;
    041    import org.apache.commons.net.io.Util;
    042
    043    /***
    044     * FTPClient encapsulates all the functionality necessary to store and
    045     * retrieve files from an FTP server.  This class takes care of all
    046     * low level details of interacting with an FTP server and provides
    047     * a convenient higher level interface.  As with all classes derived
    048     * from {@link org.apache.commons.net.SocketClient},
    049     * you must first connect to the server with
    050     * {@link org.apache.commons.net.SocketClient#connect  connect }
    051     * before doing anything, and finally
    052     * {@link org.apache.commons.net.SocketClient#disconnect  disconnect }
    053     * after you're completely finished interacting with the server.
    054     * Then you need to check the FTP reply code to see if the connection
    055     * was successful.  For example:
    056     * <pre>
    057     *    boolean error = false;
    058     *    try {
    059     *      int reply;
    060     *      ftp.connect("ftp.foobar.com");
    061     *      System.out.println("Connected to " + server + ".");
    062     *      System.out.print(ftp.getReplyString());
    063     *
    064     *      // After connection attempt, you should check the reply code to verify
    065     *      // success.
    066     *      reply = ftp.getReplyCode();
    067     *
    068     *      if(!FTPReply.isPositiveCompletion(reply)) {
    069     *        ftp.disconnect();
    070     *        System.err.println("FTP server refused connection.");
    071     *        System.exit(1);
    072     *      }
    073     *      ... // transfer files
    074     *      ftp.logout();
    075     *    } catch(IOException e) {
    076     *      error = true;
    077     *      e.printStackTrace();
    078     *    } finally {
    079     *      if(ftp.isConnected()) {
    080     *        try {
    081     *          ftp.disconnect();
    082     *        } catch(IOException ioe) {
    083     *          // do nothing
    084     *        }
    085     *      }
    086     *      System.exit(error ? 1 : 0);
    087     *    }
    088     * </pre>
    089     * <p>
    090     * Immediately after connecting is the only real time you need to check the
    091     * reply code (because connect is of type void).  The convention for all the
    092     * FTP command methods in FTPClient is such that they either return a
    093     * boolean value or some other value.
    094     * The boolean methods return true on a successful completion reply from
    095     * the FTP server and false on a reply resulting in an error condition or
    096     * failure.  The methods returning a value other than boolean return a value
    097     * containing the higher level data produced by the FTP command, or null if a
    098     * reply resulted in an error condition or failure.  If you want to access
    099     * the exact FTP reply code causing a success or failure, you must call
    100     * {@link org.apache.commons.net.ftp.FTP#getReplyCode  getReplyCode } after
    101     * a success or failure.
    102     * <p>
    103     * The default settings for FTPClient are for it to use
    104     * <code> FTP.ASCII_FILE_TYPE </code>,
    105     * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    106     * <code> FTP.STREAM_TRANSFER_MODE </code>, and
    107     * <code> FTP.FILE_STRUCTURE </code>.  The only file types directly supported
    108     * are <code> FTP.ASCII_FILE_TYPE </code> and
    109     * <code> FTP.BINARY_FILE_TYPE </code>.  Because there are at least 4
    110     * different EBCDIC encodings, we have opted not to provide direct support
    111     * for EBCDIC.  To transfer EBCDIC and other unsupported file types you
    112     * must create your own filter InputStreams and OutputStreams and wrap
    113     * them around the streams returned or required by the FTPClient methods.
    114     * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
    115     * filter streams to provide transparent handling of ASCII files.  We will
    116     * consider incorporating EBCDIC support if there is enough demand.
    117     * <p>
    118     * <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    119     * <code> FTP.STREAM_TRANSFER_MODE </code>, and
    120     * <code> FTP.FILE_STRUCTURE </code> are the only supported formats,
    121     * transfer modes, and file structures.
    122     * <p>
    123     * Because the handling of sockets on different platforms can differ
    124     * significantly, the FTPClient automatically issues a new PORT (or EPRT) command
    125     * prior to every transfer requiring that the server connect to the client's
    126     * data port.  This ensures identical problem-free behavior on Windows, Unix,
    127     * and Macintosh platforms.  Additionally, it relieves programmers from
    128     * having to issue the PORT (or EPRT) command themselves and dealing with platform
    129     * dependent issues.
    130     * <p>
    131     * Additionally, for security purposes, all data connections to the
    132     * client are verified to ensure that they originated from the intended
    133     * party (host and port).  If a data connection is initiated by an unexpected
    134     * party, the command will close the socket and throw an IOException.  You
    135     * may disable this behavior with
    136     * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
    137     * <p>
    138     * You should keep in mind that the FTP server may choose to prematurely
    139     * close a connection if the client has been idle for longer than a
    140     * given time period (usually 900 seconds).  The FTPClient class will detect a
    141     * premature FTP server connection closing when it receives a
    142     * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
    143     *  response to a command.
    144     * When that occurs, the FTP class method encountering that reply will throw
    145     * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
    146     * .
    147     * <code>FTPConnectionClosedException</code>
    148     * is a subclass of <code> IOException </code> and therefore need not be
    149     * caught separately, but if you are going to catch it separately, its
    150     * catch block must appear before the more general <code> IOException </code>
    151     * catch block.  When you encounter an
    152     * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
    153     * , you must disconnect the connection with
    154     * {@link #disconnect  disconnect() } to properly clean up the
    155     * system resources used by FTPClient.  Before disconnecting, you may check the
    156     * last reply code and text with
    157     * {@link org.apache.commons.net.ftp.FTP#getReplyCode  getReplyCode },
    158     * {@link org.apache.commons.net.ftp.FTP#getReplyString  getReplyString },
    159     * and
    160     * {@link org.apache.commons.net.ftp.FTP#getReplyStrings  getReplyStrings}.
    161     * You may avoid server disconnections while the client is idle by
    162     * periodically sending NOOP commands to the server.
    163     * <p>
    164     * Rather than list it separately for each method, we mention here that
    165     * every method communicating with the server and throwing an IOException
    166     * can also throw a
    167     * {@link org.apache.commons.net.MalformedServerReplyException}
    168     * , which is a subclass
    169     * of IOException.  A MalformedServerReplyException will be thrown when
    170     * the reply received from the server deviates enough from the protocol
    171     * specification that it cannot be interpreted in a useful manner despite
    172     * attempts to be as lenient as possible.
    173     * <p>
    174     * Listing API Examples
    175     * Both paged and unpaged examples of directory listings are available,
    176     * as follows:
    177     * <p>
    178     * Unpaged (whole list) access, using a parser accessible by auto-detect:
    179     * <pre>
    180     *    FTPClient f = new FTPClient();
    181     *    f.connect(server);
    182     *    f.login(username, password);
    183     *    FTPFile[] files = listFiles(directory);
    184     * </pre>
    185     * <p>
    186     * Paged access, using a parser not accessible by auto-detect.  The class
    187     * defined in the first parameter of initateListParsing should be derived
    188     * from org.apache.commons.net.FTPFileEntryParser:
    189     * <pre>
    190     *    FTPClient f = new FTPClient();
    191     *    f.connect(server);
    192     *    f.login(username, password);
    193     *    FTPListParseEngine engine =
    194     *       f.initiateListParsing("com.whatever.YourOwnParser", directory);
    195     *
    196     *    while (engine.hasNext()) {
    197     *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    198     *       //do whatever you want with these files, display them, etc.
    199     *       //expensive FTPFile objects not created until needed.
    200     *    }
    201     * </pre>
    202     * <p>
    203     * Paged access, using a parser accessible by auto-detect:
    204     * <pre>
    205     *    FTPClient f = new FTPClient();
    206     *    f.connect(server);
    207     *    f.login(username, password);
    208     *    FTPListParseEngine engine = f.initiateListParsing(directory);
    209     *
    210     *    while (engine.hasNext()) {
    211     *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    212     *       //do whatever you want with these files, display them, etc.
    213     *       //expensive FTPFile objects not created until needed.
    214     *    }
    215     * </pre>
    216     * <p>
    217     * For examples of using FTPClient on servers whose directory listings
    218     * <ul>
    219     * <li>use languages other than English</li>
    220     * <li>use date formats other than the American English "standard" <code>MM d yyyy</code></li>
    221     * <li>are in different timezones and you need accurate timestamps for dependency checking
    222     *     as in Ant</li>
    223     * </ul>see {@link  FTPClientConfig  FTPClientConfig}.
    224     * <p>
    225     * @author Daniel F. Savarese
    226     * @author Rory Winston
    227     * @see FTP
    228     * @see FTPConnectionClosedException
    229     * @see FTPFileEntryParser
    230     * @see FTPFileEntryParserFactory
    231     * @see DefaultFTPFileEntryParserFactory
    232     * @see FTPClientConfig
    233     *
    234     * @see org.apache.commons.net.MalformedServerReplyException
    235     **/
    236    public class FTPClient extends FTP
    237    implements Configurable
    238    {
    239        /***
    240         * A constant indicating the FTP session is expecting all transfers
    241         * to occur between the client (local) and server and that the server
    242         * should connect to the client's data port to initiate a data transfer.
    243         * This is the default data connection mode when and FTPClient instance
    244         * is created.
    245         ***/
    246        public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
    247        /***
    248         * A constant indicating the FTP session is expecting all transfers
    249         * to occur between two remote servers and that the server
    250         * the client is connected to should connect to the other server's
    251         * data port to initiate a data transfer.
    252         ***/
    253        public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
    254        /***
    255         * A constant indicating the FTP session is expecting all transfers
    256         * to occur between the client (local) and server and that the server
    257         * is in passive mode, requiring the client to connect to the
    258         * server's data port to initiate a transfer.
    259         ***/
    260        public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
    261        /***
    262         * A constant indicating the FTP session is expecting all transfers
    263         * to occur between two remote servers and that the server
    264         * the client is connected to is in passive mode, requiring the other
    265         * server to connect to the first server's data port to initiate a data
    266         * transfer.
    267         ***/
    268        public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
    269
    270        private int __dataConnectionMode, __dataTimeout;
    271        private int __passivePort;
    272        private String __passiveHost;
    273        private final Random __random;
    274        private int __activeMinPort, __activeMaxPort;
    275        private InetAddress __activeExternalHost;
    276        private int __fileType;
    277        @SuppressWarnings("unused") // fields are written, but currently not read
    278        private int __fileFormat, __fileStructure, __fileTransferMode;
    279        private boolean __remoteVerificationEnabled;
    280        private long __restartOffset;
    281        private FTPFileEntryParserFactory __parserFactory;
    282        private int __bufferSize;
    283        private boolean __listHiddenFiles;
    284        private boolean __useEPSVwithIPv4; // whether to attempt EPSV with an IPv4 connection
    285
    286        // __systemName is a cached value that should not be referenced directly
    287        // except when assigned in getSystemName and __initDefaults.
    288        private String __systemName;
    289
    290        // __entryParser is a cached value that should not be referenced directly
    291        // except when assigned in listFiles(String, String) and __initDefaults.
    292        private FTPFileEntryParser __entryParser;
    293
    294        // Key used to create the parser; necessary to ensure that the parser type is not ignored
    295        private String __entryParserKey;
    296
    297        private FTPClientConfig __configuration;
    298
    299        /** Pattern for PASV mode responses */
    300        private static final String __parms = "\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}";
    301        private static final java.util.regex.Pattern __parms_pat;
    302        static {
    303            __parms_pat = java.util.regex.Pattern.compile(__parms);
    304        }
    305
    306        /***
    307         * Default FTPClient constructor.  Creates a new FTPClient instance
    308         * with the data connection mode set to
    309         * <code> ACTIVE_LOCAL_DATA_CONNECTION_MODE </code>, the file type
    310         * set to <code> FTP.ASCII_FILE_TYPE </code>, the
    311         * file format set to <code> FTP.NON_PRINT_TEXT_FORMAT </code>,
    312         * the file structure set to <code> FTP.FILE_STRUCTURE </code>, and
    313         * the transfer mode set to <code> FTP.STREAM_TRANSFER_MODE </code>.
    314         ***/
    315        public FTPClient()
    316        {
    317            __initDefaults();
    318            __dataTimeout = -1;
    319            __remoteVerificationEnabled = true;
    320            __parserFactory = new DefaultFTPFileEntryParserFactory();
    321            __configuration      = null;
    322            __listHiddenFiles = false;
    323            __useEPSVwithIPv4 = false;
    324            __random = new Random();
    325        }
    326
    327
    328        private void __initDefaults()
    329        {
    330            __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
    331            __passiveHost        = null;
    332            __passivePort        = -1;
    333            __activeExternalHost = null;
    334            __activeMinPort = 0;
    335            __activeMaxPort = 0;
    336            __fileType           = FTP.ASCII_FILE_TYPE;
    337            __fileStructure      = FTP.FILE_STRUCTURE;
    338            __fileFormat         = FTP.NON_PRINT_TEXT_FORMAT;
    339            __fileTransferMode   = FTP.STREAM_TRANSFER_MODE;
    340            __restartOffset      = 0;
    341            __systemName         = null;
    342            __entryParser        = null;
    343            __entryParserKey    = "";
    344            __bufferSize         = Util.DEFAULT_COPY_BUFFER_SIZE;
    345        }
    346
    347        private String __parsePathname(String reply)
    348        {
    349            int begin, end;
    350
    351            begin = reply.indexOf('"') + 1;
    352            end = reply.indexOf('"', begin);
    353
    354            return reply.substring(begin, end);
    355        }
    356
    357
    358        private void __parsePassiveModeReply(String reply)
    359        throws MalformedServerReplyException
    360        {
    361            java.util.regex.Matcher m = __parms_pat.matcher(reply);
    362            if (!m.find()) {
    363                throw new MalformedServerReplyException(
    364                        "Could not parse passive host information.\nServer Reply: " + reply);
    365            }
    366            reply = m.group();
    367            String parts[] = m.group().split(",");
    368
    369            __passiveHost = parts[0] + '.' + parts[1] + '.' + parts[2] + '.' + parts[3];
    370
    371            try
    372            {
    373                int oct1 = Integer.parseInt(parts[4]);
    374                int oct2 = Integer.parseInt(parts[5]);
    375                __passivePort = (oct1 << 8) | oct2;
    376            }
    377            catch (NumberFormatException e)
    378            {
    379                throw new MalformedServerReplyException(
    380                        "Could not parse passive host information.\nServer Reply: " + reply);
    381            }
    382
    383        }
    384
    385        private void __parseExtendedPassiveModeReply(String reply)
    386        throws MalformedServerReplyException
    387        {
    388            int port;
    389
    390            reply = reply.substring(reply.indexOf('(') + 1,
    391                    reply.indexOf(')')).trim();
    392
    393            char delim1, delim2, delim3, delim4;
    394            delim1 = reply.charAt(0);
    395            delim2 = reply.charAt(1);
    396            delim3 = reply.charAt(2);
    397            delim4 = reply.charAt(reply.length()-1);
    398
    399            if (!(delim1 == delim2) || !(delim2 == delim3)
    400                    || !(delim3 == delim4))
    401                throw new MalformedServerReplyException(
    402                        "Could not parse extended passive host information.\nServer Reply: " + reply);
    403            try
    404            {
    405                port = Integer.parseInt(reply.substring(3, reply.length()-1));
    406            }
    407            catch (NumberFormatException e)
    408            {
    409                throw new MalformedServerReplyException(
    410                        "Could not parse extended passive host information.\nServer Reply: " + reply);
    411            }
    412
    413
    414            // in EPSV mode, the passive host address is implicit
    415            __passiveHost = getRemoteAddress().getHostAddress();
    416            __passivePort = port;
    417        }
    418
    419        private boolean __storeFile(int command, String remote, InputStream local)
    420        throws IOException
    421        {
    422            OutputStream output;
    423            Socket socket;
    424
    425            if ((socket = _openDataConnection_(command, remote)) == null)
    426                return false;
    427
    428            output = new BufferedOutputStream(socket.getOutputStream(),
    429                    getBufferSize()
    430            );
    431            if (__fileType == ASCII_FILE_TYPE)
    432                output = new ToNetASCIIOutputStream(output);
    433            // Treat everything else as binary for now
    434            try
    435            {
    436                Util.copyStream(local, output, getBufferSize(),
    437                        CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
    438                        false);
    439            }
    440            catch (IOException e)
    441            {
    442                try
    443                {
    444                    socket.close();
    445                }
    446                catch (IOException f)
    447                {}
    448                throw e;
    449            }
    450            output.close();
    451            socket.close();
    452            return completePendingCommand();
    453        }
    454
    455        private OutputStream __storeFileStream(int command, String remote)
    456        throws IOException
    457        {
    458            OutputStream output;
    459            Socket socket;
    460
    461            if ((socket = _openDataConnection_(command, remote)) == null)
    462                return null;
    463
    464            output = socket.getOutputStream();
    465            if (__fileType == ASCII_FILE_TYPE) {
    466                // We buffer ascii transfers because the buffering has to
    467                // be interposed between ToNetASCIIOutputSream and the underlying
    468                // socket output stream.  We don't buffer binary transfers
    469                // because we don't want to impose a buffering policy on the
    470                // programmer if possible.  Programmers can decide on their
    471                // own if they want to wrap the SocketOutputStream we return
    472                // for file types other than ASCII.
    473                output = new BufferedOutputStream(output,
    474                        getBufferSize());
    475                output = new ToNetASCIIOutputStream(output);
    476
    477            }
    478            return new org.apache.commons.net.io.SocketOutputStream(socket, output);
    479        }
    480
    481
    482        /**
    483         * Establishes a data connection with the FTP server, returning
    484         * a Socket for the connection if successful.  If a restart
    485         * offset has been set with {@link #setRestartOffset(long)},
    486         * a REST command is issued to the server with the offset as
    487         * an argument before establishing the data connection.  Active
    488         * mode connections also cause a local PORT command to be issued.
    489         * <p>
    490         * @param command  The text representation of the FTP command to send.
    491         * @param arg The arguments to the FTP command.  If this parameter is
    492         *             set to null, then the command is sent with no argument.
    493         * @return A Socket corresponding to the established data connection.
    494         *         Null is returned if an FTP protocol error is reported at
    495         *         any point during the establishment and initialization of
    496         *         the connection.
    497         * @exception IOException  If an I/O error occurs while either sending a
    498         *      command to the server or receiving a reply from the server.
    499         */
    500        protected Socket _openDataConnection_(int command, String arg)
    501        throws IOException
    502        {
    503            Socket socket;
    504
    505            if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
    506                    __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
    507                return null;
    508
    509            final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address;
    510
    511            if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
    512            {
    513                // if no activePortRange was set (correctly) -> getActivePort() = 0
    514                // -> new ServerSocket(0) -> bind to any free local port
    515                ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress());
    516
    517                // Try EPRT only if remote server is over IPv6, if not use PORT,
    518                // because EPRT has no advantage over PORT on IPv4.
    519                // It could even have the disadvantage,
    520                // that EPRT will make the data connection fail, because
    521                // today's intelligent NAT Firewalls are able to
    522                // substitute IP addresses in the PORT command,
    523                // but might not be able to recognize the EPRT command.
    524                if (isInet6Address)
    525                {
    526                    if (!FTPReply.isPositiveCompletion(eprt(getHostAddress(), server.getLocalPort())))
    527                    {
    528                        server.close();
    529                        return null;
    530                    }
    531                }
    532                else
    533                {
    534                    if (!FTPReply.isPositiveCompletion(port(getHostAddress(), server.getLocalPort())))
    535                    {
    536                        server.close();
    537                        return null;
    538                    }
    539                }
    540
    541                if ((__restartOffset > 0) && !restart(__restartOffset))
    542                {
    543                    server.close();
    544                    return null;
    545                }
    546
    547                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
    548                {
    549                    server.close();
    550                    return null;
    551                }
    552
    553                // For now, let's just use the data timeout value for waiting for
    554                // the data connection.  It may be desirable to let this be a
    555                // separately configurable value.  In any case, we really want
    556                // to allow preventing the accept from blocking indefinitely.
    557                if (__dataTimeout >= 0)
    558                    server.setSoTimeout(__dataTimeout);
    559                try {
    560                    socket = server.accept();
    561                } finally {
    562                    server.close();
    563                }
    564            }
    565            else
    566            { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
    567
    568                // Try EPSV command first on IPv6 - and IPv4 if enabled.
    569                // When using IPv4 with NAT it has the advantage
    570                // to work with more rare configurations.
    571                // E.g. if FTP server has a static PASV address (external network)
    572                // and the client is coming from another internal network.
    573                // In that case the data connection after PASV command would fail,
    574                // while EPSV would make the client succeed by taking just the port.
    575                boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address;
    576                if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE)
    577                {
    578                    __parseExtendedPassiveModeReply(_replyLines.get(0));
    579                }
    580                else
    581                {
    582                    if (isInet6Address) {
    583                        return null; // Must use EPSV for IPV6
    584                    }
    585                    // If EPSV failed on IPV4, revert to PASV
    586                    if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) {
    587                        return null;
    588                    }
    589                    __parsePassiveModeReply(_replyLines.get(0));
    590                }
    591
    592                socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
    593                if ((__restartOffset > 0) && !restart(__restartOffset))
    594                {
    595                    socket.close();
    596                    return null;
    597                }
    598
    599                if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
    600                {
    601                    socket.close();
    602                    return null;
    603                }
    604            }
    605
    606            if (__remoteVerificationEnabled && !verifyRemote(socket))
    607            {
    608                InetAddress host1, host2;
    609
    610                host1 = socket.getInetAddress();
    611                host2 = getRemoteAddress();
    612
    613                socket.close();
    614
    615                throw new IOException(
    616                        "Host attempting data connection " + host1.getHostAddress() +
    617                        " is not same as server " + host2.getHostAddress());
    618            }
    619
    620            if (__dataTimeout >= 0)
    621                socket.setSoTimeout(__dataTimeout);
    622
    623            return socket;
    624        }
    625
    626
    627        @Override
    628        protected void _connectAction_() throws IOException
    629        {
    630            super._connectAction_();
    631            __initDefaults();
    632        }
    633
    634
    635        /***
    636         * Sets the timeout in milliseconds to use when reading from the
    637         * data connection.  This timeout will be set immediately after
    638         * opening the data connection.
    639         * <p>
    640         * @param  timeout The default timeout in milliseconds that is used when
    641         *        opening a data connection socket.
    642         ***/
    643        public void setDataTimeout(int timeout)
    644        {
    645            __dataTimeout = timeout;
    646        }
    647
    648        /**
    649         * set the factory used for parser creation to the supplied factory object.
    650         *
    651         * @param parserFactory
    652         *               factory object used to create FTPFileEntryParsers
    653         *
    654         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    655         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    656         */
    657        public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
    658            __parserFactory = parserFactory;
    659        }
    660
    661
    662        /***
    663         * Closes the connection to the FTP server and restores
    664         * connection parameters to the default values.
    665         * <p>
    666         * @exception IOException If an error occurs while disconnecting.
    667         ***/
    668        @Override
    669        public void disconnect() throws IOException
    670        {
    671            super.disconnect();
    672            __initDefaults();
    673        }
    674
    675
    676        /***
    677         * Enable or disable verification that the remote host taking part
    678         * of a data connection is the same as the host to which the control
    679         * connection is attached.  The default is for verification to be
    680         * enabled.  You may set this value at any time, whether the
    681         * FTPClient is currently connected or not.
    682         * <p>
    683         * @param enable True to enable verification, false to disable verification.
    684         ***/
    685        public void setRemoteVerificationEnabled(boolean enable)
    686        {
    687            __remoteVerificationEnabled = enable;
    688        }
    689
    690        /***
    691         * Return whether or not verification of the remote host participating
    692         * in data connections is enabled.  The default behavior is for
    693         * verification to be enabled.
    694         * <p>
    695         * @return True if verification is enabled, false if not.
    696         ***/
    697        public boolean isRemoteVerificationEnabled()
    698        {
    699            return __remoteVerificationEnabled;
    700        }
    701
    702        /***
    703         * Login to the FTP server using the provided username and password.
    704         * <p>
    705         * @param username The username to login under.
    706         * @param password The password to use.
    707         * @return True if successfully completed, false if not.
    708         * @exception FTPConnectionClosedException
    709         *      If the FTP server prematurely closes the connection as a result
    710         *      of the client being idle or some other reason causing the server
    711         *      to send FTP reply code 421.  This exception may be caught either
    712         *      as an IOException or independently as itself.
    713         * @exception IOException  If an I/O error occurs while either sending a
    714         *      command to the server or receiving a reply from the server.
    715         ***/
    716        public boolean login(String username, String password) throws IOException
    717        {
    718
    719            user(username);
    720
    721            if (FTPReply.isPositiveCompletion(_replyCode))
    722                return true;
    723
    724            // If we get here, we either have an error code, or an intermmediate
    725            // reply requesting password.
    726            if (!FTPReply.isPositiveIntermediate(_replyCode))
    727                return false;
    728
    729            return FTPReply.isPositiveCompletion(pass(password));
    730        }
    731
    732
    733        /***
    734         * Login to the FTP server using the provided username, password,
    735         * and account.  If no account is required by the server, only
    736         * the username and password, the account information is not used.
    737         * <p>
    738         * @param username The username to login under.
    739         * @param password The password to use.
    740         * @param account  The account to use.
    741         * @return True if successfully completed, false if not.
    742         * @exception FTPConnectionClosedException
    743         *      If the FTP server prematurely closes the connection as a result
    744         *      of the client being idle or some other reason causing the server
    745         *      to send FTP reply code 421.  This exception may be caught either
    746         *      as an IOException or independently as itself.
    747         * @exception IOException  If an I/O error occurs while either sending a
    748         *      command to the server or receiving a reply from the server.
    749         ***/
    750        public boolean login(String username, String password, String account)
    751        throws IOException
    752        {
    753            user(username);
    754
    755            if (FTPReply.isPositiveCompletion(_replyCode))
    756                return true;
    757
    758            // If we get here, we either have an error code, or an intermmediate
    759            // reply requesting password.
    760            if (!FTPReply.isPositiveIntermediate(_replyCode))
    761                return false;
    762
    763            pass(password);
    764
    765            if (FTPReply.isPositiveCompletion(_replyCode))
    766                return true;
    767
    768            if (!FTPReply.isPositiveIntermediate(_replyCode))
    769                return false;
    770
    771            return FTPReply.isPositiveCompletion(acct(account));
    772        }
    773
    774        /***
    775         * Logout of the FTP server by sending the QUIT command.
    776         * <p>
    777         * @return True if successfully completed, false if not.
    778         * @exception FTPConnectionClosedException
    779         *      If the FTP server prematurely closes the connection as a result
    780         *      of the client being idle or some other reason causing the server
    781         *      to send FTP reply code 421.  This exception may be caught either
    782         *      as an IOException or independently as itself.
    783         * @exception IOException  If an I/O error occurs while either sending a
    784         *      command to the server or receiving a reply from the server.
    785         ***/
    786        public boolean logout() throws IOException
    787        {
    788            return FTPReply.isPositiveCompletion(quit());
    789        }
    790
    791
    792        /***
    793         * Change the current working directory of the FTP session.
    794         * <p>
    795         * @param pathname  The new current working directory.
    796         * @return True if successfully completed, false if not.
    797         * @exception FTPConnectionClosedException
    798         *      If the FTP server prematurely closes the connection as a result
    799         *      of the client being idle or some other reason causing the server
    800         *      to send FTP reply code 421.  This exception may be caught either
    801         *      as an IOException or independently as itself.
    802         * @exception IOException  If an I/O error occurs while either sending a
    803         *      command to the server or receiving a reply from the server.
    804         ***/
    805        public boolean changeWorkingDirectory(String pathname) throws IOException
    806        {
    807            return FTPReply.isPositiveCompletion(cwd(pathname));
    808        }
    809
    810
    811        /***
    812         * Change to the parent directory of the current working directory.
    813         * <p>
    814         * @return True if successfully completed, false if not.
    815         * @exception FTPConnectionClosedException
    816         *      If the FTP server prematurely closes the connection as a result
    817         *      of the client being idle or some other reason causing the server
    818         *      to send FTP reply code 421.  This exception may be caught either
    819         *      as an IOException or independently as itself.
    820         * @exception IOException  If an I/O error occurs while either sending a
    821         *      command to the server or receiving a reply from the server.
    822         ***/
    823        public boolean changeToParentDirectory() throws IOException
    824        {
    825            return FTPReply.isPositiveCompletion(cdup());
    826        }
    827
    828
    829        /***
    830         * Issue the FTP SMNT command.
    831         * <p>
    832         * @param pathname The pathname to mount.
    833         * @return True if successfully completed, false if not.
    834         * @exception FTPConnectionClosedException
    835         *      If the FTP server prematurely closes the connection as a result
    836         *      of the client being idle or some other reason causing the server
    837         *      to send FTP reply code 421.  This exception may be caught either
    838         *      as an IOException or independently as itself.
    839         * @exception IOException  If an I/O error occurs while either sending a
    840         *      command to the server or receiving a reply from the server.
    841         ***/
    842        public boolean structureMount(String pathname) throws IOException
    843        {
    844            return FTPReply.isPositiveCompletion(smnt(pathname));
    845        }
    846
    847        /***
    848         * Reinitialize the FTP session.  Not all FTP servers support this
    849         * command, which issues the FTP REIN command.
    850         * <p>
    851         * @return True if successfully completed, false if not.
    852         * @exception FTPConnectionClosedException
    853         *      If the FTP server prematurely closes the connection as a result
    854         *      of the client being idle or some other reason causing the server
    855         *      to send FTP reply code 421.  This exception may be caught either
    856         *      as an IOException or independently as itself.
    857         * @exception IOException  If an I/O error occurs while either sending a
    858         *      command to the server or receiving a reply from the server.
    859         ***/
    860        boolean reinitialize() throws IOException
    861        {
    862            rein();
    863
    864            if (FTPReply.isPositiveCompletion(_replyCode) ||
    865                    (FTPReply.isPositivePreliminary(_replyCode) &&
    866                            FTPReply.isPositiveCompletion(getReply())))
    867            {
    868
    869                __initDefaults();
    870
    871                return true;
    872            }
    873
    874            return false;
    875        }
    876
    877
    878        /***
    879         * Set the current data connection mode to
    880         * <code>ACTIVE_LOCAL_DATA_CONNECTION_MODE</code>.  No communication
    881         * with the FTP server is conducted, but this causes all future data
    882         * transfers to require the FTP server to connect to the client's
    883         * data port.  Additionally, to accommodate differences between socket
    884         * implementations on different platforms, this method causes the
    885         * client to issue a PORT command before every data transfer.
    886         ***/
    887        public void enterLocalActiveMode()
    888        {
    889            __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
    890            __passiveHost = null;
    891            __passivePort = -1;
    892        }
    893
    894
    895        /***
    896         * Set the current data connection mode to
    897         * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code>.  Use this
    898         * method only for data transfers between the client and server.
    899         * This method causes a PASV (or EPSV) command to be issued to the server
    900         * before the opening of every data connection, telling the server to
    901         * open a data port to which the client will connect to conduct
    902         * data transfers.  The FTPClient will stay in
    903         * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code> until the
    904         * mode is changed by calling some other method such as
    905         * {@link #enterLocalActiveMode  enterLocalActiveMode() }
    906         * <p>
    907         * <b>N.B.</b> currently calling any connect method will reset the mode to
    908         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    909         ***/
    910        public void enterLocalPassiveMode()
    911        {
    912            __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
    913            // These will be set when just before a data connection is opened
    914            // in _openDataConnection_()
    915            __passiveHost = null;
    916            __passivePort = -1;
    917        }
    918
    919
    920        /***
    921         * Set the current data connection mode to
    922         * <code> ACTIVE_REMOTE_DATA_CONNECTION </code>.  Use this method only
    923         * for server to server data transfers.  This method issues a PORT
    924         * command to the server, indicating the other server and port to which
    925         * it should connect for data transfers.  You must call this method
    926         * before EVERY server to server transfer attempt.  The FTPClient will
    927         * NOT automatically continue to issue PORT commands.  You also
    928         * must remember to call
    929         * {@link #enterLocalActiveMode  enterLocalActiveMode() } if you
    930         * wish to return to the normal data connection mode.
    931         * <p>
    932         * @param host The passive mode server accepting connections for data
    933         *             transfers.
    934         * @param port The passive mode server's data port.
    935         * @return True if successfully completed, false if not.
    936         * @exception FTPConnectionClosedException
    937         *      If the FTP server prematurely closes the connection as a result
    938         *      of the client being idle or some other reason causing the server
    939         *      to send FTP reply code 421.  This exception may be caught either
    940         *      as an IOException or independently as itself.
    941         * @exception IOException  If an I/O error occurs while either sending a
    942         *      command to the server or receiving a reply from the server.
    943         ***/
    944        public boolean enterRemoteActiveMode(InetAddress host, int port)
    945        throws IOException
    946        {
    947            if (FTPReply.isPositiveCompletion(port(host, port)))
    948            {
    949                __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
    950                __passiveHost = null;
    951                __passivePort = -1;
    952                return true;
    953            }
    954            return false;
    955        }
    956
    957        /***
    958         * Set the current data connection mode to
    959         * <code> PASSIVE_REMOTE_DATA_CONNECTION_MODE </code>.  Use this
    960         * method only for server to server data transfers.
    961         * This method issues a PASV command to the server, telling it to
    962         * open a data port to which the active server will connect to conduct
    963         * data transfers.  You must call this method
    964         * before EVERY server to server transfer attempt.  The FTPClient will
    965         * NOT automatically continue to issue PASV commands.  You also
    966         * must remember to call
    967         * {@link #enterLocalActiveMode  enterLocalActiveMode() } if you
    968         * wish to return to the normal data connection mode.
    969         * <p>
    970         * @return True if successfully completed, false if not.
    971         * @exception FTPConnectionClosedException
    972         *      If the FTP server prematurely closes the connection as a result
    973         *      of the client being idle or some other reason causing the server
    974         *      to send FTP reply code 421.  This exception may be caught either
    975         *      as an IOException or independently as itself.
    976         * @exception IOException  If an I/O error occurs while either sending a
    977         *      command to the server or receiving a reply from the server.
    978         ***/
    979        public boolean enterRemotePassiveMode() throws IOException
    980        {
    981            if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
    982                return false;
    983
    984            __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
    985            __parsePassiveModeReply(_replyLines.get(0));
    986
    987            return true;
    988        }
    989
    990        /***
    991         * Returns the hostname or IP address (in the form of a string) returned
    992         * by the server when entering passive mode.  If not in passive mode,
    993         * returns null.  This method only returns a valid value AFTER a
    994         * data connection has been opened after a call to
    995         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    996         * This is because FTPClient sends a PASV command to the server only
    997         * just before opening a data connection, and not when you call
    998         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    999         * <p>
    1000         * @return The passive host name if in passive mode, otherwise null.
    1001         ***/
    1002        public String getPassiveHost()
    1003        {
    1004            return __passiveHost;
    1005        }
    1006
    1007        /***
    1008         * If in passive mode, returns the data port of the passive host.
    1009         * This method only returns a valid value AFTER a
    1010         * data connection has been opened after a call to
    1011         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1012         * This is because FTPClient sends a PASV command to the server only
    1013         * just before opening a data connection, and not when you call
    1014         * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
    1015         * <p>
    1016         * @return The data port of the passive server.  If not in passive
    1017         *         mode, undefined.
    1018         ***/
    1019        public int getPassivePort()
    1020        {
    1021            return __passivePort;
    1022        }
    1023
    1024
    1025        /***
    1026         * Returns the current data connection mode (one of the
    1027         * <code> _DATA_CONNECTION_MODE </code> constants.
    1028         * <p>
    1029         * @return The current data connection mode (one of the
    1030         * <code> _DATA_CONNECTION_MODE </code> constants.
    1031         ***/
    1032        public int getDataConnectionMode()
    1033        {
    1034            return __dataConnectionMode;
    1035        }
    1036
    1037        /**
    1038         * Get the client port for active mode.
    1039         * <p>
    1040         * @return The client port for active mode.
    1041         */
    1042        private int getActivePort()
    1043        {
    1044            if (__activeMinPort > 0 && __activeMaxPort >= __activeMinPort)
    1045            {
    1046                if (__activeMaxPort == __activeMinPort)
    1047                    return __activeMaxPort;
    1048                // Get a random port between the min and max port range
    1049                return __random.nextInt(__activeMaxPort - __activeMinPort + 1) + __activeMinPort;
    1050            }
    1051            else
    1052            {
    1053                // default port
    1054                return 0;
    1055            }
    1056        }
    1057
    1058        /**
    1059         * Get the host address for active mode.
    1060         * <p>
    1061         * @return The host address for active mode.
    1062         */
    1063        private InetAddress getHostAddress()
    1064        {
    1065            if (__activeExternalHost != null)
    1066            {
    1067                return __activeExternalHost;
    1068            }
    1069            else
    1070            {
    1071                // default local address
    1072                return getLocalAddress();
    1073            }
    1074        }
    1075
    1076        /***
    1077         * Set the client side port range in active mode.
    1078         * <p>
    1079         * @param minPort The lowest available port (inclusive).
    1080         * @param maxPort The highest available port (inclusive).
    1081         * @since 2.2
    1082         ***/
    1083        public void setActivePortRange(int minPort, int maxPort)
    1084        {
    1085            this.__activeMinPort = minPort;
    1086            this.__activeMaxPort = maxPort;
    1087        }
    1088
    1089        /***
    1090         * Set the external IP address in active mode.
    1091         * Useful when there are multiple network cards.
    1092         * <p>
    1093         * @param ipAddress The external IP address of this machine.
    1094         * @throws UnknownHostException
    1095         * @since 2.2
    1096         ***/
    1097        public void setActiveExternalIPAddress(String ipAddress) throws UnknownHostException
    1098        {
    1099            this.__activeExternalHost = InetAddress.getByName(ipAddress);
    1100        }
    1101
    1102
    1103        /***
    1104         * Sets the file type to be transferred.  This should be one of
    1105         * <code> FTP.ASCII_FILE_TYPE </code>, <code> FTP.BINARY_FILE_TYPE</code>,
    1106         * etc.  The file type only needs to be set when you want to change the
    1107         * type.  After changing it, the new type stays in effect until you change
    1108         * it again.  The default file type is <code> FTP.ASCII_FILE_TYPE </code>
    1109         * if this method is never called.
    1110         * <p>
    1111         * <b>N.B.</b> currently calling any connect method will reset the mode to
    1112         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    1113         * @param fileType The <code> _FILE_TYPE </code> constant indcating the
    1114         *                 type of file.
    1115         * @return True if successfully completed, false if not.
    1116         * @exception FTPConnectionClosedException
    1117         *      If the FTP server prematurely closes the connection as a result
    1118         *      of the client being idle or some other reason causing the server
    1119         *      to send FTP reply code 421.  This exception may be caught either
    1120         *      as an IOException or independently as itself.
    1121         * @exception IOException  If an I/O error occurs while either sending a
    1122         *      command to the server or receiving a reply from the server.
    1123         ***/
    1124        public boolean setFileType(int fileType) throws IOException
    1125        {
    1126            if (FTPReply.isPositiveCompletion(type(fileType)))
    1127            {
    1128                __fileType = fileType;
    1129                __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
    1130                return true;
    1131            }
    1132            return false;
    1133        }
    1134
    1135
    1136        /***
    1137         * Sets the file type to be transferred and the format.  The type should be
    1138         * one of  <code> FTP.ASCII_FILE_TYPE </code>,
    1139         * <code> FTP.BINARY_FILE_TYPE </code>, etc.  The file type only needs to
    1140         * be set when you want to change the type.  After changing it, the new
    1141         * type stays in effect until you change it again.  The default file type
    1142         * is <code> FTP.ASCII_FILE_TYPE </code> if this method is never called.
    1143         * The format should be one of the FTP class <code> TEXT_FORMAT </code>
    1144         * constants, or if the type is <code> FTP.LOCAL_FILE_TYPE </code>, the
    1145         * format should be the byte size for that type.  The default format
    1146         * is <code> FTP.NON_PRINT_TEXT_FORMAT </code> if this method is never
    1147         * called.
    1148         * <p>
    1149         * <b>N.B.</b> currently calling any connect method will reset the mode to
    1150         * ACTIVE_LOCAL_DATA_CONNECTION_MODE.
    1151         * <p>
    1152         * @param fileType The <code> _FILE_TYPE </code> constant indcating the
    1153         *                 type of file.
    1154         * @param formatOrByteSize  The format of the file (one of the
    1155         *              <code>_FORMAT</code> constants.  In the case of
    1156         *              <code>LOCAL_FILE_TYPE</code>, the byte size.
    1157         * <p>
    1158         * @return True if successfully completed, false if not.
    1159         * @exception FTPConnectionClosedException
    1160         *      If the FTP server prematurely closes the connection as a result
    1161         *      of the client being idle or some other reason causing the server
    1162         *      to send FTP reply code 421.  This exception may be caught either
    1163         *      as an IOException or independently as itself.
    1164         * @exception IOException  If an I/O error occurs while either sending a
    1165         *      command to the server or receiving a reply from the server.
    1166         ***/
    1167        public boolean setFileType(int fileType, int formatOrByteSize)
    1168        throws IOException
    1169        {
    1170            if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize)))
    1171            {
    1172                __fileType = fileType;
    1173                __fileFormat = formatOrByteSize;
    1174                return true;
    1175            }
    1176            return false;
    1177        }
    1178
    1179
    1180        /***
    1181         * Sets the file structure.  The default structure is
    1182         * <code> FTP.FILE_STRUCTURE </code> if this method is never called.
    1183         * <p>
    1184         * @param structure  The structure of the file (one of the FTP class
    1185         *         <code>_STRUCTURE</code> constants).
    1186         * @return True if successfully completed, false if not.
    1187         * @exception FTPConnectionClosedException
    1188         *      If the FTP server prematurely closes the connection as a result
    1189         *      of the client being idle or some other reason causing the server
    1190         *      to send FTP reply code 421.  This exception may be caught either
    1191         *      as an IOException or independently as itself.
    1192         * @exception IOException  If an I/O error occurs while either sending a
    1193         *      command to the server or receiving a reply from the server.
    1194         ***/
    1195        public boolean setFileStructure(int structure) throws IOException
    1196        {
    1197            if (FTPReply.isPositiveCompletion(stru(structure)))
    1198            {
    1199                __fileStructure = structure;
    1200                return true;
    1201            }
    1202            return false;
    1203        }
    1204
    1205
    1206        /***
    1207         * Sets the transfer mode.  The default transfer mode
    1208         * <code> FTP.STREAM_TRANSFER_MODE </code> if this method is never called.
    1209         * <p>
    1210         * @param mode  The new transfer mode to use (one of the FTP class
    1211         *         <code>_TRANSFER_MODE</code> constants).
    1212         * @return True if successfully completed, false if not.
    1213         * @exception FTPConnectionClosedException
    1214         *      If the FTP server prematurely closes the connection as a result
    1215         *      of the client being idle or some other reason causing the server
    1216         *      to send FTP reply code 421.  This exception may be caught either
    1217         *      as an IOException or independently as itself.
    1218         * @exception IOException  If an I/O error occurs while either sending a
    1219         *      command to the server or receiving a reply from the server.
    1220         ***/
    1221        public boolean setFileTransferMode(int mode) throws IOException
    1222        {
    1223            if (FTPReply.isPositiveCompletion(mode(mode)))
    1224            {
    1225                __fileTransferMode = mode;
    1226                return true;
    1227            }
    1228            return false;
    1229        }
    1230
    1231
    1232        /***
    1233         * Initiate a server to server file transfer.  This method tells the
    1234         * server to which the client is connected to retrieve a given file from
    1235         * the other server.
    1236         * <p>
    1237         * @param filename  The name of the file to retrieve.
    1238         * @return True if successfully completed, false if not.
    1239         * @exception FTPConnectionClosedException
    1240         *      If the FTP server prematurely closes the connection as a result
    1241         *      of the client being idle or some other reason causing the server
    1242         *      to send FTP reply code 421.  This exception may be caught either
    1243         *      as an IOException or independently as itself.
    1244         * @exception IOException  If an I/O error occurs while either sending a
    1245         *      command to the server or receiving a reply from the server.
    1246         ***/
    1247        public boolean remoteRetrieve(String filename) throws IOException
    1248        {
    1249            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1250                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
    1251                return FTPReply.isPositivePreliminary(retr(filename));
    1252            return false;
    1253        }
    1254
    1255
    1256        /***
    1257         * Initiate a server to server file transfer.  This method tells the
    1258         * server to which the client is connected to store a file on
    1259         * the other server using the given filename.  The other server must
    1260         * have had a <code> remoteRetrieve </code> issued to it by another
    1261         * FTPClient.
    1262         * <p>
    1263         * @param filename  The name to call the file that is to be stored.
    1264         * @return True if successfully completed, false if not.
    1265         * @exception FTPConnectionClosedException
    1266         *      If the FTP server prematurely closes the connection as a result
    1267         *      of the client being idle or some other reason causing the server
    1268         *      to send FTP reply code 421.  This exception may be caught either
    1269         *      as an IOException or independently as itself.
    1270         * @exception IOException  If an I/O error occurs while either sending a
    1271         *      command to the server or receiving a reply from the server.
    1272         ***/
    1273        public boolean remoteStore(String filename) throws IOException
    1274        {
    1275            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1276                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
    1277                return FTPReply.isPositivePreliminary(stor(filename));
    1278            return false;
    1279        }
    1280
    1281
    1282        /***
    1283         * Initiate a server to server file transfer.  This method tells the
    1284         * server to which the client is connected to store a file on
    1285         * the other server using a unique filename based on the given filename.
    1286         * The other server must have had a <code> remoteRetrieve </code> issued
    1287         * to it by another FTPClient.
    1288         * <p>
    1289         * @param filename  The name on which to base the filename of the file
    1290         *                  that is to be stored.
    1291         * @return True if successfully completed, false if not.
    1292         * @exception FTPConnectionClosedException
    1293         *      If the FTP server prematurely closes the connection as a result
    1294         *      of the client being idle or some other reason causing the server
    1295         *      to send FTP reply code 421.  This exception may be caught either
    1296         *      as an IOException or independently as itself.
    1297         * @exception IOException  If an I/O error occurs while either sending a
    1298         *      command to the server or receiving a reply from the server.
    1299         ***/
    1300        public boolean remoteStoreUnique(String filename) throws IOException
    1301        {
    1302            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1303                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
    1304                return FTPReply.isPositivePreliminary(stou(filename));
    1305            return false;
    1306        }
    1307
    1308
    1309        /***
    1310         * Initiate a server to server file transfer.  This method tells the
    1311         * server to which the client is connected to store a file on
    1312         * the other server using a unique filename.
    1313         * The other server must have had a <code> remoteRetrieve </code> issued
    1314         * to it by another FTPClient.  Many FTP servers require that a base
    1315         * filename be given from which the unique filename can be derived.  For
    1316         * those servers use the other version of <code> remoteStoreUnique</code>
    1317         * <p>
    1318         * @return True if successfully completed, false if not.
    1319         * @exception FTPConnectionClosedException
    1320         *      If the FTP server prematurely closes the connection as a result
    1321         *      of the client being idle or some other reason causing the server
    1322         *      to send FTP reply code 421.  This exception may be caught either
    1323         *      as an IOException or independently as itself.
    1324         * @exception IOException  If an I/O error occurs while either sending a
    1325         *      command to the server or receiving a reply from the server.
    1326         ***/
    1327        public boolean remoteStoreUnique() throws IOException
    1328        {
    1329            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1330                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
    1331                return FTPReply.isPositivePreliminary(stou());
    1332            return false;
    1333        }
    1334
    1335        // For server to server transfers
    1336        /***
    1337         * Initiate a server to server file transfer.  This method tells the
    1338         * server to which the client is connected to append to a given file on
    1339         * the other server.  The other server must have had a
    1340         * <code> remoteRetrieve </code> issued to it by another FTPClient.
    1341         * <p>
    1342         * @param filename  The name of the file to be appended to, or if the
    1343         *        file does not exist, the name to call the file being stored.
    1344         * <p>
    1345         * @return True if successfully completed, false if not.
    1346         * @exception FTPConnectionClosedException
    1347         *      If the FTP server prematurely closes the connection as a result
    1348         *      of the client being idle or some other reason causing the server
    1349         *      to send FTP reply code 421.  This exception may be caught either
    1350         *      as an IOException or independently as itself.
    1351         * @exception IOException  If an I/O error occurs while either sending a
    1352         *      command to the server or receiving a reply from the server.
    1353         ***/
    1354        public boolean remoteAppend(String filename) throws IOException
    1355        {
    1356            if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
    1357                    __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
    1358                return FTPReply.isPositivePreliminary(appe(filename));
    1359            return false;
    1360        }
    1361
    1362        /***
    1363         * There are a few FTPClient methods that do not complete the
    1364         * entire sequence of FTP commands to complete a transaction.  These
    1365         * commands require some action by the programmer after the reception
    1366         * of a positive intermediate command.  After the programmer's code
    1367         * completes its actions, it must call this method to receive
    1368         * the completion reply from the server and verify the success of the
    1369         * entire transaction.
    1370         * <p>
    1371         * For example,
    1372         * <pre>
    1373         * InputStream input;
    1374         * OutputStream output;
    1375         * input  = new FileInputStream("foobaz.txt");
    1376         * output = ftp.storeFileStream("foobar.txt")
    1377         * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
    1378         *     input.close();
    1379         *     output.close();
    1380         *     ftp.logout();
    1381         *     ftp.disconnect();
    1382         *     System.err.println("File transfer failed.");
    1383         *     System.exit(1);
    1384         * }
    1385         * Util.copyStream(input, output);
    1386         * input.close();
    1387         * output.close();
    1388         * // Must call completePendingCommand() to finish command.
    1389         * if(!ftp.completePendingCommand()) {
    1390         *     ftp.logout();
    1391         *     ftp.disconnect();
    1392         *     System.err.println("File transfer failed.");
    1393         *     System.exit(1);
    1394         * }
    1395         * </pre>
    1396         * <p>
    1397         * @return True if successfully completed, false if not.
    1398         * @exception FTPConnectionClosedException
    1399         *      If the FTP server prematurely closes the connection as a result
    1400         *      of the client being idle or some other reason causing the server
    1401         *      to send FTP reply code 421.  This exception may be caught either
    1402         *      as an IOException or independently as itself.
    1403         * @exception IOException  If an I/O error occurs while either sending a
    1404         *      command to the server or receiving a reply from the server.
    1405         ***/
    1406        public boolean completePendingCommand() throws IOException
    1407        {
    1408            return FTPReply.isPositiveCompletion(getReply());
    1409        }
    1410
    1411
    1412        /***
    1413         * Retrieves a named file from the server and writes it to the given
    1414         * OutputStream.  This method does NOT close the given OutputStream.
    1415         * If the current file type is ASCII, line separators in the file are
    1416         * converted to the local representation.
    1417         * <p>
    1418         * Note: if you have used {@link #setRestartOffset(long)},
    1419         * the file data will start from the selected offset.
    1420         * @param remote  The name of the remote file.
    1421         * @param local   The local OutputStream to which to write the file.
    1422         * @return True if successfully completed, false if not.
    1423         * @exception FTPConnectionClosedException
    1424         *      If the FTP server prematurely closes the connection as a result
    1425         *      of the client being idle or some other reason causing the server
    1426         *      to send FTP reply code 421.  This exception may be caught either
    1427         *      as an IOException or independently as itself.
    1428         * @exception CopyStreamException  If an I/O error occurs while actually
    1429         *      transferring the file.  The CopyStreamException allows you to
    1430         *      determine the number of bytes transferred and the IOException
    1431         *      causing the error.  This exception may be caught either
    1432         *      as an IOException or independently as itself.
    1433         * @exception IOException  If an I/O error occurs while either sending a
    1434         *      command to the server or receiving a reply from the server.
    1435         ***/
    1436        public boolean retrieveFile(String remote, OutputStream local)
    1437        throws IOException
    1438        {
    1439            InputStream input;
    1440            Socket socket;
    1441
    1442            if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
    1443                return false;
    1444
    1445            input = new BufferedInputStream(socket.getInputStream(),
    1446                    getBufferSize());
    1447            if (__fileType == ASCII_FILE_TYPE)
    1448                input = new FromNetASCIIInputStream(input);
    1449            // Treat everything else as binary for now
    1450            try
    1451            {
    1452                Util.copyStream(input, local, getBufferSize(),
    1453                        CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
    1454                        false);
    1455            }
    1456            catch (IOException e)
    1457            {
    1458                try
    1459                {
    1460                    socket.close();
    1461                }
    1462                catch (IOException f)
    1463                {}
    1464                throw e;
    1465            }
    1466            socket.close();
    1467            return completePendingCommand();
    1468        }
    1469
    1470        /***
    1471         * Returns an InputStream from which a named file from the server
    1472         * can be read.  If the current file type is ASCII, the returned
    1473         * InputStream will convert line separators in the file to
    1474         * the local representation.  You must close the InputStream when you
    1475         * finish reading from it.  The InputStream itself will take care of
    1476         * closing the parent data connection socket upon being closed.  To
    1477         * finalize the file transfer you must call
    1478         * {@link #completePendingCommand  completePendingCommand } and
    1479         * check its return value to verify success.
    1480         * <p>
    1481         * Note: if you have used {@link #setRestartOffset(long)},
    1482         * the file data will start from the selected offset.
    1483         *
    1484         * @param remote  The name of the remote file.
    1485         * @return An InputStream from which the remote file can be read.  If
    1486         *      the data connection cannot be opened (e.g., the file does not
    1487         *      exist), null is returned (in which case you may check the reply
    1488         *      code to determine the exact reason for failure).
    1489         * @exception FTPConnectionClosedException
    1490         *      If the FTP server prematurely closes the connection as a result
    1491         *      of the client being idle or some other reason causing the server
    1492         *      to send FTP reply code 421.  This exception may be caught either
    1493         *      as an IOException or independently as itself.
    1494         * @exception IOException  If an I/O error occurs while either sending a
    1495         *      command to the server or receiving a reply from the server.
    1496         ***/
    1497        public InputStream retrieveFileStream(String remote) throws IOException
    1498        {
    1499            InputStream input;
    1500            Socket socket;
    1501
    1502            if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
    1503                return null;
    1504
    1505            input = socket.getInputStream();
    1506            if (__fileType == ASCII_FILE_TYPE) {
    1507                // We buffer ascii transfers because the buffering has to
    1508                // be interposed between FromNetASCIIOutputSream and the underlying
    1509                // socket input stream.  We don't buffer binary transfers
    1510                // because we don't want to impose a buffering policy on the
    1511                // programmer if possible.  Programmers can decide on their
    1512                // own if they want to wrap the SocketInputStream we return
    1513                // for file types other than ASCII.
    1514                input = new BufferedInputStream(input,
    1515                        getBufferSize());
    1516                input = new FromNetASCIIInputStream(input);
    1517            }
    1518            return new org.apache.commons.net.io.SocketInputStream(socket, input);
    1519        }
    1520
    1521
    1522        /***
    1523         * Stores a file on the server using the given name and taking input
    1524         * from the given InputStream.  This method does NOT close the given
    1525         * InputStream.  If the current file type is ASCII, line separators in
    1526         * the file are transparently converted to the NETASCII format (i.e.,
    1527         * you should not attempt to create a special InputStream to do this).
    1528         * <p>
    1529         * @param remote  The name to give the remote file.
    1530         * @param local   The local InputStream from which to read the file.
    1531         * @return True if successfully completed, false if not.
    1532         * @exception FTPConnectionClosedException
    1533         *      If the FTP server prematurely closes the connection as a result
    1534         *      of the client being idle or some other reason causing the server
    1535         *      to send FTP reply code 421.  This exception may be caught either
    1536         *      as an IOException or independently as itself.
    1537         * @exception CopyStreamException  If an I/O error occurs while actually
    1538         *      transferring the file.  The CopyStreamException allows you to
    1539         *      determine the number of bytes transferred and the IOException
    1540         *      causing the error.  This exception may be caught either
    1541         *      as an IOException or independently as itself.
    1542         * @exception IOException  If an I/O error occurs while either sending a
    1543         *      command to the server or receiving a reply from the server.
    1544         ***/
    1545        public boolean storeFile(String remote, InputStream local)
    1546        throws IOException
    1547        {
    1548            return __storeFile(FTPCommand.STOR, remote, local);
    1549        }
    1550
    1551
    1552        /***
    1553         * Returns an OutputStream through which data can be written to store
    1554         * a file on the server using the given name.  If the current file type
    1555         * is ASCII, the returned OutputStream will convert line separators in
    1556         * the file to the NETASCII format  (i.e., you should not attempt to
    1557         * create a special OutputStream to do this).  You must close the
    1558         * OutputStream when you finish writing to it.  The OutputStream itself
    1559         * will take care of closing the parent data connection socket upon being
    1560         * closed.  To finalize the file transfer you must call
    1561         * {@link #completePendingCommand  completePendingCommand } and
    1562         * check its return value to verify success.
    1563         * <p>
    1564         * @param remote  The name to give the remote file.
    1565         * @return An OutputStream through which the remote file can be written.  If
    1566         *      the data connection cannot be opened (e.g., the file does not
    1567         *      exist), null is returned (in which case you may check the reply
    1568         *      code to determine the exact reason for failure).
    1569         * @exception FTPConnectionClosedException
    1570         *      If the FTP server prematurely closes the connection as a result
    1571         *      of the client being idle or some other reason causing the server
    1572         *      to send FTP reply code 421.  This exception may be caught either
    1573         *      as an IOException or independently as itself.
    1574         * @exception IOException  If an I/O error occurs while either sending a
    1575         *      command to the server or receiving a reply from the server.
    1576         ***/
    1577        public OutputStream storeFileStream(String remote) throws IOException
    1578        {
    1579            return __storeFileStream(FTPCommand.STOR, remote);
    1580        }
    1581
    1582        /***
    1583         * Appends to a file on the server with the given name, taking input
    1584         * from the given InputStream.  This method does NOT close the given
    1585         * InputStream.  If the current file type is ASCII, line separators in
    1586         * the file are transparently converted to the NETASCII format (i.e.,
    1587         * you should not attempt to create a special InputStream to do this).
    1588         * <p>
    1589         * @param remote  The name of the remote file.
    1590         * @param local   The local InputStream from which to read the data to
    1591         *                be appended to the remote file.
    1592         * @return True if successfully completed, false if not.
    1593         * @exception FTPConnectionClosedException
    1594         *      If the FTP server prematurely closes the connection as a result
    1595         *      of the client being idle or some other reason causing the server
    1596         *      to send FTP reply code 421.  This exception may be caught either
    1597         *      as an IOException or independently as itself.
    1598         * @exception CopyStreamException  If an I/O error occurs while actually
    1599         *      transferring the file.  The CopyStreamException allows you to
    1600         *      determine the number of bytes transferred and the IOException
    1601         *      causing the error.  This exception may be caught either
    1602         *      as an IOException or independently as itself.
    1603         * @exception IOException  If an I/O error occurs while either sending a
    1604         *      command to the server or receiving a reply from the server.
    1605         ***/
    1606        public boolean appendFile(String remote, InputStream local)
    1607        throws IOException
    1608        {
    1609            return __storeFile(FTPCommand.APPE, remote, local);
    1610        }
    1611
    1612        /***
    1613         * Returns an OutputStream through which data can be written to append
    1614         * to a file on the server with the given name.  If the current file type
    1615         * is ASCII, the returned OutputStream will convert line separators in
    1616         * the file to the NETASCII format  (i.e., you should not attempt to
    1617         * create a special OutputStream to do this).  You must close the
    1618         * OutputStream when you finish writing to it.  The OutputStream itself
    1619         * will take care of closing the parent data connection socket upon being
    1620         * closed.  To finalize the file transfer you must call
    1621         * {@link #completePendingCommand  completePendingCommand } and
    1622         * check its return value to verify success.
    1623         * <p>
    1624         * @param remote  The name of the remote file.
    1625         * @return An OutputStream through which the remote file can be appended.
    1626         *      If the data connection cannot be opened (e.g., the file does not
    1627         *      exist), null is returned (in which case you may check the reply
    1628         *      code to determine the exact reason for failure).
    1629         * @exception FTPConnectionClosedException
    1630         *      If the FTP server prematurely closes the connection as a result
    1631         *      of the client being idle or some other reason causing the server
    1632         *      to send FTP reply code 421.  This exception may be caught either
    1633         *      as an IOException or independently as itself.
    1634         * @exception IOException  If an I/O error occurs while either sending a
    1635         *      command to the server or receiving a reply from the server.
    1636         ***/
    1637        public OutputStream appendFileStream(String remote) throws IOException
    1638        {
    1639            return __storeFileStream(FTPCommand.APPE, remote);
    1640        }
    1641
    1642        /***
    1643         * Stores a file on the server using a unique name derived from the
    1644         * given name and taking input
    1645         * from the given InputStream.  This method does NOT close the given
    1646         * InputStream.  If the current file type is ASCII, line separators in
    1647         * the file are transparently converted to the NETASCII format (i.e.,
    1648         * you should not attempt to create a special InputStream to do this).
    1649         * <p>
    1650         * @param remote  The name on which to base the unique name given to
    1651         *                the remote file.
    1652         * @param local   The local InputStream from which to read the file.
    1653         * @return True if successfully completed, false if not.
    1654         * @exception FTPConnectionClosedException
    1655         *      If the FTP server prematurely closes the connection as a result
    1656         *      of the client being idle or some other reason causing the server
    1657         *      to send FTP reply code 421.  This exception may be caught either
    1658         *      as an IOException or independently as itself.
    1659         * @exception CopyStreamException  If an I/O error occurs while actually
    1660         *      transferring the file.  The CopyStreamException allows you to
    1661         *      determine the number of bytes transferred and the IOException
    1662         *      causing the error.  This exception may be caught either
    1663         *      as an IOException or independently as itself.
    1664         * @exception IOException  If an I/O error occurs while either sending a
    1665         *      command to the server or receiving a reply from the server.
    1666         ***/
    1667        public boolean storeUniqueFile(String remote, InputStream local)
    1668        throws IOException
    1669        {
    1670            return __storeFile(FTPCommand.STOU, remote, local);
    1671        }
    1672
    1673
    1674        /***
    1675         * Returns an OutputStream through which data can be written to store
    1676         * a file on the server using a unique name derived from the given name.
    1677         * If the current file type
    1678         * is ASCII, the returned OutputStream will convert line separators in
    1679         * the file to the NETASCII format  (i.e., you should not attempt to
    1680         * create a special OutputStream to do this).  You must close the
    1681         * OutputStream when you finish writing to it.  The OutputStream itself
    1682         * will take care of closing the parent data connection socket upon being
    1683         * closed.  To finalize the file transfer you must call
    1684         * {@link #completePendingCommand  completePendingCommand } and
    1685         * check its return value to verify success.
    1686         * <p>
    1687         * @param remote  The name on which to base the unique name given to
    1688         *                the remote file.
    1689         * @return An OutputStream through which the remote file can be written.  If
    1690         *      the data connection cannot be opened (e.g., the file does not
    1691         *      exist), null is returned (in which case you may check the reply
    1692         *      code to determine the exact reason for failure).
    1693         * @exception FTPConnectionClosedException
    1694         *      If the FTP server prematurely closes the connection as a result
    1695         *      of the client being idle or some other reason causing the server
    1696         *      to send FTP reply code 421.  This exception may be caught either
    1697         *      as an IOException or independently as itself.
    1698         * @exception IOException  If an I/O error occurs while either sending a
    1699         *      command to the server or receiving a reply from the server.
    1700         ***/
    1701        public OutputStream storeUniqueFileStream(String remote) throws IOException
    1702        {
    1703            return __storeFileStream(FTPCommand.STOU, remote);
    1704        }
    1705
    1706        /**
    1707         * Stores a file on the server using a unique name assigned by the
    1708         * server and taking input from the given InputStream.  This method does
    1709         * NOT close the given
    1710         * InputStream.  If the current file type is ASCII, line separators in
    1711         * the file are transparently converted to the NETASCII format (i.e.,
    1712         * you should not attempt to create a special InputStream to do this).
    1713         * <p>
    1714         * @param local   The local InputStream from which to read the file.
    1715         * @return True if successfully completed, false if not.
    1716         * @exception FTPConnectionClosedException
    1717         *      If the FTP server prematurely closes the connection as a result
    1718         *      of the client being idle or some other reason causing the server
    1719         *      to send FTP reply code 421.  This exception may be caught either
    1720         *      as an IOException or independently as itself.
    1721         * @exception CopyStreamException  If an I/O error occurs while actually
    1722         *      transferring the file.  The CopyStreamException allows you to
    1723         *      determine the number of bytes transferred and the IOException
    1724         *      causing the error.  This exception may be caught either
    1725         *      as an IOException or independently as itself.
    1726         * @exception IOException  If an I/O error occurs while either sending a
    1727         *      command to the server or receiving a reply from the server.
    1728         */
    1729        public boolean storeUniqueFile(InputStream local) throws IOException
    1730        {
    1731            return __storeFile(FTPCommand.STOU, null, local);
    1732        }
    1733
    1734        /**
    1735         * Returns an OutputStream through which data can be written to store
    1736         * a file on the server using a unique name assigned by the server.
    1737         * If the current file type
    1738         * is ASCII, the returned OutputStream will convert line separators in
    1739         * the file to the NETASCII format  (i.e., you should not attempt to
    1740         * create a special OutputStream to do this).  You must close the
    1741         * OutputStream when you finish writing to it.  The OutputStream itself
    1742         * will take care of closing the parent data connection socket upon being
    1743         * closed.  To finalize the file transfer you must call
    1744         * {@link #completePendingCommand  completePendingCommand } and
    1745         * check its return value to verify success.
    1746         * <p>
    1747         * @return An OutputStream through which the remote file can be written.  If
    1748         *      the data connection cannot be opened (e.g., the file does not
    1749         *      exist), null is returned (in which case you may check the reply
    1750         *      code to determine the exact reason for failure).
    1751         * @exception FTPConnectionClosedException
    1752         *      If the FTP server prematurely closes the connection as a result
    1753         *      of the client being idle or some other reason causing the server
    1754         *      to send FTP reply code 421.  This exception may be caught either
    1755         *      as an IOException or independently as itself.
    1756         * @exception IOException  If an I/O error occurs while either sending a
    1757         *      command to the server or receiving a reply from the server.
    1758         */
    1759        public OutputStream storeUniqueFileStream() throws IOException
    1760        {
    1761            return __storeFileStream(FTPCommand.STOU, null);
    1762        }
    1763
    1764        /***
    1765         * Reserve a number of bytes on the server for the next file transfer.
    1766         * <p>
    1767         * @param bytes  The number of bytes which the server should allocate.
    1768         * @return True if successfully completed, false if not.
    1769         * @exception FTPConnectionClosedException
    1770         *      If the FTP server prematurely closes the connection as a result
    1771         *      of the client being idle or some other reason causing the server
    1772         *      to send FTP reply code 421.  This exception may be caught either
    1773         *      as an IOException or independently as itself.
    1774         * @exception IOException  If an I/O error occurs while either sending a
    1775         *      command to the server or receiving a reply from the server.
    1776         ***/
    1777        public boolean allocate(int bytes) throws IOException
    1778        {
    1779            return FTPReply.isPositiveCompletion(allo(bytes));
    1780        }
    1781
    1782        /**
    1783         * Query the server for supported features. The server may reply with a list of server-supported exensions.
    1784         * For example, a typical client-server interaction might be (from RFC     2289):
    1785         * <pre>
    1786            C> feat
    1787            S> 211-Extensions supported:
    1788            S>  MLST size*;create;modify*;perm;media-type
    1789            S>  SIZE
    1790            S>  COMPRESSION
    1791            S>  MDTM
    1792            S> 211 END
    1793         * </pre>
    1794         * @see <a href="http://www.faqs.org/rfcs/rfc2389.html">http://www.faqs.org/rfcs/rfc2389.html</a>
    1795         * @return True if successfully completed, false if not.
    1796         * @throws IOException
    1797         * @since 2.2
    1798         */
    1799        public boolean features() throws IOException {
    1800            return FTPReply.isPositiveCompletion(feat());
    1801        }
    1802
    1803
    1804        /**
    1805         * Reserve space on the server for the next file transfer.
    1806         * <p>
    1807         * @param bytes  The number of bytes which the server should allocate.
    1808         * @param recordSize  The size of a file record.
    1809         * @return True if successfully completed, false if not.
    1810         * @exception FTPConnectionClosedException
    1811         *      If the FTP server prematurely closes the connection as a result
    1812         *      of the client being idle or some other reason causing the server
    1813         *      to send FTP reply code 421.  This exception may be caught either
    1814         *      as an IOException or independently as itself.
    1815         * @exception IOException  If an I/O error occurs while either sending a
    1816         *      command to the server or receiving a reply from the server.
    1817         */
    1818        public boolean allocate(int bytes, int recordSize) throws IOException
    1819        {
    1820            return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
    1821        }
    1822
    1823
    1824        /***
    1825         * Restart a <code>STREAM_TRANSFER_MODE</code> file transfer starting
    1826         * from the given offset.  This will only work on FTP servers supporting
    1827         * the REST comand for the stream transfer mode.  However, most FTP
    1828         * servers support this.  Any subsequent file transfer will start
    1829         * reading or writing the remote file from the indicated offset.
    1830         * <p>
    1831         * @param offset  The offset into the remote file at which to start the
    1832         *           next file transfer.
    1833         * @return True if successfully completed, false if not.
    1834         * @exception FTPConnectionClosedException
    1835         *      If the FTP server prematurely closes the connection as a result
    1836         *      of the client being idle or some other reason causing the server
    1837         *      to send FTP reply code 421.  This exception may be caught either
    1838         *      as an IOException or independently as itself.
    1839         * @exception IOException  If an I/O error occurs while either sending a
    1840         *      command to the server or receiving a reply from the server.
    1841         ***/
    1842        private boolean restart(long offset) throws IOException
    1843        {
    1844            __restartOffset = 0;
    1845            return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
    1846        }
    1847
    1848        /***
    1849         * Sets the restart offset.  The restart command is sent to the server
    1850         * only before sending the file transfer command.  When this is done,
    1851         * the restart marker is reset to zero.
    1852         * <p>
    1853         * @param offset  The offset into the remote file at which to start the
    1854         *           next file transfer.  This must be a value greater than or
    1855         *           equal to zero.
    1856         ***/
    1857        public void setRestartOffset(long offset)
    1858        {
    1859            if (offset >= 0)
    1860                __restartOffset = offset;
    1861        }
    1862
    1863        /***
    1864         * Fetches the restart offset.
    1865         * <p>
    1866         * @return offset  The offset into the remote file at which to start the
    1867         *           next file transfer.
    1868         ***/
    1869        public long getRestartOffset()
    1870        {
    1871            return __restartOffset;
    1872        }
    1873
    1874
    1875
    1876        /***
    1877         * Renames a remote file.
    1878         * <p>
    1879         * @param from  The name of the remote file to rename.
    1880         * @param to    The new name of the remote file.
    1881         * @return True if successfully completed, false if not.
    1882         * @exception FTPConnectionClosedException
    1883         *      If the FTP server prematurely closes the connection as a result
    1884         *      of the client being idle or some other reason causing the server
    1885         *      to send FTP reply code 421.  This exception may be caught either
    1886         *      as an IOException or independently as itself.
    1887         * @exception IOException  If an I/O error occurs while either sending a
    1888         *      command to the server or receiving a reply from the server.
    1889         ***/
    1890        public boolean rename(String from, String to) throws IOException
    1891        {
    1892            if (!FTPReply.isPositiveIntermediate(rnfr(from)))
    1893                return false;
    1894
    1895            return FTPReply.isPositiveCompletion(rnto(to));
    1896        }
    1897
    1898
    1899        /***
    1900         * Abort a transfer in progress.
    1901         * <p>
    1902         * @return True if successfully completed, false if not.
    1903         * @exception FTPConnectionClosedException
    1904         *      If the FTP server prematurely closes the connection as a result
    1905         *      of the client being idle or some other reason causing the server
    1906         *      to send FTP reply code 421.  This exception may be caught either
    1907         *      as an IOException or independently as itself.
    1908         * @exception IOException  If an I/O error occurs while either sending a
    1909         *      command to the server or receiving a reply from the server.
    1910         ***/
    1911        public boolean abort() throws IOException
    1912        {
    1913            return FTPReply.isPositiveCompletion(abor());
    1914        }
    1915
    1916        /***
    1917         * Deletes a file on the FTP server.
    1918         * <p>
    1919         * @param pathname   The pathname of the file to be deleted.
    1920         * @return True if successfully completed, false if not.
    1921         * @exception FTPConnectionClosedException
    1922         *      If the FTP server prematurely closes the connection as a result
    1923         *      of the client being idle or some other reason causing the server
    1924         *      to send FTP reply code 421.  This exception may be caught either
    1925         *      as an IOException or independently as itself.
    1926         * @exception IOException  If an I/O error occurs while either sending a
    1927         *      command to the server or receiving a reply from the server.
    1928         ***/
    1929        public boolean deleteFile(String pathname) throws IOException
    1930        {
    1931            return FTPReply.isPositiveCompletion(dele(pathname));
    1932        }
    1933
    1934
    1935        /***
    1936         * Removes a directory on the FTP server (if empty).
    1937         * <p>
    1938         * @param pathname  The pathname of the directory to remove.
    1939         * @return True if successfully completed, false if not.
    1940         * @exception FTPConnectionClosedException
    1941         *      If the FTP server prematurely closes the connection as a result
    1942         *      of the client being idle or some other reason causing the server
    1943         *      to send FTP reply code 421.  This exception may be caught either
    1944         *      as an IOException or independently as itself.
    1945         * @exception IOException  If an I/O error occurs while either sending a
    1946         *      command to the server or receiving a reply from the server.
    1947         ***/
    1948        public boolean removeDirectory(String pathname) throws IOException
    1949        {
    1950            return FTPReply.isPositiveCompletion(rmd(pathname));
    1951        }
    1952
    1953
    1954        /***
    1955         * Creates a new subdirectory on the FTP server in the current directory
    1956         * (if a relative pathname is given) or where specified (if an absolute
    1957         * pathname is given).
    1958         * <p>
    1959         * @param pathname The pathname of the directory to create.
    1960         * @return True if successfully completed, false if not.
    1961         * @exception FTPConnectionClosedException
    1962         *      If the FTP server prematurely closes the connection as a result
    1963         *      of the client being idle or some other reason causing the server
    1964         *      to send FTP reply code 421.  This exception may be caught either
    1965         *      as an IOException or independently as itself.
    1966         * @exception IOException  If an I/O error occurs while either sending a
    1967         *      command to the server or receiving a reply from the server.
    1968         ***/
    1969        public boolean makeDirectory(String pathname) throws IOException
    1970        {
    1971            return FTPReply.isPositiveCompletion(mkd(pathname));
    1972        }
    1973
    1974
    1975        /***
    1976         * Returns the pathname of the current working directory.
    1977         * <p>
    1978         * @return The pathname of the current working directory.  If it cannot
    1979         *         be obtained, returns null.
    1980         * @exception FTPConnectionClosedException
    1981         *      If the FTP server prematurely closes the connection as a result
    1982         *      of the client being idle or some other reason causing the server
    1983         *      to send FTP reply code 421.  This exception may be caught either
    1984         *      as an IOException or independently as itself.
    1985         * @exception IOException  If an I/O error occurs while either sending a
    1986         *      command to the server or receiving a reply from the server.
    1987         ***/
    1988        public String printWorkingDirectory() throws IOException
    1989        {
    1990            if (pwd() != FTPReply.PATHNAME_CREATED)
    1991                return null;
    1992
    1993            return __parsePathname(_replyLines.get( _replyLines.size() - 1));
    1994        }
    1995
    1996
    1997        /**
    1998         * Send a site specific command.
    1999         * @param arguments The site specific command and arguments.
    2000         * @return True if successfully completed, false if not.
    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 boolean sendSiteCommand(String arguments) throws IOException
    2010        {
    2011            return FTPReply.isPositiveCompletion(site(arguments));
    2012        }
    2013
    2014
    2015        /***
    2016         * Fetches the system type name from the server and returns the string.
    2017         * This value is cached for the duration of the connection after the
    2018         * first call to this method.  In other words, only the first time
    2019         * that you invoke this method will it issue a SYST command to the
    2020         * FTP server.  FTPClient will remember the value and return the
    2021         * cached value until a call to disconnect.
    2022         * <p>
    2023         * @return The system type name obtained from the server.  null if the
    2024         *       information could not be obtained.
    2025         * @exception FTPConnectionClosedException
    2026         *      If the FTP server prematurely closes the connection as a result
    2027         *      of the client being idle or some other reason causing the server
    2028         *      to send FTP reply code 421.  This exception may be caught either
    2029         *      as an IOException or independently as itself.
    2030         * @exception IOException  If an I/O error occurs while either sending a
    2031         *  command to the server or receiving a reply from the server.
    2032         *  @deprecated Use {@link #getSystemType()} - which does not return null.
    2033         *  Will be deleted in version 3.0
    2034         ***/
    2035        @Deprecated
    2036        public String getSystemName() throws IOException
    2037        {
    2038            //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
    2039            // Technically, we should expect a NAME_SYSTEM_TYPE response, but
    2040            // in practice FTP servers deviate, so we soften the condition to
    2041            // a positive completion.
    2042            if (__systemName == null && FTPReply.isPositiveCompletion(syst()))
    2043                __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
    2044
    2045            return __systemName;
    2046        }
    2047
    2048
    2049        /***
    2050         * Fetches the system type from the server and returns the string.
    2051         * This value is cached for the duration of the connection after the
    2052         * first call to this method.  In other words, only the first time
    2053         * that you invoke this method will it issue a SYST command to the
    2054         * FTP server.  FTPClient will remember the value and return the
    2055         * cached value until a call to disconnect.
    2056         * <p>
    2057         * @return The system type obtained from the server. Never null.
    2058         * @exception FTPConnectionClosedException
    2059         *      If the FTP server prematurely closes the connection as a result
    2060         *      of the client being idle or some other reason causing the server
    2061         *      to send FTP reply code 421.  This exception may be caught either
    2062         *      as an IOException or independently as itself.
    2063         * @exception IOException  If an I/O error occurs while either sending a
    2064         *  command to the server or receiving a reply from the server.
    2065         *  @since 2.2
    2066         ***/
    2067        public String getSystemType() throws IOException
    2068        {
    2069            //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
    2070            // Technically, we should expect a NAME_SYSTEM_TYPE response, but
    2071            // in practice FTP servers deviate, so we soften the condition to
    2072            // a positive completion.
    2073            if (__systemName == null){
    2074                if (FTPReply.isPositiveCompletion(syst())) {
    2075                    // Assume that response is not empty here (cannot be null)
    2076                    __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
    2077                } else {
    2078                    throw new IOException("Unable to determine system type - response: " + getReplyString());
    2079                }
    2080            }
    2081            return __systemName;
    2082        }
    2083
    2084
    2085        /***
    2086         * Fetches the system help information from the server and returns the
    2087         * full string.
    2088         * <p>
    2089         * @return The system help string obtained from the server.  null if the
    2090         *       information could not be obtained.
    2091         * @exception FTPConnectionClosedException
    2092         *      If the FTP server prematurely closes the connection as a result
    2093         *      of the client being idle or some other reason causing the server
    2094         *      to send FTP reply code 421.  This exception may be caught either
    2095         *      as an IOException or independently as itself.
    2096         * @exception IOException  If an I/O error occurs while either sending a
    2097         *  command to the server or receiving a reply from the server.
    2098         ***/
    2099        public String listHelp() throws IOException
    2100        {
    2101            if (FTPReply.isPositiveCompletion(help()))
    2102                return getReplyString();
    2103            return null;
    2104        }
    2105
    2106
    2107        /**
    2108         * Fetches the help information for a given command from the server and
    2109         * returns the full string.
    2110         * @param command The command on which to ask for help.
    2111         * @return The command help string obtained from the server.  null if the
    2112         *       information could not be obtained.
    2113         * @exception FTPConnectionClosedException
    2114         *      If the FTP server prematurely closes the connection as a result
    2115         *      of the client being idle or some other reason causing the server
    2116         *      to send FTP reply code 421.  This exception may be caught either
    2117         *      as an IOException or independently as itself.
    2118         * @exception IOException  If an I/O error occurs while either sending a
    2119         *  command to the server or receiving a reply from the server.
    2120         */
    2121        public String listHelp(String command) throws IOException
    2122        {
    2123            if (FTPReply.isPositiveCompletion(help(command)))
    2124                return getReplyString();
    2125            return null;
    2126        }
    2127
    2128
    2129        /***
    2130         * Sends a NOOP command to the FTP server.  This is useful for preventing
    2131         * server timeouts.
    2132         * <p>
    2133         * @return True if successfully completed, false if not.
    2134         * @exception FTPConnectionClosedException
    2135         *      If the FTP server prematurely closes the connection as a result
    2136         *      of the client being idle or some other reason causing the server
    2137         *      to send FTP reply code 421.  This exception may be caught either
    2138         *      as an IOException or independently as itself.
    2139         * @exception IOException  If an I/O error occurs while either sending a
    2140         *      command to the server or receiving a reply from the server.
    2141         ***/
    2142        public boolean sendNoOp() throws IOException
    2143        {
    2144            return FTPReply.isPositiveCompletion(noop());
    2145        }
    2146
    2147
    2148        /***
    2149         * Obtain a list of filenames in a directory (or just the name of a given
    2150         * file, which is not particularly useful).  This information is obtained
    2151         * through the NLST command.  If the given pathname is a directory and
    2152         * contains no files,  a zero length array is returned only
    2153         * if the FTP server returned a positive completion code, otherwise
    2154         * null is returned (the FTP server returned a 550 error No files found.).
    2155         * If the directory is not empty, an array of filenames in the directory is
    2156         * returned. If the pathname corresponds
    2157         * to a file, only that file will be listed.  The server may or may not
    2158         * expand glob expressions.
    2159         * <p>
    2160         * @param pathname  The file or directory to list.
    2161         * @return The list of filenames contained in the given path.  null if
    2162         *     the list could not be obtained.  If there are no filenames in
    2163         *     the directory, a zero-length array is returned.
    2164         * @exception FTPConnectionClosedException
    2165         *      If the FTP server prematurely closes the connection as a result
    2166         *      of the client being idle or some other reason causing the server
    2167         *      to send FTP reply code 421.  This exception may be caught either
    2168         *      as an IOException or independently as itself.
    2169         * @exception IOException  If an I/O error occurs while either sending a
    2170         *      command to the server or receiving a reply from the server.
    2171         ***/
    2172        public String[] listNames(String pathname) throws IOException
    2173        {
    2174            String line;
    2175            Socket socket;
    2176            BufferedReader reader;
    2177            ArrayList<String> results;
    2178
    2179            if ((socket = _openDataConnection_(FTPCommand.NLST, pathname)) == null)
    2180                return null;
    2181
    2182            reader =
    2183                new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding()));
    2184
    2185            results = new ArrayList<String>();
    2186            while ((line = reader.readLine()) != null)
    2187                results.add(line);
    2188
    2189            reader.close();
    2190            socket.close();
    2191
    2192            if (completePendingCommand())
    2193            {
    2194                String[] names = new String[ results.size() ];
    2195                return results.toArray(names);
    2196            }
    2197
    2198            return null;
    2199        }
    2200
    2201
    2202        /***
    2203         * Obtain a list of filenames in the current working directory
    2204         * This information is obtained through the NLST command.  If the current
    2205         * directory contains no files, a zero length array is returned only
    2206         * if the FTP server returned a positive completion code, otherwise,
    2207         * null is returned (the FTP server returned a 550 error No files found.).
    2208         * If the directory is not empty, an array of filenames in the directory is
    2209         * returned.
    2210         * <p>
    2211         * @return The list of filenames contained in the current working
    2212         *     directory.  null if the list could not be obtained.
    2213         *     If there are no filenames in the directory, a zero-length array
    2214         *     is returned.
    2215         * @exception FTPConnectionClosedException
    2216         *      If the FTP server prematurely closes the connection as a result
    2217         *      of the client being idle or some other reason causing the server
    2218         *      to send FTP reply code 421.  This exception may be caught either
    2219         *      as an IOException or independently as itself.
    2220         * @exception IOException  If an I/O error occurs while either sending a
    2221         *      command to the server or receiving a reply from the server.
    2222         ***/
    2223        public String[] listNames() throws IOException
    2224        {
    2225            return listNames(null);
    2226        }
    2227
    2228
    2229
    2230        /**
    2231         * Using the default system autodetect mechanism, obtain a
    2232         * list of file information for the current working directory
    2233         * or for just a single file.
    2234         * <p>
    2235         * This information is obtained through the LIST command.  The contents of
    2236         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2237         * used.
    2238         * <p>
    2239         * @param pathname  The file or directory to list.  Since the server may
    2240         *                  or may not expand glob expressions, using them here
    2241         *                  is not recommended and may well cause this method to
    2242         *                  fail.
    2243         *
    2244         * @return The list of file information contained in the given path in
    2245         *         the format determined by the autodetection mechanism
    2246         * @exception FTPConnectionClosedException
    2247         *                   If the FTP server prematurely closes the connection
    2248         *                   as a result of the client being idle or some other
    2249         *                   reason causing the server to send FTP reply code 421.
    2250         *                   This exception may be caught either as an IOException
    2251         *                   or independently as itself.
    2252         * @exception IOException
    2253         *                   If an I/O error occurs while either sending a
    2254         *                   command to the server or receiving a reply
    2255         *                   from the server.
    2256         * @exception ParserInitializationException
    2257         *                   Thrown if the parserKey parameter cannot be
    2258         *                   resolved by the selected parser factory.
    2259         *                   In the DefaultFTPEntryParserFactory, this will
    2260         *                   happen when parserKey is neither
    2261         *                   the fully qualified class name of a class
    2262         *                   implementing the interface
    2263         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2264         *                   nor a string containing one of the recognized keys
    2265         *                   mapping to such a parser or if class loader
    2266         *                   security issues prevent its being loaded.
    2267         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2268         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2269         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2270         */
    2271        public FTPFile[] listFiles(String pathname)
    2272        throws IOException
    2273        {
    2274            String key = null;
    2275            FTPListParseEngine engine =
    2276                initiateListParsing(key, pathname);
    2277            return engine.getFiles();
    2278
    2279        }
    2280        /**
    2281         * Using the default system autodetect mechanism, obtain a
    2282         * list of file information for the current working directory.
    2283         * <p>
    2284         * This information is obtained through the LIST command.  The contents of
    2285         * the returned array is determined by the<code> FTPFileEntryParser </code>
    2286         * used.
    2287         * <p>
    2288         * @return The list of file information contained in the current directory
    2289         *         in the format determined by the autodetection mechanism.
    2290         *         <p><b>
    2291         *         NOTE:</b> This array may contain null members if any of the
    2292         *         individual file listings failed to parse.  The caller should
    2293         *         check each entry for null before referencing it.
    2294         * @exception FTPConnectionClosedException
    2295         *                   If the FTP server prematurely closes the connection
    2296         *                   as a result of the client being idle or some other
    2297         *                   reason causing the server to send FTP reply code 421.
    2298         *                   This exception may be caught either as an IOException
    2299         *                   or independently as itself.
    2300         * @exception IOException
    2301         *                   If an I/O error occurs while either sending a
    2302         *                   command to the server or receiving a reply
    2303         *                   from the server.
    2304         * @exception ParserInitializationException
    2305         *                   Thrown if the parserKey parameter cannot be
    2306         *                   resolved by the selected parser factory.
    2307         *                   In the DefaultFTPEntryParserFactory, this will
    2308         *                   happen when parserKey is neither
    2309         *                   the fully qualified class name of a class
    2310         *                   implementing the interface
    2311         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2312         *                   nor a string containing one of the recognized keys
    2313         *                   mapping to such a parser or if class loader
    2314         *                   security issues prevent its being loaded.
    2315         * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
    2316         * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
    2317         * @see org.apache.commons.net.ftp.FTPFileEntryParser
    2318         */
    2319        public FTPFile[] listFiles()
    2320        throws IOException
    2321        {
    2322            return listFiles((String) null);
    2323        }
    2324
    2325        /**
    2326         * Version of {@link #listFiles(String)} which allows a filter to be provided.
    2327         * For example: <code>listFiles("site", FTPFileFilters.DIRECTORY);</code>
    2328         * @param pathname the initial path, may be null
    2329         * @param filter the filter, non-null
    2330         * @return the list of FTPFile entries.
    2331         * @throws IOException
    2332         * @since 2.2
    2333         */
    2334        public FTPFile[] listFiles(String pathname, FTPFileFilter filter)
    2335        throws IOException
    2336        {
    2337            FTPListParseEngine engine = initiateListParsing((String) null, pathname);
    2338            return engine.getFiles(filter);
    2339
    2340        }
    2341
    2342        /**
    2343         * Using the default autodetect mechanism, initialize an FTPListParseEngine
    2344         * object containing a raw file information for the current working
    2345         * directory on the server
    2346         * This information is obtained through the LIST command.  This object
    2347         * is then capable of being iterated to return a sequence of FTPFile
    2348         * objects with information filled in by the
    2349         * <code> FTPFileEntryParser </code> used.
    2350         * <p>
    2351         * This method differs from using the listFiles() methods in that
    2352         * expensive FTPFile objects are not created until needed which may be
    2353         * an advantage on large lists.
    2354         *
    2355         * @return A FTPListParseEngine object that holds the raw information and
    2356         * is capable of providing parsed FTPFile objects, one for each file
    2357         * containing information contained in the given path in the format
    2358         * determined by the <code> parser </code> parameter.   Null will be
    2359         * returned if a data connection cannot be opened.  If the current working
    2360         * directory contains no files, an empty array will be the return.
    2361         *
    2362         * @exception FTPConnectionClosedException
    2363         *                   If the FTP server prematurely closes the connection as a result
    2364         *                   of the client being idle or some other reason causing the server
    2365         *                   to send FTP reply code 421.  This exception may be caught either
    2366         *                   as an IOException or independently as itself.
    2367         * @exception IOException
    2368         *                   If an I/O error occurs while either sending a
    2369         *                   command to the server or receiving a reply from the server.
    2370         * @exception ParserInitializationException
    2371         *                   Thrown if the autodetect mechanism cannot
    2372         *                   resolve the type of system we are connected with.
    2373         * @see FTPListParseEngine
    2374         */
    2375        public FTPListParseEngine initiateListParsing()
    2376        throws IOException
    2377        {
    2378            return initiateListParsing((String) null);
    2379        }
    2380
    2381        /**
    2382         * Using the default autodetect mechanism, initialize an FTPListParseEngine
    2383         * object containing a raw file information for the supplied directory.
    2384         * This information is obtained through the LIST command.  This object
    2385         * is then capable of being iterated to return a sequence of FTPFile
    2386         * objects with information filled in by the
    2387         * <code> FTPFileEntryParser </code> used.
    2388         * <p>
    2389         * The server may or may not expand glob expressions.  You should avoid
    2390         * using glob expressions because the return format for glob listings
    2391         * differs from server to server and will likely cause this method to fail.
    2392         * <p>
    2393         * This method differs from using the listFiles() methods in that
    2394         * expensive FTPFile objects are not created until needed which may be
    2395         * an advantage on large lists.
    2396         * <p>
    2397         * <pre>
    2398         *    FTPClient f=FTPClient();
    2399         *    f.connect(server);
    2400         *    f.login(username, password);
    2401         *    FTPListParseEngine engine = f.initiateListParsing(directory);
    2402         *
    2403         *    while (engine.hasNext()) {
    2404         *       FTPFile[] files = engine.getNext(25);  // "page size" you want
    2405         *       //do whatever you want with these files, display them, etc.
    2406         *       //expensive FTPFile objects not created until needed.
    2407         *    }
    2408         * </pre>
    2409         *
    2410         * @return A FTPListParseEngine object that holds the raw information and
    2411         * is capable of providing parsed FTPFile objects, one for each file
    2412         * containing information contained in the given path in the format
    2413         * determined by the <code> parser </code> parameter.   Null will be
    2414         * returned if a data connection cannot be opened.  If the current working
    2415         * directory contains no files, an empty array will be the return.
    2416         *
    2417         * @exception FTPConnectionClosedException
    2418         *                   If the FTP server prematurely closes the connection as a result
    2419         *                   of the client being idle or some other reason causing the server
    2420         *                   to send FTP reply code 421.  This exception may be caught either
    2421         *                   as an IOException or independently as itself.
    2422         * @exception IOException
    2423         *                   If an I/O error occurs while either sending a
    2424         *                   command to the server or receiving a reply from the server.
    2425         * @exception ParserInitializationException
    2426         *                   Thrown if the autodetect mechanism cannot
    2427         *                   resolve the type of system we are connected with.
    2428         * @see FTPListParseEngine
    2429         */
    2430        public FTPListParseEngine initiateListParsing(
    2431                String pathname)
    2432        throws IOException
    2433        {
    2434            String key = null;
    2435            return initiateListParsing(key, pathname);
    2436        }
    2437
    2438        /**
    2439         * Using the supplied parser key, initialize an FTPListParseEngine
    2440         * object containing a raw file information for the supplied directory.
    2441         * This information is obtained through the LIST command.  This object
    2442         * is then capable of being iterated to return a sequence of FTPFile
    2443         * objects with information filled in by the
    2444         * <code> FTPFileEntryParser </code> used.
    2445         * <p>
    2446         * The server may or may not expand glob expressions.  You should avoid
    2447         * using glob expressions because the return format for glob listings
    2448         * differs from server to server and will likely cause this method to fail.
    2449         * <p>
    2450         * This method differs from using the listFiles() methods in that
    2451         * expensive FTPFile objects are not created until needed which may be
    2452         * an advantage on large lists.
    2453         *
    2454         * @param parserKey A string representing a designated code or fully-qualified
    2455         * class name of an  <code> FTPFileEntryParser </code> that should be
    2456         *               used to parse each server file listing.
    2457         *
    2458         * @return A FTPListParseEngine object that holds the raw information and
    2459         * is capable of providing parsed FTPFile objects, one for each file
    2460         * containing information contained in the given path in the format
    2461         * determined by the <code> parser </code> parameter.   Null will be
    2462         * returned if a data connection cannot be opened.  If the current working
    2463         * directory contains no files, an empty array will be the return.
    2464         *
    2465         * @exception FTPConnectionClosedException
    2466         *                   If the FTP server prematurely closes the connection as a result
    2467         *                   of the client being idle or some other reason causing the server
    2468         *                   to send FTP reply code 421.  This exception may be caught either
    2469         *                   as an IOException or independently as itself.
    2470         * @exception IOException
    2471         *                   If an I/O error occurs while either sending a
    2472         *                   command to the server or receiving a reply from the server.
    2473         * @exception ParserInitializationException
    2474         *                   Thrown if the parserKey parameter cannot be
    2475         *                   resolved by the selected parser factory.
    2476         *                   In the DefaultFTPEntryParserFactory, this will
    2477         *                   happen when parserKey is neither
    2478         *                   the fully qualified class name of a class
    2479         *                   implementing the interface
    2480         *                   org.apache.commons.net.ftp.FTPFileEntryParser
    2481         *                   nor a string containing one of the recognized keys
    2482         *                   mapping to such a parser or if class loader
    2483         *                   security issues prevent its being loaded.
    2484         * @see FTPListParseEngine
    2485         */
    2486        public FTPListParseEngine initiateListParsing(
    2487                String parserKey, String pathname)
    2488        throws IOException
    2489        {
    2490            // We cache the value to avoid creation of a new object every
    2491            // time a file listing is generated.
    2492            if(__entryParser == null ||  ! __entryParserKey.equals(parserKey)) {
    2493                if (null != parserKey) {
    2494                    // if a parser key was supplied in the parameters,
    2495                    // use that to create the parser
    2496                    __entryParser =
    2497                        __parserFactory.createFileEntryParser(parserKey);
    2498                    __entryParserKey = parserKey;
    2499
    2500                } else {
    2501                    // if no parserKey was supplied, check for a configuration
    2502                    // in the params, and if non-null, use that.
    2503                    if (null != __configuration) {
    2504                        __entryParser =
    2505                            __parserFactory.createFileEntryParser(__configuration);
    2506                        __entryParserKey = __configuration.getServerSystemKey();
    2507                    } else {
    2508                        // if a parserKey hasn't been supplied, and a configuration
    2509                        // hasn't been supplied, then autodetect by calling
    2510                        // the SYST command and use that to choose the parser.
    2511                        final String systemType = getSystemType(); // cannot be null
    2512                        __entryParser =
    2513                            __parserFactory.createFileEntryParser(systemType);
    2514                        __entryParserKey = systemType;
    2515                    }
    2516                }
    2517            }
    2518
    2519            return initiateListParsing(__entryParser, pathname);
    2520
    2521        }
    2522
    2523
    2524        /**
    2525         * private method through which all listFiles() and
    2526         * initiateListParsing methods pass once a parser is determined.
    2527         *
    2528         * @exception FTPConnectionClosedException
    2529         *                   If the FTP server prematurely closes the connection as a result
    2530         *                   of the client being idle or some other reason causing the server
    2531         *                   to send FTP reply code 421.  This exception may be caught either
    2532         *                   as an IOException or independently as itself.
    2533         * @exception IOException
    2534         *                   If an I/O error occurs while either sending a
    2535         *                   command to the server or receiving a reply from the server.
    2536         * @see FTPListParseEngine
    2537         */
    2538        private FTPListParseEngine initiateListParsing(
    2539                FTPFileEntryParser parser, String pathname)
    2540        throws IOException
    2541        {
    2542            Socket socket;
    2543
    2544            FTPListParseEngine engine = new FTPListParseEngine(parser);
    2545            if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null)
    2546            {
    2547                return engine;
    2548            }
    2549
    2550            try {
    2551                engine.readServerList(socket.getInputStream(), getControlEncoding());
    2552            }
    2553            finally {
    2554                socket.close();
    2555            }
    2556
    2557            completePendingCommand();
    2558            return engine;
    2559        }
    2560
    2561        /**
    2562         * @since 2.0
    2563         */
    2564        protected String getListArguments(String pathname) {
    2565            if (getListHiddenFiles())
    2566            {
    2567                if (pathname != null)
    2568                {
    2569                    StringBuilder sb = new StringBuilder(pathname.length() + 3);
    2570                    sb.append("-a ");
    2571                    sb.append(pathname);
    2572                    return sb.toString();
    2573                }
    2574                else
    2575                {
    2576                    return "-a";
    2577                }
    2578            }
    2579
    2580            return pathname;
    2581        }
    2582
    2583
    2584        /***
    2585         * Issue the FTP STAT command to the server.
    2586         * <p>
    2587         * @return The status information returned by the server.
    2588         * @exception FTPConnectionClosedException
    2589         *      If the FTP server prematurely closes the connection as a result
    2590         *      of the client being idle or some other reason causing the server
    2591         *      to send FTP reply code 421.  This exception may be caught either
    2592         *      as an IOException or independently as itself.
    2593         * @exception IOException  If an I/O error occurs while either sending a
    2594         *      command to the server or receiving a reply from the server.
    2595         ***/
    2596        public String getStatus() throws IOException
    2597        {
    2598            if (FTPReply.isPositiveCompletion(stat()))
    2599                return getReplyString();
    2600            return null;
    2601        }
    2602
    2603
    2604        /***
    2605         * Issue the FTP STAT command to the server for a given pathname.  This
    2606         * should produce a listing of the file or directory.
    2607         * <p>
    2608         * @return The status information returned by the server.
    2609         * @exception FTPConnectionClosedException
    2610         *      If the FTP server prematurely closes the connection as a result
    2611         *      of the client being idle or some other reason causing the server
    2612         *      to send FTP reply code 421.  This exception may be caught either
    2613         *      as an IOException or independently as itself.
    2614         * @exception IOException  If an I/O error occurs while either sending a
    2615         *      command to the server or receiving a reply from the server.
    2616         ***/
    2617        public String getStatus(String pathname) throws IOException
    2618        {
    2619            if (FTPReply.isPositiveCompletion(stat(pathname)))
    2620                return getReplyString();
    2621            return null;
    2622        }
    2623
    2624
    2625        /**
    2626         * Issue the FTP MDTM command (not supported by all servers to retrieve the last
    2627         * modification time of a file. The modification string should be in the
    2628         * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in
    2629         * GMT, but not all FTP servers honour this.
    2630         *
    2631         * @param pathname The file path to query.
    2632         * @return A string representing the last file modification time in <code>YYYYMMDDhhmmss</code> format.
    2633         * @throws IOException if an I/O error occurs.
    2634         * @since 2.0
    2635         */
    2636        public String getModificationTime(String pathname) throws IOException {
    2637            if (FTPReply.isPositiveCompletion(mdtm(pathname)))
    2638                return getReplyString();
    2639            return null;
    2640        }
    2641
    2642
    2643        /**
    2644         * Issue the FTP MFMT command (not supported by all servers) which sets the last
    2645         * modified time of a file.
    2646         *
    2647         * The timestamp should be in the form <code>YYYYMMDDhhmmss</code>. It should also
    2648         * be in GMT, but not all servers honour this.
    2649         *
    2650         * An FTP server would indicate its support of this feature by including "MFMT"
    2651         * in its response to the FEAT command, which may be retrieved by FTPClient.features()
    2652         *
    2653         * @param pathname The file path for which last modified time is to be changed.
    2654         * @param timeval The timestamp to set to, in <code>YYYYMMDDhhmmss</code> format.
    2655         * @return true if successfully set, false if not
    2656         * @throws IOException if an I/O error occurs.
    2657         * @since 2.2
    2658         * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
    2659         */
    2660        public boolean setModificationTime(String pathname, String timeval) throws IOException {
    2661            return (FTPReply.isPositiveCompletion(mfmt(pathname, timeval)));
    2662        }
    2663
    2664
    2665        /**
    2666         * Set the internal buffer size.
    2667         *
    2668         * @param bufSize The size of the buffer
    2669         */
    2670        public void setBufferSize(int bufSize) {
    2671            __bufferSize = bufSize;
    2672        }
    2673
    2674        /**
    2675         * Retrieve the current internal buffer size.
    2676         * @return The current buffer size.
    2677         */
    2678        public int getBufferSize() {
    2679            return __bufferSize;
    2680        }
    2681
    2682
    2683        /**
    2684         * Implementation of the {@link Configurable Configurable} interface.
    2685         * In the case of this class, configuring merely makes the config object available for the
    2686         * factory methods that construct parsers.
    2687         * @param config {@link FTPClientConfig FTPClientConfig} object used to
    2688         * provide non-standard configurations to the parser.
    2689         * @since 1.4
    2690         */
    2691        public void configure(FTPClientConfig config) {
    2692            this.__configuration = config;
    2693        }
    2694
    2695        /**
    2696         * You can set this to true if you would like to get hidden files when {@link #listFiles} too.
    2697         * A <code>LIST -a</code> will be issued to the ftp server.
    2698         * It depends on your ftp server if you need to call this method, also dont expect to get rid
    2699         * of hidden files if you call this method with "false".
    2700         *
    2701         * @param listHiddenFiles true if hidden files should be listed
    2702         * @since 2.0
    2703         */
    2704        public void setListHiddenFiles(boolean listHiddenFiles) {
    2705            this.__listHiddenFiles = listHiddenFiles;
    2706        }
    2707
    2708        /**
    2709         * @see #setListHiddenFiles(boolean)
    2710         * @return the current state
    2711         * @since 2.0
    2712         */
    2713        public boolean getListHiddenFiles() {
    2714            return this.__listHiddenFiles;
    2715        }
    2716
    2717        /**
    2718         * Whether should attempt to use EPSV with IPv4.
    2719         * Default (if not set) is <code>false</code>
    2720         * @return true if should attempt EPS
    2721         * @since 2.2
    2722         */
    2723        public boolean isUseEPSVwithIPv4() {
    2724            return __useEPSVwithIPv4;
    2725        }
    2726
    2727
    2728        /**
    2729         * Set whether to use EPSV with IPv4.
    2730         * Might be worth enabling in some circumstances.
    2731         *
    2732         * For example, when using IPv4 with NAT it
    2733         * may work with some rare configurations.
    2734         * E.g. if FTP server has a static PASV address (external network)
    2735         * and the client is coming from another internal network.
    2736         * In that case the data connection after PASV command would fail,
    2737         * while EPSV would make the client succeed by taking just the port.
    2738         *
    2739         * @param selected value to set.
    2740         * @since 2.2
    2741         */
    2742        public void setUseEPSVwithIPv4(boolean selected) {
    2743            this.__useEPSVwithIPv4 = selected;
    2744        }
    2745
    2746    }
    2747
    2748    /* Emacs configuration
    2749     * Local variables:        **
    2750     * mode:             java  **
    2751     * c-basic-offset:   4     **
    2752     * indent-tabs-mode: nil   **
    2753     * End:                    **
    2754     */