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