View Javadoc

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