View Javadoc

1   /*
2    * Copyright 2001-2005 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.net.ftp;
17  import java.io.BufferedInputStream;
18  import java.io.BufferedOutputStream;
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.io.OutputStream;
24  import java.net.InetAddress;
25  import java.net.ServerSocket;
26  import java.net.Socket;
27  import java.util.Vector;
28  
29  import org.apache.commons.net.MalformedServerReplyException;
30  import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
31  import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
32  import org.apache.commons.net.ftp.parser.ParserInitializationException;
33  import org.apache.commons.net.io.CopyStreamEvent;
34  import org.apache.commons.net.io.CopyStreamException;
35  import org.apache.commons.net.io.FromNetASCIIInputStream;
36  import org.apache.commons.net.io.ToNetASCIIOutputStream;
37  import org.apache.commons.net.io.Util;
38  
39  /***
40   * FTPClient encapsulates all the functionality necessary to store and
41   * retrieve files from an FTP server.  This class takes care of all
42   * low level details of interacting with an FTP server and provides
43   * a convenient higher level interface.  As with all classes derived
44   * from {@link org.apache.commons.net.SocketClient},
45   * you must first connect to the server with
46   * {@link org.apache.commons.net.SocketClient#connect  connect }
47   * before doing anything, and finally
48   * {@link org.apache.commons.net.SocketClient#disconnect  disconnect }
49   * after you're completely finished interacting with the server.
50   * Then you need to check the FTP reply code to see if the connection
51   * was successful.  For example:
52   * <pre>
53   *    boolean error = false;
54   *    try {
55   *      int reply;
56   *      ftp.connect("ftp.foobar.com");
57   *      System.out.println("Connected to " + server + ".");
58   *      System.out.print(ftp.getReplyString());
59   *
60   *      // After connection attempt, you should check the reply code to verify
61   *      // success.
62   *      reply = ftp.getReplyCode();
63   *
64   *      if(!FTPReply.isPositiveCompletion(reply)) {
65   *        ftp.disconnect();
66   *        System.err.println("FTP server refused connection.");
67   *        System.exit(1);
68   *      }
69   *      ... // transfer files
70   *      ftp.logout();
71   *    } catch(IOException e) {
72   *      error = true;
73   *      e.printStackTrace();
74   *    } finally {
75   *      if(ftp.isConnected()) {
76   *        try {
77   *          ftp.disconnect();
78   *        } catch(IOException ioe) {
79   *          // do nothing
80   *        }
81   *      }
82   *      System.exit(error ? 1 : 0);
83   *    }
84   * </pre>
85   * <p>
86   * Immediately after connecting is the only real time you need to check the
87   * reply code (because connect is of type void).  The convention for all the
88   * FTP command methods in FTPClient is such that they either return a
89   * boolean value or some other value.
90   * The boolean methods return true on a successful completion reply from
91   * the FTP server and false on a reply resulting in an error condition or
92   * failure.  The methods returning a value other than boolean return a value
93   * containing the higher level data produced by the FTP command, or null if a
94   * reply resulted in an error condition or failure.  If you want to access
95   * the exact FTP reply code causing a success or failure, you must call
96   * {@link org.apache.commons.net.ftp.FTP#getReplyCode  getReplyCode } after
97   * a success or failure.
98   * <p>
99   * 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  */