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     */