001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.net.ftp;
019import java.io.BufferedReader;
020import java.io.BufferedWriter;
021import java.io.IOException;
022import java.io.InputStreamReader;
023import java.io.OutputStreamWriter;
024import java.io.Reader;
025import java.net.Inet4Address;
026import java.net.Inet6Address;
027import java.net.InetAddress;
028import java.net.SocketException;
029import java.net.SocketTimeoutException;
030import java.util.ArrayList;
031
032import org.apache.commons.net.MalformedServerReplyException;
033import org.apache.commons.net.ProtocolCommandSupport;
034import org.apache.commons.net.SocketClient;
035import org.apache.commons.net.io.CRLFLineReader;
036
037/***
038 * FTP provides the basic the functionality necessary to implement your
039 * own FTP client.  It extends org.apache.commons.net.SocketClient since
040 * extending TelnetClient was causing unwanted behavior (like connections
041 * that did not time out properly).
042 * <p>
043 * To derive the full benefits of the FTP class requires some knowledge
044 * of the FTP protocol defined in RFC 959.  However, there is no reason
045 * why you should have to use the FTP class.  The
046 * {@link org.apache.commons.net.ftp.FTPClient} class,
047 * derived from FTP,
048 * implements all the functionality required of an FTP client.  The
049 * FTP class is made public to provide access to various FTP constants
050 * and to make it easier for adventurous programmers (or those with
051 * special needs) to interact with the FTP protocol and implement their
052 * own clients.  A set of methods with names corresponding to the FTP
053 * command names are provided to facilitate this interaction.
054 * <p>
055 * You should keep in mind that the FTP server may choose to prematurely
056 * close a connection if the client has been idle for longer than a
057 * given time period (usually 900 seconds).  The FTP class will detect a
058 * premature FTP server connection closing when it receives a
059 * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
060 *  response to a command.
061 * When that occurs, the FTP class method encountering that reply will throw
062 * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
063 * .  <code>FTPConectionClosedException</code>
064 * is a subclass of <code> IOException </code> and therefore need not be
065 * caught separately, but if you are going to catch it separately, its
066 * catch block must appear before the more general <code> IOException </code>
067 * catch block.  When you encounter an
068 * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
069 * , you must disconnect the connection with
070 * {@link #disconnect  disconnect() } to properly clean up the
071 * system resources used by FTP.  Before disconnecting, you may check the
072 * last reply code and text with
073 * {@link #getReplyCode  getReplyCode },
074 * {@link #getReplyString  getReplyString },
075 * and {@link #getReplyStrings  getReplyStrings}.
076 * You may avoid server disconnections while the client is idle by
077 * periodicaly sending NOOP commands to the server.
078 * <p>
079 * Rather than list it separately for each method, we mention here that
080 * every method communicating with the server and throwing an IOException
081 * can also throw a
082 * {@link org.apache.commons.net.MalformedServerReplyException}
083 * , which is a subclass
084 * of IOException.  A MalformedServerReplyException will be thrown when
085 * the reply received from the server deviates enough from the protocol
086 * specification that it cannot be interpreted in a useful manner despite
087 * attempts to be as lenient as possible.
088 *
089 * @see FTPClient
090 * @see FTPConnectionClosedException
091 * @see org.apache.commons.net.MalformedServerReplyException
092 ***/
093
094public class FTP extends SocketClient
095{
096    /*** The default FTP data port (20). ***/
097    public static final int DEFAULT_DATA_PORT = 20;
098    /*** The default FTP control port (21). ***/
099    public static final int DEFAULT_PORT = 21;
100
101    /***
102     * A constant used to indicate the file(s) being transferred should
103     * be treated as ASCII.  This is the default file type.  All constants
104     * ending in <code>FILE_TYPE</code> are used to indicate file types.
105     ***/
106    public static final int ASCII_FILE_TYPE = 0;
107
108    /***
109     * A constant used to indicate the file(s) being transferred should
110     * be treated as EBCDIC.  Note however that there are several different
111     * EBCDIC formats.  All constants ending in <code>FILE_TYPE</code>
112     * are used to indicate file types.
113     ***/
114    public static final int EBCDIC_FILE_TYPE = 1;
115
116
117    /***
118     * A constant used to indicate the file(s) being transferred should
119     * be treated as a binary image, i.e., no translations should be
120     * performed.  All constants ending in <code>FILE_TYPE</code> are used to
121     * indicate file types.
122     ***/
123    public static final int BINARY_FILE_TYPE = 2;
124
125    /***
126     * A constant used to indicate the file(s) being transferred should
127     * be treated as a local type.  All constants ending in
128     * <code>FILE_TYPE</code> are used to indicate file types.
129     ***/
130    public static final int LOCAL_FILE_TYPE = 3;
131
132    /***
133     * A constant used for text files to indicate a non-print text format.
134     * This is the default format.
135     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
136     * text formatting for text transfers (both ASCII and EBCDIC).
137     ***/
138    public static final int NON_PRINT_TEXT_FORMAT = 4;
139
140    /***
141     * A constant used to indicate a text file contains format vertical format
142     * control characters.
143     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
144     * text formatting for text transfers (both ASCII and EBCDIC).
145     ***/
146    public static final int TELNET_TEXT_FORMAT = 5;
147
148    /***
149     * A constant used to indicate a text file contains ASA vertical format
150     * control characters.
151     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
152     * text formatting for text transfers (both ASCII and EBCDIC).
153     ***/
154    public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
155
156    /***
157     * A constant used to indicate a file is to be treated as a continuous
158     * sequence of bytes.  This is the default structure.  All constants ending
159     * in <code>_STRUCTURE</code> are used to indicate file structure for
160     * file transfers.
161     ***/
162    public static final int FILE_STRUCTURE = 7;
163
164    /***
165     * A constant used to indicate a file is to be treated as a sequence
166     * of records.  All constants ending in <code>_STRUCTURE</code>
167     * are used to indicate file structure for file transfers.
168     ***/
169    public static final int RECORD_STRUCTURE = 8;
170
171    /***
172     * A constant used to indicate a file is to be treated as a set of
173     * independent indexed pages.  All constants ending in
174     * <code>_STRUCTURE</code> are used to indicate file structure for file
175     * transfers.
176     ***/
177    public static final int PAGE_STRUCTURE = 9;
178
179    /***
180     * A constant used to indicate a file is to be transferred as a stream
181     * of bytes.  This is the default transfer mode.  All constants ending
182     * in <code>TRANSFER_MODE</code> are used to indicate file transfer
183     * modes.
184     ***/
185    public static final int STREAM_TRANSFER_MODE = 10;
186
187    /***
188     * A constant used to indicate a file is to be transferred as a series
189     * of blocks.  All constants ending in <code>TRANSFER_MODE</code> are used
190     * to indicate file transfer modes.
191     ***/
192    public static final int BLOCK_TRANSFER_MODE = 11;
193
194    /***
195     * A constant used to indicate a file is to be transferred as FTP
196     * compressed data.  All constants ending in <code>TRANSFER_MODE</code>
197     * are used to indicate file transfer modes.
198     ***/
199    public static final int COMPRESSED_TRANSFER_MODE = 12;
200
201    // We have to ensure that the protocol communication is in ASCII
202    // but we use ISO-8859-1 just in case 8-bit characters cross
203    // the wire.
204    /**
205     * The default character encoding used for communicating over an
206     * FTP control connection.  The default encoding is an
207     * ASCII-compatible encoding.  Some FTP servers expect other
208     * encodings.  You can change the encoding used by an FTP instance
209     * with {@link #setControlEncoding setControlEncoding}.
210     */
211    public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1";
212
213    /** Length of the FTP reply code (3 alphanumerics) */
214    public static final int REPLY_CODE_LEN = 3;
215
216    private static final String __modes = "AEILNTCFRPSBC";
217
218    protected int _replyCode;
219    protected ArrayList<String> _replyLines;
220    protected boolean _newReplyString;
221    protected String _replyString;
222    protected String _controlEncoding;
223
224    /**
225     * A ProtocolCommandSupport object used to manage the registering of
226     * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
227     */
228    protected ProtocolCommandSupport _commandSupport_;
229
230    /**
231     * This is used to signal whether a block of multiline responses beginning
232     * with xxx must be terminated by the same numeric code xxx
233     * See section 4.2 of RFC 959 for details.
234     */
235    protected boolean strictMultilineParsing = false;
236
237    /**
238     * If this is true, then non-multiline replies must have the format:
239     * 3 digit code <space> <text>
240     * If false, then the 3 digit code does not have to be followed by space
241     * See section 4.2 of RFC 959 for details.
242     */
243    private boolean strictReplyParsing = true;
244
245    /**
246     * Wraps SocketClient._input_ to facilitate the reading of text
247     * from the FTP control connection.  Do not access the control
248     * connection via SocketClient._input_.  This member starts
249     * with a null value, is initialized in {@link #_connectAction_},
250     * and set to null in {@link #disconnect}.
251     */
252    protected BufferedReader _controlInput_;
253
254    /**
255     * Wraps SocketClient._output_ to facilitate the writing of text
256     * to the FTP control connection.  Do not access the control
257     * connection via SocketClient._output_.  This member starts
258     * with a null value, is initialized in {@link #_connectAction_},
259     * and set to null in {@link #disconnect}.
260     */
261    protected BufferedWriter _controlOutput_;
262
263    /***
264     * The default FTP constructor.  Sets the default port to
265     * <code>DEFAULT_PORT</code> and initializes internal data structures
266     * for saving FTP reply information.
267     ***/
268    public FTP()
269    {
270        super();
271        setDefaultPort(DEFAULT_PORT);
272        _replyLines = new ArrayList<String>();
273        _newReplyString = false;
274        _replyString = null;
275        _controlEncoding = DEFAULT_CONTROL_ENCODING;
276        _commandSupport_ = new ProtocolCommandSupport(this);
277    }
278
279    // The RFC-compliant multiline termination check
280    private boolean __strictCheck(String line, String code) {
281        return (!(line.startsWith(code) && line.charAt(REPLY_CODE_LEN) == ' '));
282    }
283
284    // The strict check is too strong a condition because of non-conforming ftp
285    // servers like ftp.funet.fi which sent 226 as the last line of a
286    // 426 multi-line reply in response to ls /.  We relax the condition to
287    // test that the line starts with a digit rather than starting with
288    // the code.
289    private boolean __lenientCheck(String line) {
290        return (!(line.length() > REPLY_CODE_LEN&& line.charAt(REPLY_CODE_LEN) != '-' &&
291                Character.isDigit(line.charAt(0))));
292    }
293
294    /**
295     * Get the reply, and pass it to command listeners
296     */
297    private void __getReply()  throws IOException
298    {
299        __getReply(true);
300    }
301
302    /**
303     * Get the reply, but don't pass it to command listeners.
304     * Used for keep-alive processing only.
305     * @since 3.0
306     * @throws IOException on error
307     */
308    protected void __getReplyNoReport()  throws IOException
309    {
310        __getReply(false);
311    }
312
313    private void __getReply(boolean reportReply) throws IOException
314    {
315        int length;
316
317        _newReplyString = true;
318        _replyLines.clear();
319
320        String line = _controlInput_.readLine();
321
322        if (line == null) {
323            throw new FTPConnectionClosedException(
324                    "Connection closed without indication.");
325        }
326
327        // In case we run into an anomaly we don't want fatal index exceptions
328        // to be thrown.
329        length = line.length();
330        if (length < REPLY_CODE_LEN) {
331            throw new MalformedServerReplyException(
332                "Truncated server reply: " + line);
333        }
334
335        String code = null;
336        try
337        {
338            code = line.substring(0, REPLY_CODE_LEN);
339            _replyCode = Integer.parseInt(code);
340        }
341        catch (NumberFormatException e)
342        {
343            throw new MalformedServerReplyException(
344                "Could not parse response code.\nServer Reply: " + line);
345        }
346
347        _replyLines.add(line);
348
349        // Check the server reply type
350        if (length > REPLY_CODE_LEN) {
351            char sep = line.charAt(REPLY_CODE_LEN);
352            // Get extra lines if message continues.
353            if (sep == '-') {
354                do
355                {
356                    line = _controlInput_.readLine();
357
358                    if (line == null) {
359                        throw new FTPConnectionClosedException(
360                            "Connection closed without indication.");
361                    }
362
363                    _replyLines.add(line);
364
365                    // The length() check handles problems that could arise from readLine()
366                    // returning too soon after encountering a naked CR or some other
367                    // anomaly.
368                }
369                while ( isStrictMultilineParsing() ? __strictCheck(line, code) : __lenientCheck(line));
370
371            } else if (isStrictReplyParsing()) {
372                if (length == REPLY_CODE_LEN + 1) { // expecting some text
373                    throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
374                } else if (sep != ' ') {
375                    throw new MalformedServerReplyException("Invalid server reply: '" + line +"'");
376                }
377            }
378        } else if (isStrictReplyParsing()) {
379            throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
380        }
381
382        if (reportReply) {
383            fireReplyReceived(_replyCode, getReplyString());
384        }
385
386        if (_replyCode == FTPReply.SERVICE_NOT_AVAILABLE) {
387            throw new FTPConnectionClosedException("FTP response 421 received.  Server closed connection.");
388        }
389    }
390
391    /**
392     * Initiates control connections and gets initial reply.
393     * Initializes {@link #_controlInput_} and {@link #_controlOutput_}.
394     */
395    @Override
396    protected void _connectAction_() throws IOException
397    {
398        _connectAction_(null);
399    }
400
401
402    /**
403     * Initiates control connections and gets initial reply.
404     * Initializes {@link #_controlInput_} and {@link #_controlOutput_}.
405     *
406     * @param socketIsReader the reader to reuse (if non-null)
407     * @throws IOException on error
408     * @since 3.4
409     */
410    protected void _connectAction_(Reader socketIsReader) throws IOException {
411        super._connectAction_(); // sets up _input_ and _output_
412        if(socketIsReader == null) {
413            _controlInput_ =
414                    new CRLFLineReader(new InputStreamReader(_input_, getControlEncoding()));
415        } else {
416            _controlInput_ = new CRLFLineReader(socketIsReader);
417        }
418        _controlOutput_ =
419            new BufferedWriter(new OutputStreamWriter(_output_, getControlEncoding()));
420        if (connectTimeout > 0) { // NET-385
421            int original = _socket_.getSoTimeout();
422            _socket_.setSoTimeout(connectTimeout);
423            try {
424                __getReply();
425                // If we received code 120, we have to fetch completion reply.
426                if (FTPReply.isPositivePreliminary(_replyCode)) {
427                    __getReply();
428                }
429            } catch (SocketTimeoutException e) {
430                IOException ioe = new IOException("Timed out waiting for initial connect reply");
431                ioe.initCause(e);
432                throw ioe;
433            } finally {
434                _socket_.setSoTimeout(original);
435            }
436        } else {
437            __getReply();
438            // If we received code 120, we have to fetch completion reply.
439            if (FTPReply.isPositivePreliminary(_replyCode)) {
440                __getReply();
441            }
442        }
443    }
444
445
446    /**
447     * Saves the character encoding to be used by the FTP control connection.
448     * Some FTP servers require that commands be issued in a non-ASCII
449     * encoding like UTF-8 so that file names with multi-byte character
450     * representations (e.g, Big 8) can be specified.
451     * <p>
452     * Please note that this has to be set before the connection is established.
453     *
454     * @param encoding The new character encoding for the control connection.
455     */
456    public void setControlEncoding(String encoding) {
457        _controlEncoding = encoding;
458    }
459
460
461    /**
462     * @return The character encoding used to communicate over the
463     * control connection.
464     */
465    public String getControlEncoding() {
466        return _controlEncoding;
467    }
468
469
470    /***
471     * Closes the control connection to the FTP server and sets to null
472     * some internal data so that the memory may be reclaimed by the
473     * garbage collector.  The reply text and code information from the
474     * last command is voided so that the memory it used may be reclaimed.
475     * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
476     *
477     * @throws IOException If an error occurs while disconnecting.
478     ***/
479    @Override
480    public void disconnect() throws IOException
481    {
482        super.disconnect();
483        _controlInput_ = null;
484        _controlOutput_ = null;
485        _newReplyString = false;
486        _replyString = null;
487    }
488
489
490    /***
491     * Sends an FTP command to the server, waits for a reply and returns the
492     * numerical response code.  After invocation, for more detailed
493     * information, the actual reply text can be accessed by calling
494     * {@link #getReplyString  getReplyString } or
495     * {@link #getReplyStrings  getReplyStrings }.
496     *
497     * @param command  The text representation of the  FTP command to send.
498     * @param args The arguments to the FTP command.  If this parameter is
499     *             set to null, then the command is sent with no argument.
500     * @return The integer value of the FTP reply code returned by the server
501     *         in response to the command.
502     * @throws FTPConnectionClosedException
503     *      If the FTP server prematurely closes the connection as a result
504     *      of the client being idle or some other reason causing the server
505     *      to send FTP reply code 421.  This exception may be caught either
506     *      as an IOException or independently as itself.
507     * @throws IOException  If an I/O error occurs while either sending the
508     *      command or receiving the server reply.
509     ***/
510    public int sendCommand(String command, String args) throws IOException
511    {
512        if (_controlOutput_ == null) {
513            throw new IOException("Connection is not open");
514        }
515
516        final String message = __buildMessage(command, args);
517
518        __send(message);
519
520        fireCommandSent(command, message);
521
522        __getReply();
523        return _replyCode;
524    }
525
526    private String __buildMessage(String command, String args) {
527        final StringBuilder __commandBuffer = new StringBuilder();
528
529        __commandBuffer.append(command);
530
531        if (args != null)
532        {
533            __commandBuffer.append(' ');
534            __commandBuffer.append(args);
535        }
536        __commandBuffer.append(SocketClient.NETASCII_EOL);
537        return __commandBuffer.toString();
538    }
539
540    private void __send(String message) throws IOException,
541            FTPConnectionClosedException, SocketException {
542        try{
543            _controlOutput_.write(message);
544            _controlOutput_.flush();
545        }
546        catch (SocketException e)
547        {
548            if (!isConnected())
549            {
550                throw new FTPConnectionClosedException("Connection unexpectedly closed.");
551            }
552            else
553            {
554                throw e;
555            }
556        }
557    }
558
559    /**
560     * Send a noop and get the reply without reporting to the command listener.
561     * Intended for use with keep-alive.
562     *
563     * @throws IOException on error
564     * @since 3.0
565     */
566    protected void __noop() throws IOException {
567        String msg = __buildMessage(FTPCmd.NOOP.getCommand(), null);
568        __send(msg);
569        __getReplyNoReport(); // This may timeout
570    }
571
572    /***
573     * Sends an FTP command to the server, waits for a reply and returns the
574     * numerical response code.  After invocation, for more detailed
575     * information, the actual reply text can be accessed by calling
576     * {@link #getReplyString  getReplyString } or
577     * {@link #getReplyStrings  getReplyStrings }.
578     *
579     * @param command  The FTPCommand constant corresponding to the FTP command
580     *                 to send.
581     * @param args The arguments to the FTP command.  If this parameter is
582     *             set to null, then the command is sent with no argument.
583     * @return The integer value of the FTP reply code returned by the server
584     *         in response to the command.
585     * @throws FTPConnectionClosedException
586     *      If the FTP server prematurely closes the connection as a result
587     *      of the client being idle or some other reason causing the server
588     *      to send FTP reply code 421.  This exception may be caught either
589     *      as an IOException or independently as itself.
590     * @throws IOException  If an I/O error occurs while either sending the
591     *      command or receiving the server reply.
592     * @deprecated (3.3) Use {@link #sendCommand(FTPCmd, String)} instead
593     ***/
594    @Deprecated
595    public int sendCommand(int command, String args) throws IOException
596    {
597        return sendCommand(FTPCommand.getCommand(command), args);
598    }
599
600    /**
601     * Sends an FTP command to the server, waits for a reply and returns the
602     * numerical response code.  After invocation, for more detailed
603     * information, the actual reply text can be accessed by calling
604     * {@link #getReplyString  getReplyString } or
605     * {@link #getReplyStrings  getReplyStrings }.
606     *
607     * @param command  The FTPCmd enum corresponding to the FTP command
608     *                 to send.
609     * @return The integer value of the FTP reply code returned by the server
610     *         in response to the command.
611     * @throws FTPConnectionClosedException
612     *      If the FTP server prematurely closes the connection as a result
613     *      of the client being idle or some other reason causing the server
614     *      to send FTP reply code 421.  This exception may be caught either
615     *      as an IOException or independently as itself.
616     * @throws IOException  If an I/O error occurs while either sending the
617     *      command or receiving the server reply.
618     * @since 3.3
619     */
620    public int sendCommand(FTPCmd command)  throws IOException{
621        return sendCommand(command, null);
622    }
623
624    /**
625     * Sends an FTP command to the server, waits for a reply and returns the
626     * numerical response code.  After invocation, for more detailed
627     * information, the actual reply text can be accessed by calling
628     * {@link #getReplyString  getReplyString } or
629     * {@link #getReplyStrings  getReplyStrings }.
630     *
631     * @param command  The FTPCmd enum corresponding to the FTP command
632     *                 to send.
633     * @param args The arguments to the FTP command.  If this parameter is
634     *             set to null, then the command is sent with no argument.
635     * @return The integer value of the FTP reply code returned by the server
636     *         in response to the command.
637     * @throws FTPConnectionClosedException
638     *      If the FTP server prematurely closes the connection as a result
639     *      of the client being idle or some other reason causing the server
640     *      to send FTP reply code 421.  This exception may be caught either
641     *      as an IOException or independently as itself.
642     * @throws IOException  If an I/O error occurs while either sending the
643     *      command or receiving the server reply.
644     * @since 3.3
645     */
646    public int sendCommand(FTPCmd command, String args)  throws IOException{
647        return sendCommand(command.getCommand(), args);
648    }
649
650    /***
651     * Sends an FTP command with no arguments to the server, waits for a
652     * reply and returns the numerical response code.  After invocation, for
653     * more detailed information, the actual reply text can be accessed by
654     * calling {@link #getReplyString  getReplyString } or
655     * {@link #getReplyStrings  getReplyStrings }.
656     *
657     * @param command  The text representation of the  FTP command to send.
658     * @return The integer value of the FTP reply code returned by the server
659     *         in response to the command.
660     * @throws FTPConnectionClosedException
661     *      If the FTP server prematurely closes the connection as a result
662     *      of the client being idle or some other reason causing the server
663     *      to send FTP reply code 421.  This exception may be caught either
664     *      as an IOException or independently as itself.
665     * @throws IOException  If an I/O error occurs while either sending the
666     *      command or receiving the server reply.
667     ***/
668    public int sendCommand(String command) throws IOException
669    {
670        return sendCommand(command, null);
671    }
672
673
674    /***
675     * Sends an FTP command with no arguments to the server, waits for a
676     * reply and returns the numerical response code.  After invocation, for
677     * more detailed information, the actual reply text can be accessed by
678     * calling {@link #getReplyString  getReplyString } or
679     * {@link #getReplyStrings  getReplyStrings }.
680     *
681     * @param command  The FTPCommand constant corresponding to the FTP command
682     *                 to send.
683     * @return The integer value of the FTP reply code returned by the server
684     *         in response to the command.
685     * @throws FTPConnectionClosedException
686     *      If the FTP server prematurely closes the connection as a result
687     *      of the client being idle or some other reason causing the server
688     *      to send FTP reply code 421.  This exception may be caught either
689     *      as an IOException or independently as itself.
690     * @throws IOException  If an I/O error occurs while either sending the
691     *      command or receiving the server reply.
692     ***/
693    public int sendCommand(int command) throws IOException
694    {
695        return sendCommand(command, null);
696    }
697
698
699    /***
700     * Returns the integer value of the reply code of the last FTP reply.
701     * You will usually only use this method after you connect to the
702     * FTP server to check that the connection was successful since
703     * <code> connect </code> is of type void.
704     *
705     * @return The integer value of the reply code of the last FTP reply.
706     ***/
707    public int getReplyCode()
708    {
709        return _replyCode;
710    }
711
712    /***
713     * Fetches a reply from the FTP server and returns the integer reply
714     * code.  After calling this method, the actual reply text can be accessed
715     * from either  calling {@link #getReplyString  getReplyString } or
716     * {@link #getReplyStrings  getReplyStrings }.  Only use this
717     * method if you are implementing your own FTP client or if you need to
718     * fetch a secondary response from the FTP server.
719     *
720     * @return The integer value of the reply code of the fetched FTP reply.
721     * @throws FTPConnectionClosedException
722     *      If the FTP server prematurely closes the connection as a result
723     *      of the client being idle or some other reason causing the server
724     *      to send FTP reply code 421.  This exception may be caught either
725     *      as an IOException or independently as itself.
726     * @throws IOException  If an I/O error occurs while receiving the
727     *                         server reply.
728     ***/
729    public int getReply() throws IOException
730    {
731        __getReply();
732        return _replyCode;
733    }
734
735
736    /***
737     * Returns the lines of text from the last FTP server response as an array
738     * of strings, one entry per line.  The end of line markers of each are
739     * stripped from each line.
740     *
741     * @return The lines of text from the last FTP response as an array.
742     ***/
743    public String[] getReplyStrings()
744    {
745        return _replyLines.toArray(new String[_replyLines.size()]);
746    }
747
748    /***
749     * Returns the entire text of the last FTP server response exactly
750     * as it was received, including all end of line markers in NETASCII
751     * format.
752     *
753     * @return The entire text from the last FTP response as a String.
754     ***/
755    public String getReplyString()
756    {
757        StringBuilder buffer;
758
759        if (!_newReplyString) {
760            return _replyString;
761        }
762
763        buffer = new StringBuilder(256);
764
765        for (String line : _replyLines) {
766                buffer.append(line);
767                buffer.append(SocketClient.NETASCII_EOL);
768        }
769
770         _newReplyString = false;
771
772        return (_replyString = buffer.toString());
773    }
774
775
776    /***
777     * A convenience method to send the FTP USER command to the server,
778     * receive the reply, and return the reply code.
779     *
780     * @param username  The username to login under.
781     * @return The reply code received from the server.
782     * @throws FTPConnectionClosedException
783     *      If the FTP server prematurely closes the connection as a result
784     *      of the client being idle or some other reason causing the server
785     *      to send FTP reply code 421.  This exception may be caught either
786     *      as an IOException or independently as itself.
787     * @throws IOException  If an I/O error occurs while either sending the
788     *      command or receiving the server reply.
789     ***/
790    public int user(String username) throws IOException
791    {
792        return sendCommand(FTPCmd.USER, username);
793    }
794
795    /**
796     * A convenience method to send the FTP PASS command to the server,
797     * receive the reply, and return the reply code.
798     * @param password The plain text password of the username being logged into.
799     * @return The reply code received from the server.
800     * @throws FTPConnectionClosedException
801     *      If the FTP server prematurely closes the connection as a result
802     *      of the client being idle or some other reason causing the server
803     *      to send FTP reply code 421.  This exception may be caught either
804     *      as an IOException or independently as itself.
805     * @throws IOException  If an I/O error occurs while either sending the
806     *      command or receiving the server reply.
807     */
808    public int pass(String password) throws IOException
809    {
810        return sendCommand(FTPCmd.PASS, password);
811    }
812
813    /***
814     * A convenience method to send the FTP ACCT command to the server,
815     * receive the reply, and return the reply code.
816     *
817     * @param account  The account name to access.
818     * @return The reply code received from the server.
819     * @throws FTPConnectionClosedException
820     *      If the FTP server prematurely closes the connection as a result
821     *      of the client being idle or some other reason causing the server
822     *      to send FTP reply code 421.  This exception may be caught either
823     *      as an IOException or independently as itself.
824     * @throws IOException  If an I/O error occurs while either sending the
825     *      command or receiving the server reply.
826     ***/
827    public int acct(String account) throws IOException
828    {
829        return sendCommand(FTPCmd.ACCT, account);
830    }
831
832
833    /***
834     * A convenience method to send the FTP ABOR command to the server,
835     * receive the reply, and return the reply code.
836     *
837     * @return The reply code received from the server.
838     * @throws FTPConnectionClosedException
839     *      If the FTP server prematurely closes the connection as a result
840     *      of the client being idle or some other reason causing the server
841     *      to send FTP reply code 421.  This exception may be caught either
842     *      as an IOException or independently as itself.
843     * @throws IOException  If an I/O error occurs while either sending the
844     *      command or receiving the server reply.
845     ***/
846    public int abor() throws IOException
847    {
848        return sendCommand(FTPCmd.ABOR);
849    }
850
851    /***
852     * A convenience method to send the FTP CWD command to the server,
853     * receive the reply, and return the reply code.
854     *
855     * @param directory The new working directory.
856     * @return The reply code received from the server.
857     * @throws FTPConnectionClosedException
858     *      If the FTP server prematurely closes the connection as a result
859     *      of the client being idle or some other reason causing the server
860     *      to send FTP reply code 421.  This exception may be caught either
861     *      as an IOException or independently as itself.
862     * @throws IOException  If an I/O error occurs while either sending the
863     *      command or receiving the server reply.
864     ***/
865    public int cwd(String directory) throws IOException
866    {
867        return sendCommand(FTPCmd.CWD, directory);
868    }
869
870    /***
871     * A convenience method to send the FTP CDUP command to the server,
872     * receive the reply, and return the reply code.
873     *
874     * @return The reply code received from the server.
875     * @throws FTPConnectionClosedException
876     *      If the FTP server prematurely closes the connection as a result
877     *      of the client being idle or some other reason causing the server
878     *      to send FTP reply code 421.  This exception may be caught either
879     *      as an IOException or independently as itself.
880     * @throws IOException  If an I/O error occurs while either sending the
881     *      command or receiving the server reply.
882     ***/
883    public int cdup() throws IOException
884    {
885        return sendCommand(FTPCmd.CDUP);
886    }
887
888    /***
889     * A convenience method to send the FTP QUIT command to the server,
890     * receive the reply, and return the reply code.
891     *
892     * @return The reply code received from the server.
893     * @throws FTPConnectionClosedException
894     *      If the FTP server prematurely closes the connection as a result
895     *      of the client being idle or some other reason causing the server
896     *      to send FTP reply code 421.  This exception may be caught either
897     *      as an IOException or independently as itself.
898     * @throws IOException  If an I/O error occurs while either sending the
899     *      command or receiving the server reply.
900     ***/
901    public int quit() throws IOException
902    {
903        return sendCommand(FTPCmd.QUIT);
904    }
905
906    /***
907     * A convenience method to send the FTP REIN command to the server,
908     * receive the reply, and return the reply code.
909     *
910     * @return The reply code received from the server.
911     * @throws FTPConnectionClosedException
912     *      If the FTP server prematurely closes the connection as a result
913     *      of the client being idle or some other reason causing the server
914     *      to send FTP reply code 421.  This exception may be caught either
915     *      as an IOException or independently as itself.
916     * @throws IOException  If an I/O error occurs while either sending the
917     *      command or receiving the server reply.
918     ***/
919    public int rein() throws IOException
920    {
921        return sendCommand(FTPCmd.REIN);
922    }
923
924    /***
925     * A convenience method to send the FTP SMNT command to the server,
926     * receive the reply, and return the reply code.
927     *
928     * @param dir  The directory name.
929     * @return The reply code received from the server.
930     * @throws FTPConnectionClosedException
931     *      If the FTP server prematurely closes the connection as a result
932     *      of the client being idle or some other reason causing the server
933     *      to send FTP reply code 421.  This exception may be caught either
934     *      as an IOException or independently as itself.
935     * @throws IOException  If an I/O error occurs while either sending the
936     *      command or receiving the server reply.
937     ***/
938    public int smnt(String dir) throws IOException
939    {
940        return sendCommand(FTPCmd.SMNT, dir);
941    }
942
943    /***
944     * A convenience method to send the FTP PORT command to the server,
945     * receive the reply, and return the reply code.
946     *
947     * @param host  The host owning the port.
948     * @param port  The new port.
949     * @return The reply code received from the server.
950     * @throws FTPConnectionClosedException
951     *      If the FTP server prematurely closes the connection as a result
952     *      of the client being idle or some other reason causing the server
953     *      to send FTP reply code 421.  This exception may be caught either
954     *      as an IOException or independently as itself.
955     * @throws IOException  If an I/O error occurs while either sending the
956     *      command or receiving the server reply.
957     ***/
958    public int port(InetAddress host, int port) throws IOException
959    {
960        int num;
961        StringBuilder info = new StringBuilder(24);
962
963        info.append(host.getHostAddress().replace('.', ','));
964        num = port >>> 8;
965        info.append(',');
966        info.append(num);
967        info.append(',');
968        num = port & 0xff;
969        info.append(num);
970
971        return sendCommand(FTPCmd.PORT, info.toString());
972    }
973
974    /***
975     * A convenience method to send the FTP EPRT command to the server,
976     * receive the reply, and return the reply code.
977     *
978     * Examples:
979     * <ul>
980     * <li>EPRT |1|132.235.1.2|6275|</li>
981     * <li>EPRT |2|1080::8:800:200C:417A|5282|</li>
982     * </ul>
983     *
984     * @see "http://www.faqs.org/rfcs/rfc2428.html"
985     *
986     * @param host  The host owning the port.
987     * @param port  The new port.
988     * @return The reply code received from the server.
989     * @throws FTPConnectionClosedException
990     *      If the FTP server prematurely closes the connection as a result
991     *      of the client being idle or some other reason causing the server
992     *      to send FTP reply code 421.  This exception may be caught either
993     *      as an IOException or independently as itself.
994     * @throws IOException  If an I/O error occurs while either sending the
995     *      command or receiving the server reply.
996     * @since 2.2
997     ***/
998    public int eprt(InetAddress host, int port) throws IOException
999    {
1000        int num;
1001        StringBuilder info = new StringBuilder();
1002        String h;
1003
1004        // If IPv6, trim the zone index
1005        h = host.getHostAddress();
1006        num = h.indexOf('%');
1007        if (num > 0) {
1008            h = h.substring(0, num);
1009        }
1010
1011        info.append("|");
1012
1013        if (host instanceof Inet4Address) {
1014            info.append("1");
1015        } else if (host instanceof Inet6Address) {
1016            info.append("2");
1017        }
1018        info.append("|");
1019        info.append(h);
1020        info.append("|");
1021        info.append(port);
1022        info.append("|");
1023
1024        return sendCommand(FTPCmd.EPRT, info.toString());
1025    }
1026
1027    /***
1028     * A convenience method to send the FTP PASV command to the server,
1029     * receive the reply, and return the reply code.  Remember, it's up
1030     * to you to interpret the reply string containing the host/port
1031     * information.
1032     *
1033     * @return The reply code received from the server.
1034     * @throws FTPConnectionClosedException
1035     *      If the FTP server prematurely closes the connection as a result
1036     *      of the client being idle or some other reason causing the server
1037     *      to send FTP reply code 421.  This exception may be caught either
1038     *      as an IOException or independently as itself.
1039     * @throws IOException  If an I/O error occurs while either sending the
1040     *      command or receiving the server reply.
1041     ***/
1042    public int pasv() throws IOException
1043    {
1044        return sendCommand(FTPCmd.PASV);
1045    }
1046
1047     /***
1048     * A convenience method to send the FTP EPSV command to the server,
1049     * receive the reply, and return the reply code.  Remember, it's up
1050     * to you to interpret the reply string containing the host/port
1051     * information.
1052     *
1053     * @return The reply code received from the server.
1054     * @throws FTPConnectionClosedException
1055     *      If the FTP server prematurely closes the connection as a result
1056     *      of the client being idle or some other reason causing the server
1057     *      to send FTP reply code 421.  This exception may be caught either
1058     *      as an IOException or independently as itself.
1059     * @throws IOException  If an I/O error occurs while either sending the
1060     *      command or receiving the server reply.
1061     * @since 2.2
1062     ***/
1063    public int epsv() throws IOException
1064    {
1065        return sendCommand(FTPCmd.EPSV);
1066    }
1067
1068    /**
1069     * A convenience method to send the FTP TYPE command for text files
1070     * to the server, receive the reply, and return the reply code.
1071     * @param fileType  The type of the file (one of the <code>FILE_TYPE</code>
1072     *              constants).
1073     * @param formatOrByteSize  The format of the file (one of the
1074     *              <code>_FORMAT</code> constants.  In the case of
1075     *              <code>LOCAL_FILE_TYPE</code>, the byte size.
1076     * @return The reply code received from the server.
1077     * @throws FTPConnectionClosedException
1078     *      If the FTP server prematurely closes the connection as a result
1079     *      of the client being idle or some other reason causing the server
1080     *      to send FTP reply code 421.  This exception may be caught either
1081     *      as an IOException or independently as itself.
1082     * @throws IOException  If an I/O error occurs while either sending the
1083     *      command or receiving the server reply.
1084     */
1085    public int type(int fileType, int formatOrByteSize) throws IOException
1086    {
1087        StringBuilder arg = new StringBuilder();
1088
1089        arg.append(__modes.charAt(fileType));
1090        arg.append(' ');
1091        if (fileType == LOCAL_FILE_TYPE) {
1092            arg.append(formatOrByteSize);
1093        } else {
1094            arg.append(__modes.charAt(formatOrByteSize));
1095        }
1096
1097        return sendCommand(FTPCmd.TYPE, arg.toString());
1098    }
1099
1100
1101    /**
1102     * A convenience method to send the FTP TYPE command to the server,
1103     * receive the reply, and return the reply code.
1104     *
1105     * @param fileType  The type of the file (one of the <code>FILE_TYPE</code>
1106     *              constants).
1107     * @return The reply code received from the server.
1108     * @throws FTPConnectionClosedException
1109     *      If the FTP server prematurely closes the connection as a result
1110     *      of the client being idle or some other reason causing the server
1111     *      to send FTP reply code 421.  This exception may be caught either
1112     *      as an IOException or independently as itself.
1113     * @throws IOException  If an I/O error occurs while either sending the
1114     *      command or receiving the server reply.
1115     */
1116    public int type(int fileType) throws IOException
1117    {
1118        return sendCommand(FTPCmd.TYPE,
1119                           __modes.substring(fileType, fileType + 1));
1120    }
1121
1122    /***
1123     * A convenience method to send the FTP STRU command to the server,
1124     * receive the reply, and return the reply code.
1125     *
1126     * @param structure  The structure of the file (one of the
1127     *         <code>_STRUCTURE</code> constants).
1128     * @return The reply code received from the server.
1129     * @throws FTPConnectionClosedException
1130     *      If the FTP server prematurely closes the connection as a result
1131     *      of the client being idle or some other reason causing the server
1132     *      to send FTP reply code 421.  This exception may be caught either
1133     *      as an IOException or independently as itself.
1134     * @throws IOException  If an I/O error occurs while either sending the
1135     *      command or receiving the server reply.
1136     ***/
1137    public int stru(int structure) throws IOException
1138    {
1139        return sendCommand(FTPCmd.STRU,
1140                           __modes.substring(structure, structure + 1));
1141    }
1142
1143    /***
1144     * A convenience method to send the FTP MODE command to the server,
1145     * receive the reply, and return the reply code.
1146     *
1147     * @param mode  The transfer mode to use (one of the
1148     *         <code>TRANSFER_MODE</code> constants).
1149     * @return The reply code received from the server.
1150     * @throws FTPConnectionClosedException
1151     *      If the FTP server prematurely closes the connection as a result
1152     *      of the client being idle or some other reason causing the server
1153     *      to send FTP reply code 421.  This exception may be caught either
1154     *      as an IOException or independently as itself.
1155     * @throws IOException  If an I/O error occurs while either sending the
1156     *      command or receiving the server reply.
1157     ***/
1158    public int mode(int mode) throws IOException
1159    {
1160        return sendCommand(FTPCmd.MODE,
1161                           __modes.substring(mode, mode + 1));
1162    }
1163
1164    /***
1165     * A convenience method to send the FTP RETR command to the server,
1166     * receive the reply, and return the reply code.  Remember, it is up
1167     * to you to manage the data connection.  If you don't need this low
1168     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1169     * , which will handle all low level details for you.
1170     *
1171     * @param pathname  The pathname of the file to retrieve.
1172     * @return The reply code received from the server.
1173     * @throws FTPConnectionClosedException
1174     *      If the FTP server prematurely closes the connection as a result
1175     *      of the client being idle or some other reason causing the server
1176     *      to send FTP reply code 421.  This exception may be caught either
1177     *      as an IOException or independently as itself.
1178     * @throws IOException  If an I/O error occurs while either sending the
1179     *      command or receiving the server reply.
1180     ***/
1181    public int retr(String pathname) throws IOException
1182    {
1183        return sendCommand(FTPCmd.RETR, pathname);
1184    }
1185
1186    /***
1187     * A convenience method to send the FTP STOR command to the server,
1188     * receive the reply, and return the reply code.  Remember, it is up
1189     * to you to manage the data connection.  If you don't need this low
1190     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1191     * , which will handle all low level details for you.
1192     *
1193     * @param pathname  The pathname to use for the file when stored at
1194     *                  the remote end of the transfer.
1195     * @return The reply code received from the server.
1196     * @throws FTPConnectionClosedException
1197     *      If the FTP server prematurely closes the connection as a result
1198     *      of the client being idle or some other reason causing the server
1199     *      to send FTP reply code 421.  This exception may be caught either
1200     *      as an IOException or independently as itself.
1201     * @throws IOException  If an I/O error occurs while either sending the
1202     *      command or receiving the server reply.
1203     ***/
1204    public int stor(String pathname) throws IOException
1205    {
1206        return sendCommand(FTPCmd.STOR, pathname);
1207    }
1208
1209    /***
1210     * A convenience method to send the FTP STOU command to the server,
1211     * receive the reply, and return the reply code.  Remember, it is up
1212     * to you to manage the data connection.  If you don't need this low
1213     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1214     * , which will handle all low level details for you.
1215     *
1216     * @return The reply code received from the server.
1217     * @throws FTPConnectionClosedException
1218     *      If the FTP server prematurely closes the connection as a result
1219     *      of the client being idle or some other reason causing the server
1220     *      to send FTP reply code 421.  This exception may be caught either
1221     *      as an IOException or independently as itself.
1222     * @throws IOException  If an I/O error occurs while either sending the
1223     *      command or receiving the server reply.
1224     ***/
1225    public int stou() throws IOException
1226    {
1227        return sendCommand(FTPCmd.STOU);
1228    }
1229
1230    /***
1231     * A convenience method to send the FTP STOU command to the server,
1232     * receive the reply, and return the reply code.  Remember, it is up
1233     * to you to manage the data connection.  If you don't need this low
1234     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1235     * , which will handle all low level details for you.
1236     * @param pathname  The base pathname to use for the file when stored at
1237     *                  the remote end of the transfer.  Some FTP servers
1238     *                  require this.
1239     * @return The reply code received from the server.
1240     * @throws FTPConnectionClosedException
1241     *      If the FTP server prematurely closes the connection as a result
1242     *      of the client being idle or some other reason causing the server
1243     *      to send FTP reply code 421.  This exception may be caught either
1244     *      as an IOException or independently as itself.
1245     * @throws IOException  If an I/O error occurs while either sending the
1246     *      command or receiving the server reply.
1247     */
1248    public int stou(String pathname) throws IOException
1249    {
1250        return sendCommand(FTPCmd.STOU, pathname);
1251    }
1252
1253    /***
1254     * A convenience method to send the FTP APPE command to the server,
1255     * receive the reply, and return the reply code.  Remember, it is up
1256     * to you to manage the data connection.  If you don't need this low
1257     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1258     * , which will handle all low level details for you.
1259     *
1260     * @param pathname  The pathname to use for the file when stored at
1261     *                  the remote end of the transfer.
1262     * @return The reply code received from the server.
1263     * @throws FTPConnectionClosedException
1264     *      If the FTP server prematurely closes the connection as a result
1265     *      of the client being idle or some other reason causing the server
1266     *      to send FTP reply code 421.  This exception may be caught either
1267     *      as an IOException or independently as itself.
1268     * @throws IOException  If an I/O error occurs while either sending the
1269     *      command or receiving the server reply.
1270     ***/
1271    public int appe(String pathname) throws IOException
1272    {
1273        return sendCommand(FTPCmd.APPE, pathname);
1274    }
1275
1276    /***
1277     * A convenience method to send the FTP ALLO command to the server,
1278     * receive the reply, and return the reply code.
1279     *
1280     * @param bytes The number of bytes to allocate.
1281     * @return The reply code received from the server.
1282     * @throws FTPConnectionClosedException
1283     *      If the FTP server prematurely closes the connection as a result
1284     *      of the client being idle or some other reason causing the server
1285     *      to send FTP reply code 421.  This exception may be caught either
1286     *      as an IOException or independently as itself.
1287     * @throws IOException  If an I/O error occurs while either sending the
1288     *      command or receiving the server reply.
1289     ***/
1290    public int allo(int bytes) throws IOException
1291    {
1292        return sendCommand(FTPCmd.ALLO, Integer.toString(bytes));
1293    }
1294
1295    /***
1296     * A convenience method to send the FTP ALLO command to the server,
1297     * receive the reply, and return the reply code.
1298     *
1299     * @param bytes The number of bytes to allocate.
1300     * @return The reply code received from the server.
1301     * @throws FTPConnectionClosedException
1302     *      If the FTP server prematurely closes the connection as a result
1303     *      of the client being idle or some other reason causing the server
1304     *      to send FTP reply code 421.  This exception may be caught either
1305     *      as an IOException or independently as itself.
1306     * @throws IOException  If an I/O error occurs while either sending the
1307     *      command or receiving the server reply.
1308     ***/
1309    public int allo(long bytes) throws IOException
1310    {
1311        return sendCommand(FTPCmd.ALLO, Long.toString(bytes));
1312    }
1313
1314    /**
1315     * A convenience method to send the FTP FEAT command to the server, receive the reply,
1316     * and return the reply code.
1317     * @return The reply code received by the server
1318     * @throws IOException  If an I/O error occurs while either sending the
1319     *      command or receiving the server reply.
1320     * @since 2.2
1321     */
1322    public int feat() throws IOException
1323    {
1324        return sendCommand(FTPCmd.FEAT);
1325    }
1326
1327    /***
1328     * A convenience method to send the FTP ALLO command to the server,
1329     * receive the reply, and return the reply code.
1330     *
1331     * @param bytes The number of bytes to allocate.
1332     * @param recordSize  The size of a record.
1333     * @return The reply code received from the server.
1334     * @throws FTPConnectionClosedException
1335     *      If the FTP server prematurely closes the connection as a result
1336     *      of the client being idle or some other reason causing the server
1337     *      to send FTP reply code 421.  This exception may be caught either
1338     *      as an IOException or independently as itself.
1339     * @throws IOException  If an I/O error occurs while either sending the
1340     *      command or receiving the server reply.
1341     ***/
1342    public int allo(int bytes, int recordSize) throws IOException
1343    {
1344        return sendCommand(FTPCmd.ALLO, Integer.toString(bytes) + " R " +
1345                           Integer.toString(recordSize));
1346    }
1347
1348    /***
1349     * A convenience method to send the FTP ALLO command to the server,
1350     * receive the reply, and return the reply code.
1351     *
1352     * @param bytes The number of bytes to allocate.
1353     * @param recordSize  The size of a record.
1354     * @return The reply code received from the server.
1355     * @throws FTPConnectionClosedException
1356     *      If the FTP server prematurely closes the connection as a result
1357     *      of the client being idle or some other reason causing the server
1358     *      to send FTP reply code 421.  This exception may be caught either
1359     *      as an IOException or independently as itself.
1360     * @throws IOException  If an I/O error occurs while either sending the
1361     *      command or receiving the server reply.
1362     ***/
1363    public int allo(long bytes, int recordSize) throws IOException
1364    {
1365        return sendCommand(FTPCmd.ALLO, Long.toString(bytes) + " R " +
1366                           Integer.toString(recordSize));
1367    }
1368
1369    /***
1370     * A convenience method to send the FTP REST command to the server,
1371     * receive the reply, and return the reply code.
1372     *
1373     * @param marker The marker at which to restart a transfer.
1374     * @return The reply code received from the server.
1375     * @throws FTPConnectionClosedException
1376     *      If the FTP server prematurely closes the connection as a result
1377     *      of the client being idle or some other reason causing the server
1378     *      to send FTP reply code 421.  This exception may be caught either
1379     *      as an IOException or independently as itself.
1380     * @throws IOException  If an I/O error occurs while either sending the
1381     *      command or receiving the server reply.
1382     ***/
1383    public int rest(String marker) throws IOException
1384    {
1385        return sendCommand(FTPCmd.REST, marker);
1386    }
1387
1388
1389    /**
1390     * @param file name of file
1391     * @return the status
1392     * @throws IOException on error
1393     * @since 2.0
1394     **/
1395    public int mdtm(String file) throws IOException
1396    {
1397        return sendCommand(FTPCmd.MDTM, file);
1398    }
1399
1400
1401    /**
1402     * A convenience method to send the FTP MFMT command to the server,
1403     * receive the reply, and return the reply code.
1404     *
1405     * @param pathname The pathname for which mtime is to be changed
1406     * @param timeval Timestamp in <code>YYYYMMDDhhmmss</code> format
1407     * @return The reply code received from the server.
1408     * @throws FTPConnectionClosedException
1409     *      If the FTP server prematurely closes the connection as a result
1410     *      of the client being idle or some other reason causing the server
1411     *      to send FTP reply code 421.  This exception may be caught either
1412     *      as an IOException or independently as itself.
1413     * @throws IOException  If an I/O error occurs while either sending the
1414     *      command or receiving the server reply.
1415     * @since 2.2
1416     * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
1417     **/
1418    public int mfmt(String pathname, String timeval) throws IOException
1419    {
1420        return sendCommand(FTPCmd.MFMT, timeval + " " + pathname);
1421    }
1422
1423
1424    /***
1425     * A convenience method to send the FTP RNFR command to the server,
1426     * receive the reply, and return the reply code.
1427     *
1428     * @param pathname The pathname to rename from.
1429     * @return The reply code received from the server.
1430     * @throws FTPConnectionClosedException
1431     *      If the FTP server prematurely closes the connection as a result
1432     *      of the client being idle or some other reason causing the server
1433     *      to send FTP reply code 421.  This exception may be caught either
1434     *      as an IOException or independently as itself.
1435     * @throws IOException  If an I/O error occurs while either sending the
1436     *      command or receiving the server reply.
1437     ***/
1438    public int rnfr(String pathname) throws IOException
1439    {
1440        return sendCommand(FTPCmd.RNFR, pathname);
1441    }
1442
1443    /***
1444     * A convenience method to send the FTP RNTO command to the server,
1445     * receive the reply, and return the reply code.
1446     *
1447     * @param pathname The pathname to rename to
1448     * @return The reply code received from the server.
1449     * @throws FTPConnectionClosedException
1450     *      If the FTP server prematurely closes the connection as a result
1451     *      of the client being idle or some other reason causing the server
1452     *      to send FTP reply code 421.  This exception may be caught either
1453     *      as an IOException or independently as itself.
1454     * @throws IOException  If an I/O error occurs while either sending the
1455     *      command or receiving the server reply.
1456     ***/
1457    public int rnto(String pathname) throws IOException
1458    {
1459        return sendCommand(FTPCmd.RNTO, pathname);
1460    }
1461
1462    /***
1463     * A convenience method to send the FTP DELE command to the server,
1464     * receive the reply, and return the reply code.
1465     *
1466     * @param pathname The pathname to delete.
1467     * @return The reply code received from the server.
1468     * @throws FTPConnectionClosedException
1469     *      If the FTP server prematurely closes the connection as a result
1470     *      of the client being idle or some other reason causing the server
1471     *      to send FTP reply code 421.  This exception may be caught either
1472     *      as an IOException or independently as itself.
1473     * @throws IOException  If an I/O error occurs while either sending the
1474     *      command or receiving the server reply.
1475     ***/
1476    public int dele(String pathname) throws IOException
1477    {
1478        return sendCommand(FTPCmd.DELE, pathname);
1479    }
1480
1481    /***
1482     * A convenience method to send the FTP RMD command to the server,
1483     * receive the reply, and return the reply code.
1484     *
1485     * @param pathname The pathname of the directory to remove.
1486     * @return The reply code received from the server.
1487     * @throws FTPConnectionClosedException
1488     *      If the FTP server prematurely closes the connection as a result
1489     *      of the client being idle or some other reason causing the server
1490     *      to send FTP reply code 421.  This exception may be caught either
1491     *      as an IOException or independently as itself.
1492     * @throws IOException  If an I/O error occurs while either sending the
1493     *      command or receiving the server reply.
1494     ***/
1495    public int rmd(String pathname) throws IOException
1496    {
1497        return sendCommand(FTPCmd.RMD, pathname);
1498    }
1499
1500    /***
1501     * A convenience method to send the FTP MKD command to the server,
1502     * receive the reply, and return the reply code.
1503     *
1504     * @param pathname The pathname of the new directory to create.
1505     * @return The reply code received from the server.
1506     * @throws FTPConnectionClosedException
1507     *      If the FTP server prematurely closes the connection as a result
1508     *      of the client being idle or some other reason causing the server
1509     *      to send FTP reply code 421.  This exception may be caught either
1510     *      as an IOException or independently as itself.
1511     * @throws IOException  If an I/O error occurs while either sending the
1512     *      command or receiving the server reply.
1513     ***/
1514    public int mkd(String pathname) throws IOException
1515    {
1516        return sendCommand(FTPCmd.MKD, pathname);
1517    }
1518
1519    /***
1520     * A convenience method to send the FTP PWD command to the server,
1521     * receive the reply, and return the reply code.
1522     *
1523     * @return The reply code received from the server.
1524     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
1530     *      command or receiving the server reply.
1531     ***/
1532    public int pwd() throws IOException
1533    {
1534        return sendCommand(FTPCmd.PWD);
1535    }
1536
1537    /***
1538     * A convenience method to send the FTP LIST command to the server,
1539     * receive the reply, and return the reply code.  Remember, it is up
1540     * to you to manage the data connection.  If you don't need this low
1541     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1542     * , which will handle all low level details for you.
1543     *
1544     * @return The reply code received from the server.
1545     * @throws FTPConnectionClosedException
1546     *      If the FTP server prematurely closes the connection as a result
1547     *      of the client being idle or some other reason causing the server
1548     *      to send FTP reply code 421.  This exception may be caught either
1549     *      as an IOException or independently as itself.
1550     * @throws IOException  If an I/O error occurs while either sending the
1551     *      command or receiving the server reply.
1552     ***/
1553    public int list() throws IOException
1554    {
1555        return sendCommand(FTPCmd.LIST);
1556    }
1557
1558    /***
1559     * A convenience method to send the FTP LIST command to the server,
1560     * receive the reply, and return the reply code.  Remember, it is up
1561     * to you to manage the data connection.  If you don't need this low
1562     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1563     * , which will handle all low level details for you.
1564     *
1565     * @param pathname  The pathname to list,
1566     * may be {@code null} in which case the command is sent with no parameters
1567     * @return The reply code received from the server.
1568     * @throws FTPConnectionClosedException
1569     *      If the FTP server prematurely closes the connection as a result
1570     *      of the client being idle or some other reason causing the server
1571     *      to send FTP reply code 421.  This exception may be caught either
1572     *      as an IOException or independently as itself.
1573     * @throws IOException  If an I/O error occurs while either sending the
1574     *      command or receiving the server reply.
1575     ***/
1576    public int list(String pathname) throws IOException
1577    {
1578        return sendCommand(FTPCmd.LIST, pathname);
1579    }
1580
1581    /**
1582     * A convenience method to send the FTP MLSD command to the server,
1583     * receive the reply, and return the reply code.  Remember, it is up
1584     * to you to manage the data connection.  If you don't need this low
1585     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1586     * , which will handle all low level details for you.
1587     *
1588     * @return The reply code received from the server.
1589     * @throws FTPConnectionClosedException
1590     *      If the FTP server prematurely closes the connection as a result
1591     *      of the client being idle or some other reason causing the server
1592     *      to send FTP reply code 421.  This exception may be caught either
1593     *      as an IOException or independently as itself.
1594     * @throws IOException  If an I/O error occurs while either sending the
1595     *      command or receiving the server reply.
1596     * @since 3.0
1597     */
1598    public int mlsd() throws IOException
1599    {
1600        return sendCommand(FTPCmd.MLSD);
1601    }
1602
1603    /**
1604     * A convenience method to send the FTP MLSD command to the server,
1605     * receive the reply, and return the reply code.  Remember, it is up
1606     * to you to manage the data connection.  If you don't need this low
1607     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1608     * , which will handle all low level details for you.
1609     *
1610     * @param path the path to report on
1611     * @return The reply code received from the server,
1612     * may be {@code null} in which case the command is sent with no parameters
1613     * @throws FTPConnectionClosedException
1614     *      If the FTP server prematurely closes the connection as a result
1615     *      of the client being idle or some other reason causing the server
1616     *      to send FTP reply code 421.  This exception may be caught either
1617     *      as an IOException or independently as itself.
1618     * @throws IOException  If an I/O error occurs while either sending the
1619     *      command or receiving the server reply.
1620     * @since 3.0
1621     */
1622    public int mlsd(String path) throws IOException
1623    {
1624        return sendCommand(FTPCmd.MLSD, path);
1625    }
1626
1627    /**
1628     * A convenience method to send the FTP MLST command to the server,
1629     * receive the reply, and return the reply code.  Remember, it is up
1630     * to you to manage the data connection.  If you don't need this low
1631     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1632     * , which will handle all low level details for you.
1633     *
1634     * @return The reply code received from the server.
1635     * @throws FTPConnectionClosedException
1636     *      If the FTP server prematurely closes the connection as a result
1637     *      of the client being idle or some other reason causing the server
1638     *      to send FTP reply code 421.  This exception may be caught either
1639     *      as an IOException or independently as itself.
1640     * @throws IOException  If an I/O error occurs while either sending the
1641     *      command or receiving the server reply.
1642     * @since 3.0
1643     */
1644    public int mlst() throws IOException
1645    {
1646        return sendCommand(FTPCmd.MLST);
1647    }
1648
1649    /**
1650     * A convenience method to send the FTP MLST command to the server,
1651     * receive the reply, and return the reply code.  Remember, it is up
1652     * to you to manage the data connection.  If you don't need this low
1653     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1654     * , which will handle all low level details for you.
1655     *
1656     * @param path the path to report on
1657     * @return The reply code received from the server,
1658     * may be {@code null} in which case the command is sent with no parameters
1659     * @throws FTPConnectionClosedException
1660     *      If the FTP server prematurely closes the connection as a result
1661     *      of the client being idle or some other reason causing the server
1662     *      to send FTP reply code 421.  This exception may be caught either
1663     *      as an IOException or independently as itself.
1664     * @throws IOException  If an I/O error occurs while either sending the
1665     *      command or receiving the server reply.
1666     * @since 3.0
1667     */
1668    public int mlst(String path) throws IOException
1669    {
1670        return sendCommand(FTPCmd.MLST, path);
1671    }
1672
1673    /***
1674     * A convenience method to send the FTP NLST command to the server,
1675     * receive the reply, and return the reply code.  Remember, it is up
1676     * to you to manage the data connection.  If you don't need this low
1677     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1678     * , which will handle all low level details for you.
1679     *
1680     * @return The reply code received from the server.
1681     * @throws FTPConnectionClosedException
1682     *      If the FTP server prematurely closes the connection as a result
1683     *      of the client being idle or some other reason causing the server
1684     *      to send FTP reply code 421.  This exception may be caught either
1685     *      as an IOException or independently as itself.
1686     * @throws IOException  If an I/O error occurs while either sending the
1687     *      command or receiving the server reply.
1688     ***/
1689    public int nlst() throws IOException
1690    {
1691        return sendCommand(FTPCmd.NLST);
1692    }
1693
1694    /***
1695     * A convenience method to send the FTP NLST command to the server,
1696     * receive the reply, and return the reply code.  Remember, it is up
1697     * to you to manage the data connection.  If you don't need this low
1698     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1699     * , which will handle all low level details for you.
1700     *
1701     * @param pathname  The pathname to list,
1702     * may be {@code null} in which case the command is sent with no parameters
1703     * @return The reply code received from the server.
1704     * @throws FTPConnectionClosedException
1705     *      If the FTP server prematurely closes the connection as a result
1706     *      of the client being idle or some other reason causing the server
1707     *      to send FTP reply code 421.  This exception may be caught either
1708     *      as an IOException or independently as itself.
1709     * @throws IOException  If an I/O error occurs while either sending the
1710     *      command or receiving the server reply.
1711     ***/
1712    public int nlst(String pathname) throws IOException
1713    {
1714        return sendCommand(FTPCmd.NLST, pathname);
1715    }
1716
1717    /***
1718     * A convenience method to send the FTP SITE command to the server,
1719     * receive the reply, and return the reply code.
1720     *
1721     * @param parameters  The site parameters to send.
1722     * @return The reply code received from the server.
1723     * @throws FTPConnectionClosedException
1724     *      If the FTP server prematurely closes the connection as a result
1725     *      of the client being idle or some other reason causing the server
1726     *      to send FTP reply code 421.  This exception may be caught either
1727     *      as an IOException or independently as itself.
1728     * @throws IOException  If an I/O error occurs while either sending the
1729     *      command or receiving the server reply.
1730     ***/
1731    public int site(String parameters) throws IOException
1732    {
1733        return sendCommand(FTPCmd.SITE, parameters);
1734    }
1735
1736    /***
1737     * A convenience method to send the FTP SIZE command to the server,
1738     * receive the reply, and return the reply code.
1739     *
1740     * @param parameters  The site parameters to send.
1741     * @return The reply code received from the server.
1742     * @throws FTPConnectionClosedException
1743     *      If the FTP server prematurely closes the connection as a result
1744     *      of the client being idle or some other reason causing the server
1745     *      to send FTP reply code 421.  This exception may be caught either
1746     *      as an IOException or independently as itself.
1747     * @throws IOException  If an I/O error occurs while either sending the
1748     *      command or receiving the server reply.
1749     * @since 3.7
1750     ***/
1751    public int size(String parameters) throws IOException
1752    {
1753        return sendCommand(FTPCmd.SIZE, parameters);
1754    }
1755
1756    /***
1757     * A convenience method to send the FTP SYST command to the server,
1758     * receive the reply, and return the reply code.
1759     *
1760     * @return The reply code received from the server.
1761     * @throws FTPConnectionClosedException
1762     *      If the FTP server prematurely closes the connection as a result
1763     *      of the client being idle or some other reason causing the server
1764     *      to send FTP reply code 421.  This exception may be caught either
1765     *      as an IOException or independently as itself.
1766     * @throws IOException  If an I/O error occurs while either sending the
1767     *      command or receiving the server reply.
1768     ***/
1769    public int syst() throws IOException
1770    {
1771        return sendCommand(FTPCmd.SYST);
1772    }
1773
1774    /***
1775     * A convenience method to send the FTP STAT command to the server,
1776     * receive the reply, and return the reply code.
1777     *
1778     * @return The reply code received from the server.
1779     * @throws FTPConnectionClosedException
1780     *      If the FTP server prematurely closes the connection as a result
1781     *      of the client being idle or some other reason causing the server
1782     *      to send FTP reply code 421.  This exception may be caught either
1783     *      as an IOException or independently as itself.
1784     * @throws IOException  If an I/O error occurs while either sending the
1785     *      command or receiving the server reply.
1786     ***/
1787    public int stat() throws IOException
1788    {
1789        return sendCommand(FTPCmd.STAT);
1790    }
1791
1792    /***
1793     * A convenience method to send the FTP STAT command to the server,
1794     * receive the reply, and return the reply code.
1795     *
1796     * @param pathname  A pathname to list.
1797     * @return The reply code received from the server.
1798     * @throws FTPConnectionClosedException
1799     *      If the FTP server prematurely closes the connection as a result
1800     *      of the client being idle or some other reason causing the server
1801     *      to send FTP reply code 421.  This exception may be caught either
1802     *      as an IOException or independently as itself.
1803     * @throws IOException  If an I/O error occurs while either sending the
1804     *      command or receiving the server reply.
1805     ***/
1806    public int stat(String pathname) throws IOException
1807    {
1808        return sendCommand(FTPCmd.STAT, pathname);
1809    }
1810
1811    /***
1812     * A convenience method to send the FTP HELP command to the server,
1813     * receive the reply, and return the reply code.
1814     *
1815     * @return The reply code received from the server.
1816     * @throws FTPConnectionClosedException
1817     *      If the FTP server prematurely closes the connection as a result
1818     *      of the client being idle or some other reason causing the server
1819     *      to send FTP reply code 421.  This exception may be caught either
1820     *      as an IOException or independently as itself.
1821     * @throws IOException  If an I/O error occurs while either sending the
1822     *      command or receiving the server reply.
1823     ***/
1824    public int help() throws IOException
1825    {
1826        return sendCommand(FTPCmd.HELP);
1827    }
1828
1829    /***
1830     * A convenience method to send the FTP HELP command to the server,
1831     * receive the reply, and return the reply code.
1832     *
1833     * @param command  The command name on which to request help.
1834     * @return The reply code received from the server.
1835     * @throws 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     * @throws IOException  If an I/O error occurs while either sending the
1841     *      command or receiving the server reply.
1842     ***/
1843    public int help(String command) throws IOException
1844    {
1845        return sendCommand(FTPCmd.HELP, command);
1846    }
1847
1848    /***
1849     * A convenience method to send the FTP NOOP command to the server,
1850     * receive the reply, and return the reply code.
1851     *
1852     * @return The reply code received from the server.
1853     * @throws FTPConnectionClosedException
1854     *      If the FTP server prematurely closes the connection as a result
1855     *      of the client being idle or some other reason causing the server
1856     *      to send FTP reply code 421.  This exception may be caught either
1857     *      as an IOException or independently as itself.
1858     * @throws IOException  If an I/O error occurs while either sending the
1859     *      command or receiving the server reply.
1860     ***/
1861    public int noop() throws IOException
1862    {
1863        return sendCommand(FTPCmd.NOOP);
1864    }
1865
1866    /**
1867     * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2.
1868     * @return True if strict, false if lenient
1869     * @since 2.0
1870     */
1871    public boolean isStrictMultilineParsing() {
1872        return strictMultilineParsing;
1873    }
1874
1875    /**
1876     * Set strict multiline parsing.
1877     * @param strictMultilineParsing the setting
1878     * @since 2.0
1879     */
1880    public void setStrictMultilineParsing(boolean strictMultilineParsing) {
1881        this.strictMultilineParsing = strictMultilineParsing;
1882    }
1883
1884    /**
1885     * Return whether strict non-multiline parsing is enabled, as per RFC 959, section 4.2.
1886     * <p>
1887     * The default is true, which requires the 3 digit code be followed by space and some text.
1888     * <br>
1889     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1890     * <br>
1891     * @return True if strict (default), false if additional checks are not made
1892     * @since 3.6
1893     */
1894    public boolean isStrictReplyParsing() {
1895        return strictReplyParsing;
1896    }
1897
1898    /**
1899     * Set strict non-multiline parsing.
1900     * <p>
1901     * If true, it requires the 3 digit code be followed by space and some text.
1902     * <br>
1903     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1904     * <p>
1905     * <b>This should not be required by a well-behaved FTP server</b>
1906     * <br>
1907     * @param strictReplyParsing the setting
1908     * @since 3.6
1909     */
1910    public void setStrictReplyParsing(boolean strictReplyParsing) {
1911        this.strictReplyParsing = strictReplyParsing;
1912    }
1913
1914    /**
1915     * Provide command support to super-class
1916     */
1917    @Override
1918    protected ProtocolCommandSupport getCommandSupport() {
1919        return _commandSupport_;
1920    }
1921}
1922
1923/* Emacs configuration
1924 * Local variables:        **
1925 * mode:             java  **
1926 * c-basic-offset:   4     **
1927 * indent-tabs-mode: nil   **
1928 * End:                    **
1929 */