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