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<>();
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(final String line, final 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(final 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(final 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 (final 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            final 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_(final 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            final 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 (final SocketTimeoutException e) {
430                final 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(final 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(final String command, final 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(final String command, final 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(final String message) throws IOException,
541            FTPConnectionClosedException, SocketException {
542        try{
543            _controlOutput_.write(message);
544            _controlOutput_.flush();
545        }
546        catch (final SocketException e)
547        {
548            if (!isConnected())
549            {
550                throw new FTPConnectionClosedException("Connection unexpectedly closed.");
551            }
552            throw e;
553        }
554    }
555
556    /**
557     * Send a noop and get the reply without reporting to the command listener.
558     * Intended for use with keep-alive.
559     *
560     * @throws IOException on error
561     * @since 3.0
562     */
563    protected void __noop() throws IOException {
564        final String msg = __buildMessage(FTPCmd.NOOP.getCommand(), null);
565        __send(msg);
566        __getReplyNoReport(); // This may timeout
567    }
568
569    /***
570     * Sends an FTP command to the server, waits for a reply and returns the
571     * numerical response code.  After invocation, for more detailed
572     * information, the actual reply text can be accessed by calling
573     * {@link #getReplyString  getReplyString } or
574     * {@link #getReplyStrings  getReplyStrings }.
575     *
576     * @param command  The FTPCommand constant corresponding to the FTP command
577     *                 to send.
578     * @param args The arguments to the FTP command.  If this parameter is
579     *             set to null, then the command is sent with no argument.
580     * @return The integer value of the FTP reply code returned by the server
581     *         in response to the command.
582     * @throws FTPConnectionClosedException
583     *      If the FTP server prematurely closes the connection as a result
584     *      of the client being idle or some other reason causing the server
585     *      to send FTP reply code 421.  This exception may be caught either
586     *      as an IOException or independently as itself.
587     * @throws IOException  If an I/O error occurs while either sending the
588     *      command or receiving the server reply.
589     * @deprecated (3.3) Use {@link #sendCommand(FTPCmd, String)} instead
590     ***/
591    @Deprecated
592    public int sendCommand(final int command, final String args) throws IOException
593    {
594        return sendCommand(FTPCommand.getCommand(command), args);
595    }
596
597    /**
598     * Sends an FTP command to the server, waits for a reply and returns the
599     * numerical response code.  After invocation, for more detailed
600     * information, the actual reply text can be accessed by calling
601     * {@link #getReplyString  getReplyString } or
602     * {@link #getReplyStrings  getReplyStrings }.
603     *
604     * @param command  The FTPCmd enum corresponding to the FTP command
605     *                 to send.
606     * @return The integer value of the FTP reply code returned by the server
607     *         in response to the command.
608     * @throws FTPConnectionClosedException
609     *      If the FTP server prematurely closes the connection as a result
610     *      of the client being idle or some other reason causing the server
611     *      to send FTP reply code 421.  This exception may be caught either
612     *      as an IOException or independently as itself.
613     * @throws IOException  If an I/O error occurs while either sending the
614     *      command or receiving the server reply.
615     * @since 3.3
616     */
617    public int sendCommand(final FTPCmd command)  throws IOException{
618        return sendCommand(command, null);
619    }
620
621    /**
622     * Sends an FTP command to the server, waits for a reply and returns the
623     * numerical response code.  After invocation, for more detailed
624     * information, the actual reply text can be accessed by calling
625     * {@link #getReplyString  getReplyString } or
626     * {@link #getReplyStrings  getReplyStrings }.
627     *
628     * @param command  The FTPCmd enum corresponding to the FTP command
629     *                 to send.
630     * @param args The arguments to the FTP command.  If this parameter is
631     *             set to null, then the command is sent with no argument.
632     * @return The integer value of the FTP reply code returned by the server
633     *         in response to the command.
634     * @throws FTPConnectionClosedException
635     *      If the FTP server prematurely closes the connection as a result
636     *      of the client being idle or some other reason causing the server
637     *      to send FTP reply code 421.  This exception may be caught either
638     *      as an IOException or independently as itself.
639     * @throws IOException  If an I/O error occurs while either sending the
640     *      command or receiving the server reply.
641     * @since 3.3
642     */
643    public int sendCommand(final FTPCmd command, final String args)  throws IOException{
644        return sendCommand(command.getCommand(), args);
645    }
646
647    /***
648     * Sends an FTP command with no arguments to the server, waits for a
649     * reply and returns the numerical response code.  After invocation, for
650     * more detailed information, the actual reply text can be accessed by
651     * calling {@link #getReplyString  getReplyString } or
652     * {@link #getReplyStrings  getReplyStrings }.
653     *
654     * @param command  The text representation of the  FTP command to send.
655     * @return The integer value of the FTP reply code returned by the server
656     *         in response to the command.
657     * @throws FTPConnectionClosedException
658     *      If the FTP server prematurely closes the connection as a result
659     *      of the client being idle or some other reason causing the server
660     *      to send FTP reply code 421.  This exception may be caught either
661     *      as an IOException or independently as itself.
662     * @throws IOException  If an I/O error occurs while either sending the
663     *      command or receiving the server reply.
664     ***/
665    public int sendCommand(final String command) throws IOException
666    {
667        return sendCommand(command, null);
668    }
669
670
671    /***
672     * Sends an FTP command with no arguments to the server, waits for a
673     * reply and returns the numerical response code.  After invocation, for
674     * more detailed information, the actual reply text can be accessed by
675     * calling {@link #getReplyString  getReplyString } or
676     * {@link #getReplyStrings  getReplyStrings }.
677     *
678     * @param command  The FTPCommand constant corresponding to the FTP command
679     *                 to send.
680     * @return The integer value of the FTP reply code returned by the server
681     *         in response to the command.
682     * @throws FTPConnectionClosedException
683     *      If the FTP server prematurely closes the connection as a result
684     *      of the client being idle or some other reason causing the server
685     *      to send FTP reply code 421.  This exception may be caught either
686     *      as an IOException or independently as itself.
687     * @throws IOException  If an I/O error occurs while either sending the
688     *      command or receiving the server reply.
689     ***/
690    public int sendCommand(final int command) throws IOException
691    {
692        return sendCommand(command, null);
693    }
694
695
696    /***
697     * Returns the integer value of the reply code of the last FTP reply.
698     * You will usually only use this method after you connect to the
699     * FTP server to check that the connection was successful since
700     * <code> connect </code> is of type void.
701     *
702     * @return The integer value of the reply code of the last FTP reply.
703     ***/
704    public int getReplyCode()
705    {
706        return _replyCode;
707    }
708
709    /***
710     * Fetches a reply from the FTP server and returns the integer reply
711     * code.  After calling this method, the actual reply text can be accessed
712     * from either  calling {@link #getReplyString  getReplyString } or
713     * {@link #getReplyStrings  getReplyStrings }.  Only use this
714     * method if you are implementing your own FTP client or if you need to
715     * fetch a secondary response from the FTP server.
716     *
717     * @return The integer value of the reply code of the fetched FTP reply.
718     * @throws FTPConnectionClosedException
719     *      If the FTP server prematurely closes the connection as a result
720     *      of the client being idle or some other reason causing the server
721     *      to send FTP reply code 421.  This exception may be caught either
722     *      as an IOException or independently as itself.
723     * @throws IOException  If an I/O error occurs while receiving the
724     *                         server reply.
725     ***/
726    public int getReply() throws IOException
727    {
728        __getReply();
729        return _replyCode;
730    }
731
732
733    /***
734     * Returns the lines of text from the last FTP server response as an array
735     * of strings, one entry per line.  The end of line markers of each are
736     * stripped from each line.
737     *
738     * @return The lines of text from the last FTP response as an array.
739     ***/
740    public String[] getReplyStrings()
741    {
742        return _replyLines.toArray(new String[_replyLines.size()]);
743    }
744
745    /***
746     * Returns the entire text of the last FTP server response exactly
747     * as it was received, including all end of line markers in NETASCII
748     * format.
749     *
750     * @return The entire text from the last FTP response as a String.
751     ***/
752    public String getReplyString()
753    {
754        StringBuilder buffer;
755
756        if (!_newReplyString) {
757            return _replyString;
758        }
759
760        buffer = new StringBuilder(256);
761
762        for (final String line : _replyLines) {
763                buffer.append(line);
764                buffer.append(SocketClient.NETASCII_EOL);
765        }
766
767         _newReplyString = false;
768
769        return _replyString = buffer.toString();
770    }
771
772
773    /***
774     * A convenience method to send the FTP USER command to the server,
775     * receive the reply, and return the reply code.
776     *
777     * @param username  The username to login under.
778     * @return The reply code received from the server.
779     * @throws FTPConnectionClosedException
780     *      If the FTP server prematurely closes the connection as a result
781     *      of the client being idle or some other reason causing the server
782     *      to send FTP reply code 421.  This exception may be caught either
783     *      as an IOException or independently as itself.
784     * @throws IOException  If an I/O error occurs while either sending the
785     *      command or receiving the server reply.
786     ***/
787    public int user(final String username) throws IOException
788    {
789        return sendCommand(FTPCmd.USER, username);
790    }
791
792    /**
793     * A convenience method to send the FTP PASS command to the server,
794     * receive the reply, and return the reply code.
795     * @param password The plain text password of the username being logged into.
796     * @return The reply code received from the server.
797     * @throws FTPConnectionClosedException
798     *      If the FTP server prematurely closes the connection as a result
799     *      of the client being idle or some other reason causing the server
800     *      to send FTP reply code 421.  This exception may be caught either
801     *      as an IOException or independently as itself.
802     * @throws IOException  If an I/O error occurs while either sending the
803     *      command or receiving the server reply.
804     */
805    public int pass(final String password) throws IOException
806    {
807        return sendCommand(FTPCmd.PASS, password);
808    }
809
810    /***
811     * A convenience method to send the FTP ACCT command to the server,
812     * receive the reply, and return the reply code.
813     *
814     * @param account  The account name to access.
815     * @return The reply code received from the server.
816     * @throws FTPConnectionClosedException
817     *      If the FTP server prematurely closes the connection as a result
818     *      of the client being idle or some other reason causing the server
819     *      to send FTP reply code 421.  This exception may be caught either
820     *      as an IOException or independently as itself.
821     * @throws IOException  If an I/O error occurs while either sending the
822     *      command or receiving the server reply.
823     ***/
824    public int acct(final String account) throws IOException
825    {
826        return sendCommand(FTPCmd.ACCT, account);
827    }
828
829
830    /***
831     * A convenience method to send the FTP ABOR command to the server,
832     * receive the reply, and return the reply code.
833     *
834     * @return The reply code received from the server.
835     * @throws FTPConnectionClosedException
836     *      If the FTP server prematurely closes the connection as a result
837     *      of the client being idle or some other reason causing the server
838     *      to send FTP reply code 421.  This exception may be caught either
839     *      as an IOException or independently as itself.
840     * @throws IOException  If an I/O error occurs while either sending the
841     *      command or receiving the server reply.
842     ***/
843    public int abor() throws IOException
844    {
845        return sendCommand(FTPCmd.ABOR);
846    }
847
848    /***
849     * A convenience method to send the FTP CWD command to the server,
850     * receive the reply, and return the reply code.
851     *
852     * @param directory The new working directory.
853     * @return The reply code received from the server.
854     * @throws FTPConnectionClosedException
855     *      If the FTP server prematurely closes the connection as a result
856     *      of the client being idle or some other reason causing the server
857     *      to send FTP reply code 421.  This exception may be caught either
858     *      as an IOException or independently as itself.
859     * @throws IOException  If an I/O error occurs while either sending the
860     *      command or receiving the server reply.
861     ***/
862    public int cwd(final String directory) throws IOException
863    {
864        return sendCommand(FTPCmd.CWD, directory);
865    }
866
867    /***
868     * A convenience method to send the FTP CDUP command to the server,
869     * receive the reply, and return the reply code.
870     *
871     * @return The reply code received from the server.
872     * @throws FTPConnectionClosedException
873     *      If the FTP server prematurely closes the connection as a result
874     *      of the client being idle or some other reason causing the server
875     *      to send FTP reply code 421.  This exception may be caught either
876     *      as an IOException or independently as itself.
877     * @throws IOException  If an I/O error occurs while either sending the
878     *      command or receiving the server reply.
879     ***/
880    public int cdup() throws IOException
881    {
882        return sendCommand(FTPCmd.CDUP);
883    }
884
885    /***
886     * A convenience method to send the FTP QUIT command to the server,
887     * receive the reply, and return the reply code.
888     *
889     * @return The reply code received from the server.
890     * @throws FTPConnectionClosedException
891     *      If the FTP server prematurely closes the connection as a result
892     *      of the client being idle or some other reason causing the server
893     *      to send FTP reply code 421.  This exception may be caught either
894     *      as an IOException or independently as itself.
895     * @throws IOException  If an I/O error occurs while either sending the
896     *      command or receiving the server reply.
897     ***/
898    public int quit() throws IOException
899    {
900        return sendCommand(FTPCmd.QUIT);
901    }
902
903    /***
904     * A convenience method to send the FTP REIN command to the server,
905     * receive the reply, and return the reply code.
906     *
907     * @return The reply code received from the server.
908     * @throws FTPConnectionClosedException
909     *      If the FTP server prematurely closes the connection as a result
910     *      of the client being idle or some other reason causing the server
911     *      to send FTP reply code 421.  This exception may be caught either
912     *      as an IOException or independently as itself.
913     * @throws IOException  If an I/O error occurs while either sending the
914     *      command or receiving the server reply.
915     ***/
916    public int rein() throws IOException
917    {
918        return sendCommand(FTPCmd.REIN);
919    }
920
921    /***
922     * A convenience method to send the FTP SMNT command to the server,
923     * receive the reply, and return the reply code.
924     *
925     * @param dir  The directory name.
926     * @return The reply code received from the server.
927     * @throws FTPConnectionClosedException
928     *      If the FTP server prematurely closes the connection as a result
929     *      of the client being idle or some other reason causing the server
930     *      to send FTP reply code 421.  This exception may be caught either
931     *      as an IOException or independently as itself.
932     * @throws IOException  If an I/O error occurs while either sending the
933     *      command or receiving the server reply.
934     ***/
935    public int smnt(final String dir) throws IOException
936    {
937        return sendCommand(FTPCmd.SMNT, dir);
938    }
939
940    /***
941     * A convenience method to send the FTP PORT command to the server,
942     * receive the reply, and return the reply code.
943     *
944     * @param host  The host owning the port.
945     * @param port  The new port.
946     * @return The reply code received from the server.
947     * @throws FTPConnectionClosedException
948     *      If the FTP server prematurely closes the connection as a result
949     *      of the client being idle or some other reason causing the server
950     *      to send FTP reply code 421.  This exception may be caught either
951     *      as an IOException or independently as itself.
952     * @throws IOException  If an I/O error occurs while either sending the
953     *      command or receiving the server reply.
954     ***/
955    public int port(final InetAddress host, final int port) throws IOException
956    {
957        int num;
958        final StringBuilder info = new StringBuilder(24);
959
960        info.append(host.getHostAddress().replace('.', ','));
961        num = port >>> 8;
962        info.append(',');
963        info.append(num);
964        info.append(',');
965        num = port & 0xff;
966        info.append(num);
967
968        return sendCommand(FTPCmd.PORT, info.toString());
969    }
970
971    /***
972     * A convenience method to send the FTP EPRT command to the server,
973     * receive the reply, and return the reply code.
974     *
975     * Examples:
976     * <ul>
977     * <li>EPRT |1|132.235.1.2|6275|</li>
978     * <li>EPRT |2|1080::8:800:200C:417A|5282|</li>
979     * </ul>
980     *
981     * @see "http://www.faqs.org/rfcs/rfc2428.html"
982     *
983     * @param host  The host owning the port.
984     * @param port  The new port.
985     * @return The reply code received from the server.
986     * @throws FTPConnectionClosedException
987     *      If the FTP server prematurely closes the connection as a result
988     *      of the client being idle or some other reason causing the server
989     *      to send FTP reply code 421.  This exception may be caught either
990     *      as an IOException or independently as itself.
991     * @throws IOException  If an I/O error occurs while either sending the
992     *      command or receiving the server reply.
993     * @since 2.2
994     ***/
995    public int eprt(final InetAddress host, final int port) throws IOException
996    {
997        int num;
998        final StringBuilder info = new StringBuilder();
999        String h;
1000
1001        // If IPv6, trim the zone index
1002        h = host.getHostAddress();
1003        num = h.indexOf('%');
1004        if (num > 0) {
1005            h = h.substring(0, num);
1006        }
1007
1008        info.append("|");
1009
1010        if (host instanceof Inet4Address) {
1011            info.append("1");
1012        } else if (host instanceof Inet6Address) {
1013            info.append("2");
1014        }
1015        info.append("|");
1016        info.append(h);
1017        info.append("|");
1018        info.append(port);
1019        info.append("|");
1020
1021        return sendCommand(FTPCmd.EPRT, info.toString());
1022    }
1023
1024    /***
1025     * A convenience method to send the FTP PASV command to the server,
1026     * receive the reply, and return the reply code.  Remember, it's up
1027     * to you to interpret the reply string containing the host/port
1028     * information.
1029     *
1030     * @return The reply code received from the server.
1031     * @throws FTPConnectionClosedException
1032     *      If the FTP server prematurely closes the connection as a result
1033     *      of the client being idle or some other reason causing the server
1034     *      to send FTP reply code 421.  This exception may be caught either
1035     *      as an IOException or independently as itself.
1036     * @throws IOException  If an I/O error occurs while either sending the
1037     *      command or receiving the server reply.
1038     ***/
1039    public int pasv() throws IOException
1040    {
1041        return sendCommand(FTPCmd.PASV);
1042    }
1043
1044     /***
1045     * A convenience method to send the FTP EPSV command to the server,
1046     * receive the reply, and return the reply code.  Remember, it's up
1047     * to you to interpret the reply string containing the host/port
1048     * information.
1049     *
1050     * @return The reply code received from the server.
1051     * @throws FTPConnectionClosedException
1052     *      If the FTP server prematurely closes the connection as a result
1053     *      of the client being idle or some other reason causing the server
1054     *      to send FTP reply code 421.  This exception may be caught either
1055     *      as an IOException or independently as itself.
1056     * @throws IOException  If an I/O error occurs while either sending the
1057     *      command or receiving the server reply.
1058     * @since 2.2
1059     ***/
1060    public int epsv() throws IOException
1061    {
1062        return sendCommand(FTPCmd.EPSV);
1063    }
1064
1065    /**
1066     * A convenience method to send the FTP TYPE command for text files
1067     * to the server, receive the reply, and return the reply code.
1068     * @param fileType  The type of the file (one of the <code>FILE_TYPE</code>
1069     *              constants).
1070     * @param formatOrByteSize  The format of the file (one of the
1071     *              <code>_FORMAT</code> constants.  In the case of
1072     *              <code>LOCAL_FILE_TYPE</code>, the byte size.
1073     * @return The reply code received from the server.
1074     * @throws FTPConnectionClosedException
1075     *      If the FTP server prematurely closes the connection as a result
1076     *      of the client being idle or some other reason causing the server
1077     *      to send FTP reply code 421.  This exception may be caught either
1078     *      as an IOException or independently as itself.
1079     * @throws IOException  If an I/O error occurs while either sending the
1080     *      command or receiving the server reply.
1081     */
1082    public int type(final int fileType, final int formatOrByteSize) throws IOException
1083    {
1084        final StringBuilder arg = new StringBuilder();
1085
1086        arg.append(modes.charAt(fileType));
1087        arg.append(' ');
1088        if (fileType == LOCAL_FILE_TYPE) {
1089            arg.append(formatOrByteSize);
1090        } else {
1091            arg.append(modes.charAt(formatOrByteSize));
1092        }
1093
1094        return sendCommand(FTPCmd.TYPE, arg.toString());
1095    }
1096
1097
1098    /**
1099     * A convenience method to send the FTP TYPE command to the server,
1100     * receive the reply, and return the reply code.
1101     *
1102     * @param fileType  The type of the file (one of the <code>FILE_TYPE</code>
1103     *              constants).
1104     * @return The reply code received from the server.
1105     * @throws FTPConnectionClosedException
1106     *      If the FTP server prematurely closes the connection as a result
1107     *      of the client being idle or some other reason causing the server
1108     *      to send FTP reply code 421.  This exception may be caught either
1109     *      as an IOException or independently as itself.
1110     * @throws IOException  If an I/O error occurs while either sending the
1111     *      command or receiving the server reply.
1112     */
1113    public int type(final int fileType) throws IOException
1114    {
1115        return sendCommand(FTPCmd.TYPE,
1116                           modes.substring(fileType, fileType + 1));
1117    }
1118
1119    /***
1120     * A convenience method to send the FTP STRU command to the server,
1121     * receive the reply, and return the reply code.
1122     *
1123     * @param structure  The structure of the file (one of the
1124     *         <code>_STRUCTURE</code> constants).
1125     * @return The reply code received from the server.
1126     * @throws FTPConnectionClosedException
1127     *      If the FTP server prematurely closes the connection as a result
1128     *      of the client being idle or some other reason causing the server
1129     *      to send FTP reply code 421.  This exception may be caught either
1130     *      as an IOException or independently as itself.
1131     * @throws IOException  If an I/O error occurs while either sending the
1132     *      command or receiving the server reply.
1133     ***/
1134    public int stru(final int structure) throws IOException
1135    {
1136        return sendCommand(FTPCmd.STRU,
1137                           modes.substring(structure, structure + 1));
1138    }
1139
1140    /***
1141     * A convenience method to send the FTP MODE command to the server,
1142     * receive the reply, and return the reply code.
1143     *
1144     * @param mode  The transfer mode to use (one of the
1145     *         <code>TRANSFER_MODE</code> constants).
1146     * @return The reply code received from the server.
1147     * @throws FTPConnectionClosedException
1148     *      If the FTP server prematurely closes the connection as a result
1149     *      of the client being idle or some other reason causing the server
1150     *      to send FTP reply code 421.  This exception may be caught either
1151     *      as an IOException or independently as itself.
1152     * @throws IOException  If an I/O error occurs while either sending the
1153     *      command or receiving the server reply.
1154     ***/
1155    public int mode(final int mode) throws IOException
1156    {
1157        return sendCommand(FTPCmd.MODE,
1158                           modes.substring(mode, mode + 1));
1159    }
1160
1161    /***
1162     * A convenience method to send the FTP RETR command to the server,
1163     * receive the reply, and return the reply code.  Remember, it is up
1164     * to you to manage the data connection.  If you don't need this low
1165     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1166     * , which will handle all low level details for you.
1167     *
1168     * @param pathname  The pathname of the file to retrieve.
1169     * @return The reply code received from the server.
1170     * @throws FTPConnectionClosedException
1171     *      If the FTP server prematurely closes the connection as a result
1172     *      of the client being idle or some other reason causing the server
1173     *      to send FTP reply code 421.  This exception may be caught either
1174     *      as an IOException or independently as itself.
1175     * @throws IOException  If an I/O error occurs while either sending the
1176     *      command or receiving the server reply.
1177     ***/
1178    public int retr(final String pathname) throws IOException
1179    {
1180        return sendCommand(FTPCmd.RETR, pathname);
1181    }
1182
1183    /***
1184     * A convenience method to send the FTP STOR command to the server,
1185     * receive the reply, and return the reply code.  Remember, it is up
1186     * to you to manage the data connection.  If you don't need this low
1187     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1188     * , which will handle all low level details for you.
1189     *
1190     * @param pathname  The pathname to use for the file when stored at
1191     *                  the remote end of the transfer.
1192     * @return The reply code received from the server.
1193     * @throws FTPConnectionClosedException
1194     *      If the FTP server prematurely closes the connection as a result
1195     *      of the client being idle or some other reason causing the server
1196     *      to send FTP reply code 421.  This exception may be caught either
1197     *      as an IOException or independently as itself.
1198     * @throws IOException  If an I/O error occurs while either sending the
1199     *      command or receiving the server reply.
1200     ***/
1201    public int stor(final String pathname) throws IOException
1202    {
1203        return sendCommand(FTPCmd.STOR, pathname);
1204    }
1205
1206    /***
1207     * A convenience method to send the FTP STOU command to the server,
1208     * receive the reply, and return the reply code.  Remember, it is up
1209     * to you to manage the data connection.  If you don't need this low
1210     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1211     * , which will handle all low level details for you.
1212     *
1213     * @return The reply code received from the server.
1214     * @throws FTPConnectionClosedException
1215     *      If the FTP server prematurely closes the connection as a result
1216     *      of the client being idle or some other reason causing the server
1217     *      to send FTP reply code 421.  This exception may be caught either
1218     *      as an IOException or independently as itself.
1219     * @throws IOException  If an I/O error occurs while either sending the
1220     *      command or receiving the server reply.
1221     ***/
1222    public int stou() throws IOException
1223    {
1224        return sendCommand(FTPCmd.STOU);
1225    }
1226
1227    /***
1228     * A convenience method to send the FTP STOU command to the server,
1229     * receive the reply, and return the reply code.  Remember, it is up
1230     * to you to manage the data connection.  If you don't need this low
1231     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1232     * , which will handle all low level details for you.
1233     * @param pathname  The base pathname to use for the file when stored at
1234     *                  the remote end of the transfer.  Some FTP servers
1235     *                  require this.
1236     * @return The reply code received from the server.
1237     * @throws FTPConnectionClosedException
1238     *      If the FTP server prematurely closes the connection as a result
1239     *      of the client being idle or some other reason causing the server
1240     *      to send FTP reply code 421.  This exception may be caught either
1241     *      as an IOException or independently as itself.
1242     * @throws IOException  If an I/O error occurs while either sending the
1243     *      command or receiving the server reply.
1244     */
1245    public int stou(final String pathname) throws IOException
1246    {
1247        return sendCommand(FTPCmd.STOU, pathname);
1248    }
1249
1250    /***
1251     * A convenience method to send the FTP APPE command to the server,
1252     * receive the reply, and return the reply code.  Remember, it is up
1253     * to you to manage the data connection.  If you don't need this low
1254     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1255     * , which will handle all low level details for you.
1256     *
1257     * @param pathname  The pathname to use for the file when stored at
1258     *                  the remote end of the transfer.
1259     * @return The reply code received from the server.
1260     * @throws FTPConnectionClosedException
1261     *      If the FTP server prematurely closes the connection as a result
1262     *      of the client being idle or some other reason causing the server
1263     *      to send FTP reply code 421.  This exception may be caught either
1264     *      as an IOException or independently as itself.
1265     * @throws IOException  If an I/O error occurs while either sending the
1266     *      command or receiving the server reply.
1267     ***/
1268    public int appe(final String pathname) throws IOException
1269    {
1270        return sendCommand(FTPCmd.APPE, pathname);
1271    }
1272
1273    /***
1274     * A convenience method to send the FTP ALLO command to the server,
1275     * receive the reply, and return the reply code.
1276     *
1277     * @param bytes The number of bytes to allocate.
1278     * @return The reply code received from the server.
1279     * @throws FTPConnectionClosedException
1280     *      If the FTP server prematurely closes the connection as a result
1281     *      of the client being idle or some other reason causing the server
1282     *      to send FTP reply code 421.  This exception may be caught either
1283     *      as an IOException or independently as itself.
1284     * @throws IOException  If an I/O error occurs while either sending the
1285     *      command or receiving the server reply.
1286     ***/
1287    public int allo(final int bytes) throws IOException
1288    {
1289        return sendCommand(FTPCmd.ALLO, Integer.toString(bytes));
1290    }
1291
1292    /***
1293     * A convenience method to send the FTP ALLO command to the server,
1294     * receive the reply, and return the reply code.
1295     *
1296     * @param bytes The number of bytes to allocate.
1297     * @return The reply code received from the server.
1298     * @throws FTPConnectionClosedException
1299     *      If the FTP server prematurely closes the connection as a result
1300     *      of the client being idle or some other reason causing the server
1301     *      to send FTP reply code 421.  This exception may be caught either
1302     *      as an IOException or independently as itself.
1303     * @throws IOException  If an I/O error occurs while either sending the
1304     *      command or receiving the server reply.
1305     ***/
1306    public int allo(final long bytes) throws IOException
1307    {
1308        return sendCommand(FTPCmd.ALLO, Long.toString(bytes));
1309    }
1310
1311    /**
1312     * A convenience method to send the FTP FEAT command to the server, receive the reply,
1313     * and return the reply code.
1314     * @return The reply code received by the server
1315     * @throws IOException  If an I/O error occurs while either sending the
1316     *      command or receiving the server reply.
1317     * @since 2.2
1318     */
1319    public int feat() throws IOException
1320    {
1321        return sendCommand(FTPCmd.FEAT);
1322    }
1323
1324    /***
1325     * A convenience method to send the FTP ALLO command to the server,
1326     * receive the reply, and return the reply code.
1327     *
1328     * @param bytes The number of bytes to allocate.
1329     * @param recordSize  The size of a record.
1330     * @return The reply code received from the server.
1331     * @throws FTPConnectionClosedException
1332     *      If the FTP server prematurely closes the connection as a result
1333     *      of the client being idle or some other reason causing the server
1334     *      to send FTP reply code 421.  This exception may be caught either
1335     *      as an IOException or independently as itself.
1336     * @throws IOException  If an I/O error occurs while either sending the
1337     *      command or receiving the server reply.
1338     ***/
1339    public int allo(final int bytes, final int recordSize) throws IOException
1340    {
1341        return sendCommand(FTPCmd.ALLO, Integer.toString(bytes) + " R " +
1342                           Integer.toString(recordSize));
1343    }
1344
1345    /***
1346     * A convenience method to send the FTP ALLO command to the server,
1347     * receive the reply, and return the reply code.
1348     *
1349     * @param bytes The number of bytes to allocate.
1350     * @param recordSize  The size of a record.
1351     * @return The reply code received from the server.
1352     * @throws FTPConnectionClosedException
1353     *      If the FTP server prematurely closes the connection as a result
1354     *      of the client being idle or some other reason causing the server
1355     *      to send FTP reply code 421.  This exception may be caught either
1356     *      as an IOException or independently as itself.
1357     * @throws IOException  If an I/O error occurs while either sending the
1358     *      command or receiving the server reply.
1359     ***/
1360    public int allo(final long bytes, final int recordSize) throws IOException
1361    {
1362        return sendCommand(FTPCmd.ALLO, Long.toString(bytes) + " R " +
1363                           Integer.toString(recordSize));
1364    }
1365
1366    /***
1367     * A convenience method to send the FTP REST command to the server,
1368     * receive the reply, and return the reply code.
1369     *
1370     * @param marker The marker at which to restart a transfer.
1371     * @return The reply code received from the server.
1372     * @throws FTPConnectionClosedException
1373     *      If the FTP server prematurely closes the connection as a result
1374     *      of the client being idle or some other reason causing the server
1375     *      to send FTP reply code 421.  This exception may be caught either
1376     *      as an IOException or independently as itself.
1377     * @throws IOException  If an I/O error occurs while either sending the
1378     *      command or receiving the server reply.
1379     ***/
1380    public int rest(final String marker) throws IOException
1381    {
1382        return sendCommand(FTPCmd.REST, marker);
1383    }
1384
1385
1386    /**
1387     * @param file name of file
1388     * @return the status
1389     * @throws IOException on error
1390     * @since 2.0
1391     **/
1392    public int mdtm(final String file) throws IOException
1393    {
1394        return sendCommand(FTPCmd.MDTM, file);
1395    }
1396
1397
1398    /**
1399     * A convenience method to send the FTP MFMT command to the server,
1400     * receive the reply, and return the reply code.
1401     *
1402     * @param pathname The pathname for which mtime is to be changed
1403     * @param timeval Timestamp in <code>YYYYMMDDhhmmss</code> format
1404     * @return The reply code received from the server.
1405     * @throws FTPConnectionClosedException
1406     *      If the FTP server prematurely closes the connection as a result
1407     *      of the client being idle or some other reason causing the server
1408     *      to send FTP reply code 421.  This exception may be caught either
1409     *      as an IOException or independently as itself.
1410     * @throws IOException  If an I/O error occurs while either sending the
1411     *      command or receiving the server reply.
1412     * @since 2.2
1413     * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
1414     **/
1415    public int mfmt(final String pathname, final String timeval) throws IOException
1416    {
1417        return sendCommand(FTPCmd.MFMT, timeval + " " + pathname);
1418    }
1419
1420
1421    /***
1422     * A convenience method to send the FTP RNFR command to the server,
1423     * receive the reply, and return the reply code.
1424     *
1425     * @param pathname The pathname to rename from.
1426     * @return The reply code received from the server.
1427     * @throws FTPConnectionClosedException
1428     *      If the FTP server prematurely closes the connection as a result
1429     *      of the client being idle or some other reason causing the server
1430     *      to send FTP reply code 421.  This exception may be caught either
1431     *      as an IOException or independently as itself.
1432     * @throws IOException  If an I/O error occurs while either sending the
1433     *      command or receiving the server reply.
1434     ***/
1435    public int rnfr(final String pathname) throws IOException
1436    {
1437        return sendCommand(FTPCmd.RNFR, pathname);
1438    }
1439
1440    /***
1441     * A convenience method to send the FTP RNTO command to the server,
1442     * receive the reply, and return the reply code.
1443     *
1444     * @param pathname The pathname to rename to
1445     * @return The reply code received from the server.
1446     * @throws FTPConnectionClosedException
1447     *      If the FTP server prematurely closes the connection as a result
1448     *      of the client being idle or some other reason causing the server
1449     *      to send FTP reply code 421.  This exception may be caught either
1450     *      as an IOException or independently as itself.
1451     * @throws IOException  If an I/O error occurs while either sending the
1452     *      command or receiving the server reply.
1453     ***/
1454    public int rnto(final String pathname) throws IOException
1455    {
1456        return sendCommand(FTPCmd.RNTO, pathname);
1457    }
1458
1459    /***
1460     * A convenience method to send the FTP DELE command to the server,
1461     * receive the reply, and return the reply code.
1462     *
1463     * @param pathname The pathname to delete.
1464     * @return The reply code received from the server.
1465     * @throws FTPConnectionClosedException
1466     *      If the FTP server prematurely closes the connection as a result
1467     *      of the client being idle or some other reason causing the server
1468     *      to send FTP reply code 421.  This exception may be caught either
1469     *      as an IOException or independently as itself.
1470     * @throws IOException  If an I/O error occurs while either sending the
1471     *      command or receiving the server reply.
1472     ***/
1473    public int dele(final String pathname) throws IOException
1474    {
1475        return sendCommand(FTPCmd.DELE, pathname);
1476    }
1477
1478    /***
1479     * A convenience method to send the FTP RMD command to the server,
1480     * receive the reply, and return the reply code.
1481     *
1482     * @param pathname The pathname of the directory to remove.
1483     * @return The reply code received from the server.
1484     * @throws FTPConnectionClosedException
1485     *      If the FTP server prematurely closes the connection as a result
1486     *      of the client being idle or some other reason causing the server
1487     *      to send FTP reply code 421.  This exception may be caught either
1488     *      as an IOException or independently as itself.
1489     * @throws IOException  If an I/O error occurs while either sending the
1490     *      command or receiving the server reply.
1491     ***/
1492    public int rmd(final String pathname) throws IOException
1493    {
1494        return sendCommand(FTPCmd.RMD, pathname);
1495    }
1496
1497    /***
1498     * A convenience method to send the FTP MKD command to the server,
1499     * receive the reply, and return the reply code.
1500     *
1501     * @param pathname The pathname of the new directory to create.
1502     * @return The reply code received from the server.
1503     * @throws FTPConnectionClosedException
1504     *      If the FTP server prematurely closes the connection as a result
1505     *      of the client being idle or some other reason causing the server
1506     *      to send FTP reply code 421.  This exception may be caught either
1507     *      as an IOException or independently as itself.
1508     * @throws IOException  If an I/O error occurs while either sending the
1509     *      command or receiving the server reply.
1510     ***/
1511    public int mkd(final String pathname) throws IOException
1512    {
1513        return sendCommand(FTPCmd.MKD, pathname);
1514    }
1515
1516    /***
1517     * A convenience method to send the FTP PWD command to the server,
1518     * receive the reply, and return the reply code.
1519     *
1520     * @return The reply code received from the server.
1521     * @throws FTPConnectionClosedException
1522     *      If the FTP server prematurely closes the connection as a result
1523     *      of the client being idle or some other reason causing the server
1524     *      to send FTP reply code 421.  This exception may be caught either
1525     *      as an IOException or independently as itself.
1526     * @throws IOException  If an I/O error occurs while either sending the
1527     *      command or receiving the server reply.
1528     ***/
1529    public int pwd() throws IOException
1530    {
1531        return sendCommand(FTPCmd.PWD);
1532    }
1533
1534    /***
1535     * A convenience method to send the FTP LIST command to the server,
1536     * receive the reply, and return the reply code.  Remember, it is up
1537     * to you to manage the data connection.  If you don't need this low
1538     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1539     * , which will handle all low level details for you.
1540     *
1541     * @return The reply code received from the server.
1542     * @throws FTPConnectionClosedException
1543     *      If the FTP server prematurely closes the connection as a result
1544     *      of the client being idle or some other reason causing the server
1545     *      to send FTP reply code 421.  This exception may be caught either
1546     *      as an IOException or independently as itself.
1547     * @throws IOException  If an I/O error occurs while either sending the
1548     *      command or receiving the server reply.
1549     ***/
1550    public int list() throws IOException
1551    {
1552        return sendCommand(FTPCmd.LIST);
1553    }
1554
1555    /***
1556     * A convenience method to send the FTP LIST command to the server,
1557     * receive the reply, and return the reply code.  Remember, it is up
1558     * to you to manage the data connection.  If you don't need this low
1559     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1560     * , which will handle all low level details for you.
1561     *
1562     * @param pathname  The pathname to list,
1563     * may be {@code null} in which case the command is sent with no parameters
1564     * @return The reply code received from the server.
1565     * @throws FTPConnectionClosedException
1566     *      If the FTP server prematurely closes the connection as a result
1567     *      of the client being idle or some other reason causing the server
1568     *      to send FTP reply code 421.  This exception may be caught either
1569     *      as an IOException or independently as itself.
1570     * @throws IOException  If an I/O error occurs while either sending the
1571     *      command or receiving the server reply.
1572     ***/
1573    public int list(final String pathname) throws IOException
1574    {
1575        return sendCommand(FTPCmd.LIST, pathname);
1576    }
1577
1578    /**
1579     * A convenience method to send the FTP MLSD command to the server,
1580     * receive the reply, and return the reply code.  Remember, it is up
1581     * to you to manage the data connection.  If you don't need this low
1582     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1583     * , which will handle all low level details for you.
1584     *
1585     * @return The reply code received from the server.
1586     * @throws FTPConnectionClosedException
1587     *      If the FTP server prematurely closes the connection as a result
1588     *      of the client being idle or some other reason causing the server
1589     *      to send FTP reply code 421.  This exception may be caught either
1590     *      as an IOException or independently as itself.
1591     * @throws IOException  If an I/O error occurs while either sending the
1592     *      command or receiving the server reply.
1593     * @since 3.0
1594     */
1595    public int mlsd() throws IOException
1596    {
1597        return sendCommand(FTPCmd.MLSD);
1598    }
1599
1600    /**
1601     * A convenience method to send the FTP MLSD command to the server,
1602     * receive the reply, and return the reply code.  Remember, it is up
1603     * to you to manage the data connection.  If you don't need this low
1604     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1605     * , which will handle all low level details for you.
1606     *
1607     * @param path the path to report on
1608     * @return The reply code received from the server,
1609     * may be {@code null} in which case the command is sent with no parameters
1610     * @throws FTPConnectionClosedException
1611     *      If the FTP server prematurely closes the connection as a result
1612     *      of the client being idle or some other reason causing the server
1613     *      to send FTP reply code 421.  This exception may be caught either
1614     *      as an IOException or independently as itself.
1615     * @throws IOException  If an I/O error occurs while either sending the
1616     *      command or receiving the server reply.
1617     * @since 3.0
1618     */
1619    public int mlsd(final String path) throws IOException
1620    {
1621        return sendCommand(FTPCmd.MLSD, path);
1622    }
1623
1624    /**
1625     * A convenience method to send the FTP MLST command to the server,
1626     * receive the reply, and return the reply code.  Remember, it is up
1627     * to you to manage the data connection.  If you don't need this low
1628     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1629     * , which will handle all low level details for you.
1630     *
1631     * @return The reply code received from the server.
1632     * @throws FTPConnectionClosedException
1633     *      If the FTP server prematurely closes the connection as a result
1634     *      of the client being idle or some other reason causing the server
1635     *      to send FTP reply code 421.  This exception may be caught either
1636     *      as an IOException or independently as itself.
1637     * @throws IOException  If an I/O error occurs while either sending the
1638     *      command or receiving the server reply.
1639     * @since 3.0
1640     */
1641    public int mlst() throws IOException
1642    {
1643        return sendCommand(FTPCmd.MLST);
1644    }
1645
1646    /**
1647     * A convenience method to send the FTP MLST command to the server,
1648     * receive the reply, and return the reply code.  Remember, it is up
1649     * to you to manage the data connection.  If you don't need this low
1650     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1651     * , which will handle all low level details for you.
1652     *
1653     * @param path the path to report on
1654     * @return The reply code received from the server,
1655     * may be {@code null} in which case the command is sent with no parameters
1656     * @throws FTPConnectionClosedException
1657     *      If the FTP server prematurely closes the connection as a result
1658     *      of the client being idle or some other reason causing the server
1659     *      to send FTP reply code 421.  This exception may be caught either
1660     *      as an IOException or independently as itself.
1661     * @throws IOException  If an I/O error occurs while either sending the
1662     *      command or receiving the server reply.
1663     * @since 3.0
1664     */
1665    public int mlst(final String path) throws IOException
1666    {
1667        return sendCommand(FTPCmd.MLST, path);
1668    }
1669
1670    /***
1671     * A convenience method to send the FTP NLST command to the server,
1672     * receive the reply, and return the reply code.  Remember, it is up
1673     * to you to manage the data connection.  If you don't need this low
1674     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1675     * , which will handle all low level details for you.
1676     *
1677     * @return The reply code received from the server.
1678     * @throws FTPConnectionClosedException
1679     *      If the FTP server prematurely closes the connection as a result
1680     *      of the client being idle or some other reason causing the server
1681     *      to send FTP reply code 421.  This exception may be caught either
1682     *      as an IOException or independently as itself.
1683     * @throws IOException  If an I/O error occurs while either sending the
1684     *      command or receiving the server reply.
1685     ***/
1686    public int nlst() throws IOException
1687    {
1688        return sendCommand(FTPCmd.NLST);
1689    }
1690
1691    /***
1692     * A convenience method to send the FTP NLST command to the server,
1693     * receive the reply, and return the reply code.  Remember, it is up
1694     * to you to manage the data connection.  If you don't need this low
1695     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1696     * , which will handle all low level details for you.
1697     *
1698     * @param pathname  The pathname to list,
1699     * may be {@code null} in which case the command is sent with no parameters
1700     * @return The reply code received from the server.
1701     * @throws FTPConnectionClosedException
1702     *      If the FTP server prematurely closes the connection as a result
1703     *      of the client being idle or some other reason causing the server
1704     *      to send FTP reply code 421.  This exception may be caught either
1705     *      as an IOException or independently as itself.
1706     * @throws IOException  If an I/O error occurs while either sending the
1707     *      command or receiving the server reply.
1708     ***/
1709    public int nlst(final String pathname) throws IOException
1710    {
1711        return sendCommand(FTPCmd.NLST, pathname);
1712    }
1713
1714    /***
1715     * A convenience method to send the FTP SITE command to the server,
1716     * receive the reply, and return the reply code.
1717     *
1718     * @param parameters  The site parameters to send.
1719     * @return The reply code received from the server.
1720     * @throws FTPConnectionClosedException
1721     *      If the FTP server prematurely closes the connection as a result
1722     *      of the client being idle or some other reason causing the server
1723     *      to send FTP reply code 421.  This exception may be caught either
1724     *      as an IOException or independently as itself.
1725     * @throws IOException  If an I/O error occurs while either sending the
1726     *      command or receiving the server reply.
1727     ***/
1728    public int site(final String parameters) throws IOException
1729    {
1730        return sendCommand(FTPCmd.SITE, parameters);
1731    }
1732
1733    /***
1734     * A convenience method to send the FTP SIZE command to the server,
1735     * receive the reply, and return the reply code.
1736     *
1737     * @param parameters  The site parameters to send.
1738     * @return The reply code received from the server.
1739     * @throws FTPConnectionClosedException
1740     *      If the FTP server prematurely closes the connection as a result
1741     *      of the client being idle or some other reason causing the server
1742     *      to send FTP reply code 421.  This exception may be caught either
1743     *      as an IOException or independently as itself.
1744     * @throws IOException  If an I/O error occurs while either sending the
1745     *      command or receiving the server reply.
1746     * @since 3.7
1747     ***/
1748    public int size(final String parameters) throws IOException
1749    {
1750        return sendCommand(FTPCmd.SIZE, parameters);
1751    }
1752
1753    /***
1754     * A convenience method to send the FTP SYST command to the server,
1755     * receive the reply, and return the reply code.
1756     *
1757     * @return The reply code received from the server.
1758     * @throws FTPConnectionClosedException
1759     *      If the FTP server prematurely closes the connection as a result
1760     *      of the client being idle or some other reason causing the server
1761     *      to send FTP reply code 421.  This exception may be caught either
1762     *      as an IOException or independently as itself.
1763     * @throws IOException  If an I/O error occurs while either sending the
1764     *      command or receiving the server reply.
1765     ***/
1766    public int syst() throws IOException
1767    {
1768        return sendCommand(FTPCmd.SYST);
1769    }
1770
1771    /***
1772     * A convenience method to send the FTP STAT command to the server,
1773     * receive the reply, and return the reply code.
1774     *
1775     * @return The reply code received from the server.
1776     * @throws FTPConnectionClosedException
1777     *      If the FTP server prematurely closes the connection as a result
1778     *      of the client being idle or some other reason causing the server
1779     *      to send FTP reply code 421.  This exception may be caught either
1780     *      as an IOException or independently as itself.
1781     * @throws IOException  If an I/O error occurs while either sending the
1782     *      command or receiving the server reply.
1783     ***/
1784    public int stat() throws IOException
1785    {
1786        return sendCommand(FTPCmd.STAT);
1787    }
1788
1789    /***
1790     * A convenience method to send the FTP STAT command to the server,
1791     * receive the reply, and return the reply code.
1792     *
1793     * @param pathname  A pathname to list.
1794     * @return The reply code received from the server.
1795     * @throws FTPConnectionClosedException
1796     *      If the FTP server prematurely closes the connection as a result
1797     *      of the client being idle or some other reason causing the server
1798     *      to send FTP reply code 421.  This exception may be caught either
1799     *      as an IOException or independently as itself.
1800     * @throws IOException  If an I/O error occurs while either sending the
1801     *      command or receiving the server reply.
1802     ***/
1803    public int stat(final String pathname) throws IOException
1804    {
1805        return sendCommand(FTPCmd.STAT, pathname);
1806    }
1807
1808    /***
1809     * A convenience method to send the FTP HELP command to the server,
1810     * receive the reply, and return the reply code.
1811     *
1812     * @return The reply code received from the server.
1813     * @throws FTPConnectionClosedException
1814     *      If the FTP server prematurely closes the connection as a result
1815     *      of the client being idle or some other reason causing the server
1816     *      to send FTP reply code 421.  This exception may be caught either
1817     *      as an IOException or independently as itself.
1818     * @throws IOException  If an I/O error occurs while either sending the
1819     *      command or receiving the server reply.
1820     ***/
1821    public int help() throws IOException
1822    {
1823        return sendCommand(FTPCmd.HELP);
1824    }
1825
1826    /***
1827     * A convenience method to send the FTP HELP command to the server,
1828     * receive the reply, and return the reply code.
1829     *
1830     * @param command  The command name on which to request help.
1831     * @return The reply code received from the server.
1832     * @throws FTPConnectionClosedException
1833     *      If the FTP server prematurely closes the connection as a result
1834     *      of the client being idle or some other reason causing the server
1835     *      to send FTP reply code 421.  This exception may be caught either
1836     *      as an IOException or independently as itself.
1837     * @throws IOException  If an I/O error occurs while either sending the
1838     *      command or receiving the server reply.
1839     ***/
1840    public int help(final String command) throws IOException
1841    {
1842        return sendCommand(FTPCmd.HELP, command);
1843    }
1844
1845    /***
1846     * A convenience method to send the FTP NOOP command to the server,
1847     * receive the reply, and return the reply code.
1848     *
1849     * @return The reply code received from the server.
1850     * @throws FTPConnectionClosedException
1851     *      If the FTP server prematurely closes the connection as a result
1852     *      of the client being idle or some other reason causing the server
1853     *      to send FTP reply code 421.  This exception may be caught either
1854     *      as an IOException or independently as itself.
1855     * @throws IOException  If an I/O error occurs while either sending the
1856     *      command or receiving the server reply.
1857     ***/
1858    public int noop() throws IOException
1859    {
1860        return sendCommand(FTPCmd.NOOP);
1861    }
1862
1863    /**
1864     * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2.
1865     * @return True if strict, false if lenient
1866     * @since 2.0
1867     */
1868    public boolean isStrictMultilineParsing() {
1869        return strictMultilineParsing;
1870    }
1871
1872    /**
1873     * Set strict multiline parsing.
1874     * @param strictMultilineParsing the setting
1875     * @since 2.0
1876     */
1877    public void setStrictMultilineParsing(final boolean strictMultilineParsing) {
1878        this.strictMultilineParsing = strictMultilineParsing;
1879    }
1880
1881    /**
1882     * Return whether strict non-multiline parsing is enabled, as per RFC 959, section 4.2.
1883     * <p>
1884     * The default is true, which requires the 3 digit code be followed by space and some text.
1885     * <br>
1886     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1887     * <br>
1888     * @return True if strict (default), false if additional checks are not made
1889     * @since 3.6
1890     */
1891    public boolean isStrictReplyParsing() {
1892        return strictReplyParsing;
1893    }
1894
1895    /**
1896     * Set strict non-multiline parsing.
1897     * <p>
1898     * If true, it requires the 3 digit code be followed by space and some text.
1899     * <br>
1900     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1901     * <p>
1902     * <b>This should not be required by a well-behaved FTP server</b>
1903     * <br>
1904     * @param strictReplyParsing the setting
1905     * @since 3.6
1906     */
1907    public void setStrictReplyParsing(final boolean strictReplyParsing) {
1908        this.strictReplyParsing = strictReplyParsing;
1909    }
1910
1911    /**
1912     * Provide command support to super-class
1913     */
1914    @Override
1915    protected ProtocolCommandSupport getCommandSupport() {
1916        return _commandSupport_;
1917    }
1918}
1919
1920/* Emacs configuration
1921 * Local variables:        **
1922 * mode:             java  **
1923 * c-basic-offset:   4     **
1924 * indent-tabs-mode: nil   **
1925 * End:                    **
1926 */