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;
036import org.apache.commons.net.util.NetConstants;
037
038/**
039 * FTP provides the basic the functionality necessary to implement your
040 * own FTP client.  It extends org.apache.commons.net.SocketClient since
041 * extending TelnetClient was causing unwanted behavior (like connections
042 * that did not time out properly).
043 * <p>
044 * To derive the full benefits of the FTP class requires some knowledge
045 * of the FTP protocol defined in RFC 959.  However, there is no reason
046 * why you should have to use the FTP class.  The
047 * {@link org.apache.commons.net.ftp.FTPClient} class,
048 * derived from FTP,
049 * implements all the functionality required of an FTP client.  The
050 * FTP class is made public to provide access to various FTP constants
051 * and to make it easier for adventurous programmers (or those with
052 * special needs) to interact with the FTP protocol and implement their
053 * own clients.  A set of methods with names corresponding to the FTP
054 * command names are provided to facilitate this interaction.
055 * <p>
056 * You should keep in mind that the FTP server may choose to prematurely
057 * close a connection if the client has been idle for longer than a
058 * given time period (usually 900 seconds).  The FTP class will detect a
059 * premature FTP server connection closing when it receives a
060 * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
061 *  response to a command.
062 * When that occurs, the FTP class method encountering that reply will throw
063 * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
064 * .  <code>FTPConectionClosedException</code>
065 * is a subclass of <code> IOException </code> and therefore need not be
066 * caught separately, but if you are going to catch it separately, its
067 * catch block must appear before the more general <code> IOException </code>
068 * catch block.  When you encounter an
069 * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
070 * , you must disconnect the connection with
071 * {@link #disconnect  disconnect() } to properly clean up the
072 * system resources used by FTP.  Before disconnecting, you may check the
073 * last reply code and text with
074 * {@link #getReplyCode  getReplyCode },
075 * {@link #getReplyString  getReplyString },
076 * and {@link #getReplyStrings  getReplyStrings}.
077 * You may avoid server disconnections while the client is idle by
078 * periodicaly sending NOOP commands to the server.
079 * <p>
080 * Rather than list it separately for each method, we mention here that
081 * every method communicating with the server and throwing an IOException
082 * can also throw a
083 * {@link org.apache.commons.net.MalformedServerReplyException}
084 * , which is a subclass
085 * of IOException.  A MalformedServerReplyException will be thrown when
086 * the reply received from the server deviates enough from the protocol
087 * specification that it cannot be interpreted in a useful manner despite
088 * attempts to be as lenient as possible.
089 *
090 * @see FTPClient
091 * @see FTPConnectionClosedException
092 * @see org.apache.commons.net.MalformedServerReplyException
093 */
094
095public class FTP extends SocketClient
096{
097    /** The default FTP data port (20). */
098    public static final int DEFAULT_DATA_PORT = 20;
099    /** The default FTP control port (21). */
100    public static final int DEFAULT_PORT = 21;
101
102    /**
103     * A constant used to indicate the file(s) being transferred should
104     * be treated as ASCII.  This is the default file type.  All constants
105     * ending in <code>FILE_TYPE</code> are used to indicate file types.
106     */
107    public static final int ASCII_FILE_TYPE = 0;
108
109    /**
110     * A constant used to indicate the file(s) being transferred should
111     * be treated as EBCDIC.  Note however that there are several different
112     * EBCDIC formats.  All constants ending in <code>FILE_TYPE</code>
113     * are used to indicate file types.
114     */
115    public static final int EBCDIC_FILE_TYPE = 1;
116
117
118    /**
119     * A constant used to indicate the file(s) being transferred should
120     * be treated as a binary image, i.e., no translations should be
121     * performed.  All constants ending in <code>FILE_TYPE</code> are used to
122     * indicate file types.
123     */
124    public static final int BINARY_FILE_TYPE = 2;
125
126    /**
127     * A constant used to indicate the file(s) being transferred should
128     * be treated as a local type.  All constants ending in
129     * <code>FILE_TYPE</code> are used to indicate file types.
130     */
131    public static final int LOCAL_FILE_TYPE = 3;
132
133    /**
134     * A constant used for text files to indicate a non-print text format.
135     * This is the default format.
136     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
137     * text formatting for text transfers (both ASCII and EBCDIC).
138     */
139    public static final int NON_PRINT_TEXT_FORMAT = 4;
140
141    /**
142     * A constant used to indicate a text file contains format vertical format
143     * control characters.
144     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
145     * text formatting for text transfers (both ASCII and EBCDIC).
146     */
147    public static final int TELNET_TEXT_FORMAT = 5;
148
149    /**
150     * A constant used to indicate a text file contains ASA vertical format
151     * control characters.
152     * All constants ending in <code>TEXT_FORMAT</code> are used to indicate
153     * text formatting for text transfers (both ASCII and EBCDIC).
154     */
155    public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
156
157    /**
158     * A constant used to indicate a file is to be treated as a continuous
159     * sequence of bytes.  This is the default structure.  All constants ending
160     * in <code>_STRUCTURE</code> are used to indicate file structure for
161     * file transfers.
162     */
163    public static final int FILE_STRUCTURE = 7;
164
165    /**
166     * A constant used to indicate a file is to be treated as a sequence
167     * of records.  All constants ending in <code>_STRUCTURE</code>
168     * are used to indicate file structure for file transfers.
169     */
170    public static final int RECORD_STRUCTURE = 8;
171
172    /**
173     * A constant used to indicate a file is to be treated as a set of
174     * independent indexed pages.  All constants ending in
175     * <code>_STRUCTURE</code> are used to indicate file structure for file
176     * transfers.
177     */
178    public static final int PAGE_STRUCTURE = 9;
179
180    /**
181     * A constant used to indicate a file is to be transferred as a stream
182     * of bytes.  This is the default transfer mode.  All constants ending
183     * in <code>TRANSFER_MODE</code> are used to indicate file transfer
184     * modes.
185     */
186    public static final int STREAM_TRANSFER_MODE = 10;
187
188    /**
189     * A constant used to indicate a file is to be transferred as a series
190     * of blocks.  All constants ending in <code>TRANSFER_MODE</code> are used
191     * to indicate file transfer modes.
192     */
193    public static final int BLOCK_TRANSFER_MODE = 11;
194
195    /**
196     * A constant used to indicate a file is to be transferred as FTP
197     * compressed data.  All constants ending in <code>TRANSFER_MODE</code>
198     * are used to indicate file transfer modes.
199     */
200    public static final int COMPRESSED_TRANSFER_MODE = 12;
201
202    // We have to ensure that the protocol communication is in ASCII
203    // but we use ISO-8859-1 just in case 8-bit characters cross
204    // the wire.
205    /**
206     * The default character encoding used for communicating over an
207     * FTP control connection.  The default encoding is an
208     * ASCII-compatible encoding.  Some FTP servers expect other
209     * encodings.  You can change the encoding used by an FTP instance
210     * with {@link #setControlEncoding setControlEncoding}.
211     */
212    public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1";
213
214    /** Length of the FTP reply code (3 alphanumerics) */
215    public static final int REPLY_CODE_LEN = 3;
216
217    private static final String modes = "AEILNTCFRPSBC";
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 the 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;
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        setDefaultPort(DEFAULT_PORT);
271        _replyLines = new ArrayList<>();
272        _newReplyString = false;
273        _replyString = null;
274        _controlEncoding = DEFAULT_CONTROL_ENCODING;
275        _commandSupport_ = new ProtocolCommandSupport(this);
276    }
277
278    // The RFC-compliant multiline termination check
279    private boolean strictCheck(final String line, final String code) {
280        return !(line.startsWith(code) && line.charAt(REPLY_CODE_LEN) == ' ');
281    }
282
283    // The strict check is too strong a condition because of non-conforming ftp
284    // servers like ftp.funet.fi which sent 226 as the last line of a
285    // 426 multi-line reply in response to ls /.  We relax the condition to
286    // test that the line starts with a digit rather than starting with
287    // the code.
288    private boolean lenientCheck(final String line) {
289        return !(line.length() > REPLY_CODE_LEN&& line.charAt(REPLY_CODE_LEN) != '-' &&
290                Character.isDigit(line.charAt(0)));
291    }
292
293    /**
294     * Get the reply, but don't pass it to command listeners.
295     * Used for keep-alive processing only.
296     * @since 3.0
297     * @throws IOException on error
298     */
299    protected void __getReplyNoReport()  throws IOException
300    {
301        getReply(false);
302    }
303
304    private int getReply(final boolean reportReply) throws IOException
305    {
306        final int length;
307
308        _newReplyString = true;
309        _replyLines.clear();
310
311        String line = _controlInput_.readLine();
312
313        if (line == null) {
314            throw new FTPConnectionClosedException(
315                    "Connection closed without indication.");
316        }
317
318        // In case we run into an anomaly we don't want fatal index exceptions
319        // to be thrown.
320        length = line.length();
321        if (length < REPLY_CODE_LEN) {
322            throw new MalformedServerReplyException(
323                "Truncated server reply: " + line);
324        }
325
326        String code = null;
327        try
328        {
329            code = line.substring(0, REPLY_CODE_LEN);
330            _replyCode = Integer.parseInt(code);
331        }
332        catch (final NumberFormatException e)
333        {
334            throw new MalformedServerReplyException(
335                "Could not parse response code.\nServer Reply: " + line);
336        }
337
338        _replyLines.add(line);
339
340        // Check the server reply type
341        if (length > REPLY_CODE_LEN) {
342            final char sep = line.charAt(REPLY_CODE_LEN);
343            // Get extra lines if message continues.
344            if (sep == '-') {
345                do
346                {
347                    line = _controlInput_.readLine();
348
349                    if (line == null) {
350                        throw new FTPConnectionClosedException(
351                            "Connection closed without indication.");
352                    }
353
354                    _replyLines.add(line);
355
356                    // The length() check handles problems that could arise from readLine()
357                    // returning too soon after encountering a naked CR or some other
358                    // anomaly.
359                }
360                while ( isStrictMultilineParsing() ? strictCheck(line, code) : lenientCheck(line));
361
362            } else if (isStrictReplyParsing()) {
363                if (length == REPLY_CODE_LEN + 1) { // expecting some text
364                    throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
365                } else if (sep != ' ') {
366                    throw new MalformedServerReplyException("Invalid server reply: '" + line +"'");
367                }
368            }
369        } else if (isStrictReplyParsing()) {
370            throw new MalformedServerReplyException("Truncated server reply: '" + line +"'");
371        }
372
373        if (reportReply) {
374            fireReplyReceived(_replyCode, getReplyString());
375        }
376
377        if (_replyCode == FTPReply.SERVICE_NOT_AVAILABLE) {
378            throw new FTPConnectionClosedException("FTP response 421 received.  Server closed connection.");
379        }
380        return _replyCode;
381    }
382
383    /**
384     * Initiates control connections and gets initial reply.
385     * Initializes {@link #_controlInput_} and {@link #_controlOutput_}.
386     */
387    @Override
388    protected void _connectAction_() throws IOException
389    {
390        _connectAction_(null);
391    }
392
393
394    /**
395     * Initiates control connections and gets initial reply.
396     * Initializes {@link #_controlInput_} and {@link #_controlOutput_}.
397     *
398     * @param socketIsReader the reader to reuse (if non-null)
399     * @throws IOException on error
400     * @since 3.4
401     */
402    protected void _connectAction_(final Reader socketIsReader) throws IOException {
403        super._connectAction_(); // sets up _input_ and _output_
404        if(socketIsReader == null) {
405            _controlInput_ =
406                    new CRLFLineReader(new InputStreamReader(_input_, getControlEncoding()));
407        } else {
408            _controlInput_ = new CRLFLineReader(socketIsReader);
409        }
410        _controlOutput_ =
411            new BufferedWriter(new OutputStreamWriter(_output_, getControlEncoding()));
412        if (connectTimeout > 0) { // NET-385
413            final int original = _socket_.getSoTimeout();
414            _socket_.setSoTimeout(connectTimeout);
415            try {
416                getReply();
417                // If we received code 120, we have to fetch completion reply.
418                if (FTPReply.isPositivePreliminary(_replyCode)) {
419                    getReply();
420                }
421            } catch (final SocketTimeoutException e) {
422                final IOException ioe = new IOException("Timed out waiting for initial connect reply");
423                ioe.initCause(e);
424                throw ioe;
425            } finally {
426                _socket_.setSoTimeout(original);
427            }
428        } else {
429            getReply();
430            // If we received code 120, we have to fetch completion reply.
431            if (FTPReply.isPositivePreliminary(_replyCode)) {
432                getReply();
433            }
434        }
435    }
436
437
438    /**
439     * Saves the character encoding to be used by the FTP control connection.
440     * Some FTP servers require that commands be issued in a non-ASCII
441     * encoding like UTF-8 so that file names with multi-byte character
442     * representations (e.g, Big 8) can be specified.
443     * <p>
444     * Please note that this has to be set before the connection is established.
445     *
446     * @param encoding The new character encoding for the control connection.
447     */
448    public void setControlEncoding(final String encoding) {
449        _controlEncoding = encoding;
450    }
451
452
453    /**
454     * @return The character encoding used to communicate over the
455     * control connection.
456     */
457    public String getControlEncoding() {
458        return _controlEncoding;
459    }
460
461
462    /**
463     * Closes the control connection to the FTP server and sets to null
464     * some internal data so that the memory may be reclaimed by the
465     * garbage collector.  The reply text and code information from the
466     * last command is voided so that the memory it used may be reclaimed.
467     * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
468     *
469     * @throws IOException If an error occurs while disconnecting.
470     */
471    @Override
472    public void disconnect() throws IOException
473    {
474        super.disconnect();
475        _controlInput_ = null;
476        _controlOutput_ = null;
477        _newReplyString = false;
478        _replyString = null;
479    }
480
481
482    /**
483     * Sends an FTP command to the server, waits for a reply and returns the
484     * numerical response code.  After invocation, for more detailed
485     * information, the actual reply text can be accessed by calling
486     * {@link #getReplyString  getReplyString } or
487     * {@link #getReplyStrings  getReplyStrings }.
488     *
489     * @param command  The text representation of the  FTP command to send.
490     * @param args The arguments to the FTP command.  If this parameter is
491     *             set to null, then the command is sent with no argument.
492     * @return The integer value of the FTP reply code returned by the server
493     *         in response to the command.
494     * @throws FTPConnectionClosedException
495     *      If the FTP server prematurely closes the connection as a result
496     *      of the client being idle or some other reason causing the server
497     *      to send FTP reply code 421.  This exception may be caught either
498     *      as an IOException or independently as itself.
499     * @throws IOException  If an I/O error occurs while either sending the
500     *      command or receiving the server reply.
501     */
502    public int sendCommand(final String command, final String args) throws IOException
503    {
504        if (_controlOutput_ == null) {
505            throw new IOException("Connection is not open");
506        }
507
508        final String message = buildMessage(command, args);
509
510        send(message);
511
512        fireCommandSent(command, message);
513
514        return getReply();
515    }
516
517    private String buildMessage(final String command, final String args) {
518        final StringBuilder __commandBuffer = new StringBuilder();
519
520        __commandBuffer.append(command);
521
522        if (args != null)
523        {
524            __commandBuffer.append(' ');
525            __commandBuffer.append(args);
526        }
527        __commandBuffer.append(SocketClient.NETASCII_EOL);
528        return __commandBuffer.toString();
529    }
530
531    private void send(final String message) throws IOException,
532            FTPConnectionClosedException, SocketException {
533        try{
534            _controlOutput_.write(message);
535            _controlOutput_.flush();
536        }
537        catch (final SocketException e)
538        {
539            if (!isConnected())
540            {
541                throw new FTPConnectionClosedException("Connection unexpectedly closed.");
542            }
543            throw e;
544        }
545    }
546
547    /**
548     * Send a noop and get the reply without reporting to the command listener.
549     * Intended for use with keep-alive.
550     *
551     * @throws IOException on error
552     * @since 3.0
553     */
554    protected void __noop() throws IOException {
555        final String msg = buildMessage(FTPCmd.NOOP.getCommand(), null);
556        send(msg);
557        __getReplyNoReport(); // This may timeout
558    }
559
560    /**
561     * Sends an FTP command to the server, waits for a reply and returns the
562     * numerical response code.  After invocation, for more detailed
563     * information, the actual reply text can be accessed by calling
564     * {@link #getReplyString  getReplyString } or
565     * {@link #getReplyStrings  getReplyStrings }.
566     *
567     * @param command  The FTPCommand constant corresponding to the FTP command
568     *                 to send.
569     * @param args The arguments to the FTP command.  If this parameter is
570     *             set to null, then the command is sent with no argument.
571     * @return The integer value of the FTP reply code returned by the server
572     *         in response to the command.
573     * @throws FTPConnectionClosedException
574     *      If the FTP server prematurely closes the connection as a result
575     *      of the client being idle or some other reason causing the server
576     *      to send FTP reply code 421.  This exception may be caught either
577     *      as an IOException or independently as itself.
578     * @throws IOException  If an I/O error occurs while either sending the
579     *      command or receiving the server reply.
580     * @deprecated (3.3) Use {@link #sendCommand(FTPCmd, String)} instead
581     */
582    @Deprecated
583    public int sendCommand(final int command, final String args) throws IOException
584    {
585        return sendCommand(FTPCommand.getCommand(command), args);
586    }
587
588    /**
589     * Sends an FTP command to the server, waits for a reply and returns the
590     * numerical response code.  After invocation, for more detailed
591     * information, the actual reply text can be accessed by calling
592     * {@link #getReplyString  getReplyString } or
593     * {@link #getReplyStrings  getReplyStrings }.
594     *
595     * @param command  The FTPCmd enum corresponding to the FTP command
596     *                 to send.
597     * @return The integer value of the FTP reply code returned by the server
598     *         in response to the command.
599     * @throws FTPConnectionClosedException
600     *      If the FTP server prematurely closes the connection as a result
601     *      of the client being idle or some other reason causing the server
602     *      to send FTP reply code 421.  This exception may be caught either
603     *      as an IOException or independently as itself.
604     * @throws IOException  If an I/O error occurs while either sending the
605     *      command or receiving the server reply.
606     * @since 3.3
607     */
608    public int sendCommand(final FTPCmd command)  throws IOException{
609        return sendCommand(command, null);
610    }
611
612    /**
613     * Sends an FTP command to the server, waits for a reply and returns the
614     * numerical response code.  After invocation, for more detailed
615     * information, the actual reply text can be accessed by calling
616     * {@link #getReplyString  getReplyString } or
617     * {@link #getReplyStrings  getReplyStrings }.
618     *
619     * @param command  The FTPCmd enum corresponding to the FTP command
620     *                 to send.
621     * @param args The arguments to the FTP command.  If this parameter is
622     *             set to null, then the command is sent with no argument.
623     * @return The integer value of the FTP reply code returned by the server
624     *         in response to the command.
625     * @throws FTPConnectionClosedException
626     *      If the FTP server prematurely closes the connection as a result
627     *      of the client being idle or some other reason causing the server
628     *      to send FTP reply code 421.  This exception may be caught either
629     *      as an IOException or independently as itself.
630     * @throws IOException  If an I/O error occurs while either sending the
631     *      command or receiving the server reply.
632     * @since 3.3
633     */
634    public int sendCommand(final FTPCmd command, final String args)  throws IOException{
635        return sendCommand(command.getCommand(), args);
636    }
637
638    /**
639     * Sends an FTP command with no arguments to the server, waits for a
640     * reply and returns the numerical response code.  After invocation, for
641     * more detailed information, the actual reply text can be accessed by
642     * calling {@link #getReplyString  getReplyString } or
643     * {@link #getReplyStrings  getReplyStrings }.
644     *
645     * @param command  The text representation of the  FTP command to send.
646     * @return The integer value of the FTP reply code returned by the server
647     *         in response to the command.
648     * @throws FTPConnectionClosedException
649     *      If the FTP server prematurely closes the connection as a result
650     *      of the client being idle or some other reason causing the server
651     *      to send FTP reply code 421.  This exception may be caught either
652     *      as an IOException or independently as itself.
653     * @throws IOException  If an I/O error occurs while either sending the
654     *      command or receiving the server reply.
655     */
656    public int sendCommand(final String command) throws IOException
657    {
658        return sendCommand(command, null);
659    }
660
661
662    /**
663     * Sends an FTP command with no arguments to the server, waits for a
664     * reply and returns the numerical response code.  After invocation, for
665     * more detailed information, the actual reply text can be accessed by
666     * calling {@link #getReplyString  getReplyString } or
667     * {@link #getReplyStrings  getReplyStrings }.
668     *
669     * @param command  The FTPCommand constant corresponding to the FTP command
670     *                 to send.
671     * @return The integer value of the FTP reply code returned by the server
672     *         in response to the command.
673     * @throws FTPConnectionClosedException
674     *      If the FTP server prematurely closes the connection as a result
675     *      of the client being idle or some other reason causing the server
676     *      to send FTP reply code 421.  This exception may be caught either
677     *      as an IOException or independently as itself.
678     * @throws IOException  If an I/O error occurs while either sending the
679     *      command or receiving the server reply.
680     */
681    public int sendCommand(final int command) throws IOException
682    {
683        return sendCommand(command, null);
684    }
685
686
687    /**
688     * Returns the integer value of the reply code of the last FTP reply.
689     * You will usually only use this method after you connect to the
690     * FTP server to check that the connection was successful since
691     * <code> connect </code> is of type void.
692     *
693     * @return The integer value of the reply code of the last FTP reply.
694     */
695    public int getReplyCode()
696    {
697        return _replyCode;
698    }
699
700    /**
701     * Fetches a reply from the FTP server and returns the integer reply
702     * code.  After calling this method, the actual reply text can be accessed
703     * from either  calling {@link #getReplyString  getReplyString } or
704     * {@link #getReplyStrings  getReplyStrings }.  Only use this
705     * method if you are implementing your own FTP client or if you need to
706     * fetch a secondary response from the FTP server.
707     *
708     * @return The integer value of the reply code of the fetched FTP reply.
709     * @throws FTPConnectionClosedException
710     *      If the FTP server prematurely closes the connection as a result
711     *      of the client being idle or some other reason causing the server
712     *      to send FTP reply code 421.  This exception may be caught either
713     *      as an IOException or independently as itself.
714     * @throws IOException  If an I/O error occurs while receiving the
715     *                         server reply.
716     */
717    public int getReply() throws IOException
718    {
719        return getReply(true);
720    }
721
722
723    /**
724     * Returns the lines of text from the last FTP server response as an array
725     * of strings, one entry per line.  The end of line markers of each are
726     * stripped from each line.
727     *
728     * @return The lines of text from the last FTP response as an array.
729     */
730    public String[] getReplyStrings()
731    {
732        return _replyLines.toArray(NetConstants.EMPTY_STRING_ARRAY);
733    }
734
735    /**
736     * Returns the nth line of text from the last FTP server response as a string. The end of line markers of each are
737     * stripped from the line.
738     *
739     * @param index The index of the line to return, 0-based.
740     *
741     * @return The lines of text from the last FTP response as an array.
742     */
743    String getReplyString(final int index)
744    {
745        return _replyLines.get(index);
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        final StringBuilder buffer;
758
759        if (!_newReplyString) {
760            return _replyString;
761        }
762
763        buffer = new StringBuilder(256);
764
765        for (final 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(final 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(final 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(final 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(final 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(final 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(final InetAddress host, final int port) throws IOException
959    {
960        int num;
961        final 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(final InetAddress host, final int port) throws IOException
999    {
1000        final int num;
1001        final 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(final int fileType, final int formatOrByteSize) throws IOException
1086    {
1087        final 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(final 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(final 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(final 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(final 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(final 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(final 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(final 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(final 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(final 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(final int bytes, final 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(final long bytes, final 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(final String marker) throws IOException
1384    {
1385        return sendCommand(FTPCmd.REST, marker);
1386    }
1387
1388
1389    /**
1390     * Sends the MDTM command for the given file.
1391     *
1392     * @param file name of file
1393     * @return the status
1394     * @throws IOException on error
1395     * @since 2.0
1396     **/
1397    public int mdtm(final String file) throws IOException
1398    {
1399        return sendCommand(FTPCmd.MDTM, file);
1400    }
1401
1402
1403    /**
1404     * A convenience method to send the FTP MFMT command to the server,
1405     * receive the reply, and return the reply code.
1406     *
1407     * @param pathname The pathname for which mtime is to be changed
1408     * @param timeval Timestamp in <code>YYYYMMDDhhmmss</code> format
1409     * @return The reply code received from the server.
1410     * @throws FTPConnectionClosedException
1411     *      If the FTP server prematurely closes the connection as a result
1412     *      of the client being idle or some other reason causing the server
1413     *      to send FTP reply code 421.  This exception may be caught either
1414     *      as an IOException or independently as itself.
1415     * @throws IOException  If an I/O error occurs while either sending the
1416     *      command or receiving the server reply.
1417     * @since 2.2
1418     * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a>
1419     **/
1420    public int mfmt(final String pathname, final String timeval) throws IOException
1421    {
1422        return sendCommand(FTPCmd.MFMT, timeval + " " + pathname);
1423    }
1424
1425
1426    /**
1427     * A convenience method to send the FTP RNFR command to the server,
1428     * receive the reply, and return the reply code.
1429     *
1430     * @param pathname The pathname to rename from.
1431     * @return The reply code received from the server.
1432     * @throws FTPConnectionClosedException
1433     *      If the FTP server prematurely closes the connection as a result
1434     *      of the client being idle or some other reason causing the server
1435     *      to send FTP reply code 421.  This exception may be caught either
1436     *      as an IOException or independently as itself.
1437     * @throws IOException  If an I/O error occurs while either sending the
1438     *      command or receiving the server reply.
1439     */
1440    public int rnfr(final String pathname) throws IOException
1441    {
1442        return sendCommand(FTPCmd.RNFR, pathname);
1443    }
1444
1445    /**
1446     * A convenience method to send the FTP RNTO command to the server,
1447     * receive the reply, and return the reply code.
1448     *
1449     * @param pathname The pathname to rename to
1450     * @return The reply code received from the server.
1451     * @throws FTPConnectionClosedException
1452     *      If the FTP server prematurely closes the connection as a result
1453     *      of the client being idle or some other reason causing the server
1454     *      to send FTP reply code 421.  This exception may be caught either
1455     *      as an IOException or independently as itself.
1456     * @throws IOException  If an I/O error occurs while either sending the
1457     *      command or receiving the server reply.
1458     */
1459    public int rnto(final String pathname) throws IOException
1460    {
1461        return sendCommand(FTPCmd.RNTO, pathname);
1462    }
1463
1464    /**
1465     * A convenience method to send the FTP DELE command to the server,
1466     * receive the reply, and return the reply code.
1467     *
1468     * @param pathname The pathname to delete.
1469     * @return The reply code received from the server.
1470     * @throws FTPConnectionClosedException
1471     *      If the FTP server prematurely closes the connection as a result
1472     *      of the client being idle or some other reason causing the server
1473     *      to send FTP reply code 421.  This exception may be caught either
1474     *      as an IOException or independently as itself.
1475     * @throws IOException  If an I/O error occurs while either sending the
1476     *      command or receiving the server reply.
1477     */
1478    public int dele(final String pathname) throws IOException
1479    {
1480        return sendCommand(FTPCmd.DELE, pathname);
1481    }
1482
1483    /**
1484     * A convenience method to send the FTP RMD command to the server,
1485     * receive the reply, and return the reply code.
1486     *
1487     * @param pathname The pathname of the directory to remove.
1488     * @return The reply code received from the server.
1489     * @throws FTPConnectionClosedException
1490     *      If the FTP server prematurely closes the connection as a result
1491     *      of the client being idle or some other reason causing the server
1492     *      to send FTP reply code 421.  This exception may be caught either
1493     *      as an IOException or independently as itself.
1494     * @throws IOException  If an I/O error occurs while either sending the
1495     *      command or receiving the server reply.
1496     */
1497    public int rmd(final String pathname) throws IOException
1498    {
1499        return sendCommand(FTPCmd.RMD, pathname);
1500    }
1501
1502    /**
1503     * A convenience method to send the FTP MKD command to the server,
1504     * receive the reply, and return the reply code.
1505     *
1506     * @param pathname The pathname of the new directory to create.
1507     * @return The reply code received from the server.
1508     * @throws FTPConnectionClosedException
1509     *      If the FTP server prematurely closes the connection as a result
1510     *      of the client being idle or some other reason causing the server
1511     *      to send FTP reply code 421.  This exception may be caught either
1512     *      as an IOException or independently as itself.
1513     * @throws IOException  If an I/O error occurs while either sending the
1514     *      command or receiving the server reply.
1515     */
1516    public int mkd(final String pathname) throws IOException
1517    {
1518        return sendCommand(FTPCmd.MKD, pathname);
1519    }
1520
1521    /**
1522     * A convenience method to send the FTP PWD command to the server,
1523     * receive the reply, and return the reply code.
1524     *
1525     * @return The reply code received from the server.
1526     * @throws FTPConnectionClosedException
1527     *      If the FTP server prematurely closes the connection as a result
1528     *      of the client being idle or some other reason causing the server
1529     *      to send FTP reply code 421.  This exception may be caught either
1530     *      as an IOException or independently as itself.
1531     * @throws IOException  If an I/O error occurs while either sending the
1532     *      command or receiving the server reply.
1533     */
1534    public int pwd() throws IOException
1535    {
1536        return sendCommand(FTPCmd.PWD);
1537    }
1538
1539    /**
1540     * A convenience method to send the FTP LIST command to the server,
1541     * receive the reply, and return the reply code.  Remember, it is up
1542     * to you to manage the data connection.  If you don't need this low
1543     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1544     * , which will handle all low level details for you.
1545     *
1546     * @return The reply code received from the server.
1547     * @throws FTPConnectionClosedException
1548     *      If the FTP server prematurely closes the connection as a result
1549     *      of the client being idle or some other reason causing the server
1550     *      to send FTP reply code 421.  This exception may be caught either
1551     *      as an IOException or independently as itself.
1552     * @throws IOException  If an I/O error occurs while either sending the
1553     *      command or receiving the server reply.
1554     */
1555    public int list() throws IOException
1556    {
1557        return sendCommand(FTPCmd.LIST);
1558    }
1559
1560    /**
1561     * A convenience method to send the FTP LIST command to the server,
1562     * receive the reply, and return the reply code.  Remember, it is up
1563     * to you to manage the data connection.  If you don't need this low
1564     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1565     * , which will handle all low level details for you.
1566     *
1567     * @param pathname  The pathname to list,
1568     * may be {@code null} in which case the command is sent with no parameters
1569     * @return The reply code received from the server.
1570     * @throws FTPConnectionClosedException
1571     *      If the FTP server prematurely closes the connection as a result
1572     *      of the client being idle or some other reason causing the server
1573     *      to send FTP reply code 421.  This exception may be caught either
1574     *      as an IOException or independently as itself.
1575     * @throws IOException  If an I/O error occurs while either sending the
1576     *      command or receiving the server reply.
1577     */
1578    public int list(final String pathname) throws IOException
1579    {
1580        return sendCommand(FTPCmd.LIST, pathname);
1581    }
1582
1583    /**
1584     * A convenience method to send the FTP MLSD command to the server,
1585     * receive the reply, and return the reply code.  Remember, it is up
1586     * to you to manage the data connection.  If you don't need this low
1587     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1588     * , which will handle all low level details for you.
1589     *
1590     * @return The reply code received from the server.
1591     * @throws FTPConnectionClosedException
1592     *      If the FTP server prematurely closes the connection as a result
1593     *      of the client being idle or some other reason causing the server
1594     *      to send FTP reply code 421.  This exception may be caught either
1595     *      as an IOException or independently as itself.
1596     * @throws IOException  If an I/O error occurs while either sending the
1597     *      command or receiving the server reply.
1598     * @since 3.0
1599     */
1600    public int mlsd() throws IOException
1601    {
1602        return sendCommand(FTPCmd.MLSD);
1603    }
1604
1605    /**
1606     * A convenience method to send the FTP MLSD command to the server,
1607     * receive the reply, and return the reply code.  Remember, it is up
1608     * to you to manage the data connection.  If you don't need this low
1609     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1610     * , which will handle all low level details for you.
1611     *
1612     * @param path the path to report on
1613     * @return The reply code received from the server,
1614     * may be {@code null} in which case the command is sent with no parameters
1615     * @throws FTPConnectionClosedException
1616     *      If the FTP server prematurely closes the connection as a result
1617     *      of the client being idle or some other reason causing the server
1618     *      to send FTP reply code 421.  This exception may be caught either
1619     *      as an IOException or independently as itself.
1620     * @throws IOException  If an I/O error occurs while either sending the
1621     *      command or receiving the server reply.
1622     * @since 3.0
1623     */
1624    public int mlsd(final String path) throws IOException
1625    {
1626        return sendCommand(FTPCmd.MLSD, path);
1627    }
1628
1629    /**
1630     * A convenience method to send the FTP MLST command to the server,
1631     * receive the reply, and return the reply code.  Remember, it is up
1632     * to you to manage the data connection.  If you don't need this low
1633     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1634     * , which will handle all low level details for you.
1635     *
1636     * @return The reply code received from the server.
1637     * @throws FTPConnectionClosedException
1638     *      If the FTP server prematurely closes the connection as a result
1639     *      of the client being idle or some other reason causing the server
1640     *      to send FTP reply code 421.  This exception may be caught either
1641     *      as an IOException or independently as itself.
1642     * @throws IOException  If an I/O error occurs while either sending the
1643     *      command or receiving the server reply.
1644     * @since 3.0
1645     */
1646    public int mlst() throws IOException
1647    {
1648        return sendCommand(FTPCmd.MLST);
1649    }
1650
1651    /**
1652     * A convenience method to send the FTP MLST command to the server,
1653     * receive the reply, and return the reply code.  Remember, it is up
1654     * to you to manage the data connection.  If you don't need this low
1655     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1656     * , which will handle all low level details for you.
1657     *
1658     * @param path the path to report on
1659     * @return The reply code received from the server,
1660     * may be {@code null} in which case the command is sent with no parameters
1661     * @throws FTPConnectionClosedException
1662     *      If the FTP server prematurely closes the connection as a result
1663     *      of the client being idle or some other reason causing the server
1664     *      to send FTP reply code 421.  This exception may be caught either
1665     *      as an IOException or independently as itself.
1666     * @throws IOException  If an I/O error occurs while either sending the
1667     *      command or receiving the server reply.
1668     * @since 3.0
1669     */
1670    public int mlst(final String path) throws IOException
1671    {
1672        return sendCommand(FTPCmd.MLST, path);
1673    }
1674
1675    /**
1676     * A convenience method to send the FTP NLST command to the server,
1677     * receive the reply, and return the reply code.  Remember, it is up
1678     * to you to manage the data connection.  If you don't need this low
1679     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1680     * , which will handle all low level details for you.
1681     *
1682     * @return The reply code received from the server.
1683     * @throws FTPConnectionClosedException
1684     *      If the FTP server prematurely closes the connection as a result
1685     *      of the client being idle or some other reason causing the server
1686     *      to send FTP reply code 421.  This exception may be caught either
1687     *      as an IOException or independently as itself.
1688     * @throws IOException  If an I/O error occurs while either sending the
1689     *      command or receiving the server reply.
1690     */
1691    public int nlst() throws IOException
1692    {
1693        return sendCommand(FTPCmd.NLST);
1694    }
1695
1696    /**
1697     * A convenience method to send the FTP NLST command to the server,
1698     * receive the reply, and return the reply code.  Remember, it is up
1699     * to you to manage the data connection.  If you don't need this low
1700     * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
1701     * , which will handle all low level details for you.
1702     *
1703     * @param pathname  The pathname to list,
1704     * may be {@code null} in which case the command is sent with no parameters
1705     * @return The reply code received from the server.
1706     * @throws FTPConnectionClosedException
1707     *      If the FTP server prematurely closes the connection as a result
1708     *      of the client being idle or some other reason causing the server
1709     *      to send FTP reply code 421.  This exception may be caught either
1710     *      as an IOException or independently as itself.
1711     * @throws IOException  If an I/O error occurs while either sending the
1712     *      command or receiving the server reply.
1713     */
1714    public int nlst(final String pathname) throws IOException
1715    {
1716        return sendCommand(FTPCmd.NLST, pathname);
1717    }
1718
1719    /**
1720     * A convenience method to send the FTP SITE command to the server,
1721     * receive the reply, and return the reply code.
1722     *
1723     * @param parameters  The site parameters to send.
1724     * @return The reply code received from the server.
1725     * @throws FTPConnectionClosedException
1726     *      If the FTP server prematurely closes the connection as a result
1727     *      of the client being idle or some other reason causing the server
1728     *      to send FTP reply code 421.  This exception may be caught either
1729     *      as an IOException or independently as itself.
1730     * @throws IOException  If an I/O error occurs while either sending the
1731     *      command or receiving the server reply.
1732     */
1733    public int site(final String parameters) throws IOException
1734    {
1735        return sendCommand(FTPCmd.SITE, parameters);
1736    }
1737
1738    /**
1739     * A convenience method to send the FTP SIZE command to the server,
1740     * receive the reply, and return the reply code.
1741     *
1742     * @param parameters  The site parameters to send.
1743     * @return The reply code received from the server.
1744     * @throws FTPConnectionClosedException
1745     *      If the FTP server prematurely closes the connection as a result
1746     *      of the client being idle or some other reason causing the server
1747     *      to send FTP reply code 421.  This exception may be caught either
1748     *      as an IOException or independently as itself.
1749     * @throws IOException  If an I/O error occurs while either sending the
1750     *      command or receiving the server reply.
1751     * @since 3.7
1752     */
1753    public int size(final String parameters) throws IOException
1754    {
1755        return sendCommand(FTPCmd.SIZE, parameters);
1756    }
1757
1758    /**
1759     * A convenience method to send the FTP SYST command to the server,
1760     * receive the reply, and return the reply code.
1761     *
1762     * @return The reply code received from the server.
1763     * @throws FTPConnectionClosedException
1764     *      If the FTP server prematurely closes the connection as a result
1765     *      of the client being idle or some other reason causing the server
1766     *      to send FTP reply code 421.  This exception may be caught either
1767     *      as an IOException or independently as itself.
1768     * @throws IOException  If an I/O error occurs while either sending the
1769     *      command or receiving the server reply.
1770     */
1771    public int syst() throws IOException
1772    {
1773        return sendCommand(FTPCmd.SYST);
1774    }
1775
1776    /**
1777     * A convenience method to send the FTP STAT command to the server,
1778     * receive the reply, and return the reply code.
1779     *
1780     * @return The reply code received from the server.
1781     * @throws FTPConnectionClosedException
1782     *      If the FTP server prematurely closes the connection as a result
1783     *      of the client being idle or some other reason causing the server
1784     *      to send FTP reply code 421.  This exception may be caught either
1785     *      as an IOException or independently as itself.
1786     * @throws IOException  If an I/O error occurs while either sending the
1787     *      command or receiving the server reply.
1788     */
1789    public int stat() throws IOException
1790    {
1791        return sendCommand(FTPCmd.STAT);
1792    }
1793
1794    /**
1795     * A convenience method to send the FTP STAT command to the server,
1796     * receive the reply, and return the reply code.
1797     *
1798     * @param pathname  A pathname to list.
1799     * @return The reply code received from the server.
1800     * @throws FTPConnectionClosedException
1801     *      If the FTP server prematurely closes the connection as a result
1802     *      of the client being idle or some other reason causing the server
1803     *      to send FTP reply code 421.  This exception may be caught either
1804     *      as an IOException or independently as itself.
1805     * @throws IOException  If an I/O error occurs while either sending the
1806     *      command or receiving the server reply.
1807     */
1808    public int stat(final String pathname) throws IOException
1809    {
1810        return sendCommand(FTPCmd.STAT, pathname);
1811    }
1812
1813    /**
1814     * A convenience method to send the FTP HELP command to the server,
1815     * receive the reply, and return the reply code.
1816     *
1817     * @return The reply code received from the server.
1818     * @throws FTPConnectionClosedException
1819     *      If the FTP server prematurely closes the connection as a result
1820     *      of the client being idle or some other reason causing the server
1821     *      to send FTP reply code 421.  This exception may be caught either
1822     *      as an IOException or independently as itself.
1823     * @throws IOException  If an I/O error occurs while either sending the
1824     *      command or receiving the server reply.
1825     */
1826    public int help() throws IOException
1827    {
1828        return sendCommand(FTPCmd.HELP);
1829    }
1830
1831    /**
1832     * A convenience method to send the FTP HELP command to the server,
1833     * receive the reply, and return the reply code.
1834     *
1835     * @param command  The command name on which to request help.
1836     * @return The reply code received from the server.
1837     * @throws FTPConnectionClosedException
1838     *      If the FTP server prematurely closes the connection as a result
1839     *      of the client being idle or some other reason causing the server
1840     *      to send FTP reply code 421.  This exception may be caught either
1841     *      as an IOException or independently as itself.
1842     * @throws IOException  If an I/O error occurs while either sending the
1843     *      command or receiving the server reply.
1844     */
1845    public int help(final String command) throws IOException
1846    {
1847        return sendCommand(FTPCmd.HELP, command);
1848    }
1849
1850    /**
1851     * A convenience method to send the FTP NOOP command to the server,
1852     * receive the reply, and return the reply code.
1853     *
1854     * @return The reply code received from the server.
1855     * @throws FTPConnectionClosedException
1856     *      If the FTP server prematurely closes the connection as a result
1857     *      of the client being idle or some other reason causing the server
1858     *      to send FTP reply code 421.  This exception may be caught either
1859     *      as an IOException or independently as itself.
1860     * @throws IOException  If an I/O error occurs while either sending the
1861     *      command or receiving the server reply.
1862     */
1863    public int noop() throws IOException
1864    {
1865        return sendCommand(FTPCmd.NOOP);
1866    }
1867
1868    /**
1869     * Return whether strict multiline parsing is enabled, as per RFC 959, section 4.2.
1870     * @return True if strict, false if lenient
1871     * @since 2.0
1872     */
1873    public boolean isStrictMultilineParsing() {
1874        return strictMultilineParsing;
1875    }
1876
1877    /**
1878     * Set strict multiline parsing.
1879     * @param strictMultilineParsing the setting
1880     * @since 2.0
1881     */
1882    public void setStrictMultilineParsing(final boolean strictMultilineParsing) {
1883        this.strictMultilineParsing = strictMultilineParsing;
1884    }
1885
1886    /**
1887     * Return whether strict non-multiline parsing is enabled, as per RFC 959, section 4.2.
1888     * <p>
1889     * The default is true, which requires the 3 digit code be followed by space and some text.
1890     * <br>
1891     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1892     * <br>
1893     * @return True if strict (default), false if additional checks are not made
1894     * @since 3.6
1895     */
1896    public boolean isStrictReplyParsing() {
1897        return strictReplyParsing;
1898    }
1899
1900    /**
1901     * Set strict non-multiline parsing.
1902     * <p>
1903     * If true, it requires the 3 digit code be followed by space and some text.
1904     * <br>
1905     * If false, only the 3 digit code is required (as was the case for versions up to 3.5)
1906     * <p>
1907     * <b>This should not be required by a well-behaved FTP server</b>
1908     * <br>
1909     * @param strictReplyParsing the setting
1910     * @since 3.6
1911     */
1912    public void setStrictReplyParsing(final boolean strictReplyParsing) {
1913        this.strictReplyParsing = strictReplyParsing;
1914    }
1915
1916    /**
1917     * Provide command support to super-class
1918     */
1919    @Override
1920    protected ProtocolCommandSupport getCommandSupport() {
1921        return _commandSupport_;
1922    }
1923}