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