1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.net.ftp; 18 import java.io.BufferedInputStream; 19 import java.io.BufferedOutputStream; 20 import java.io.BufferedReader; 21 import java.io.BufferedWriter; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.InputStreamReader; 25 import java.io.OutputStream; 26 import java.io.OutputStreamWriter; 27 import java.net.Inet6Address; 28 import java.net.InetAddress; 29 import java.net.InetSocketAddress; 30 import java.net.ServerSocket; 31 import java.net.Socket; 32 import java.net.SocketException; 33 import java.net.SocketTimeoutException; 34 import java.net.UnknownHostException; 35 import java.util.ArrayList; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.Locale; 39 import java.util.Properties; 40 import java.util.Random; 41 import java.util.Set; 42 43 import org.apache.commons.net.MalformedServerReplyException; 44 import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory; 45 import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory; 46 import org.apache.commons.net.ftp.parser.MLSxEntryParser; 47 import org.apache.commons.net.io.CRLFLineReader; 48 import org.apache.commons.net.io.CopyStreamAdapter; 49 import org.apache.commons.net.io.CopyStreamEvent; 50 import org.apache.commons.net.io.CopyStreamListener; 51 import org.apache.commons.net.io.FromNetASCIIInputStream; 52 import org.apache.commons.net.io.ToNetASCIIOutputStream; 53 import org.apache.commons.net.io.Util; 54 55 /** 56 * FTPClient encapsulates all the functionality necessary to store and 57 * retrieve files from an FTP server. This class takes care of all 58 * low level details of interacting with an FTP server and provides 59 * a convenient higher level interface. As with all classes derived 60 * from {@link org.apache.commons.net.SocketClient}, 61 * you must first connect to the server with 62 * {@link org.apache.commons.net.SocketClient#connect connect } 63 * before doing anything, and finally 64 * {@link org.apache.commons.net.SocketClient#disconnect disconnect } 65 * after you're completely finished interacting with the server. 66 * Then you need to check the FTP reply code to see if the connection 67 * was successful. For example: 68 * <pre> 69 * FTPClient ftp = new FTPClient(); 70 * FTPClientConfig config = new FTPClientConfig(); 71 * config.setXXX(YYY); // change required options 72 * ftp.configure(config ); 73 * boolean error = false; 74 * try { 75 * int reply; 76 * ftp.connect("ftp.foobar.com"); 77 * System.out.println("Connected to " + server + "."); 78 * System.out.print(ftp.getReplyString()); 79 * 80 * // After connection attempt, you should check the reply code to verify 81 * // success. 82 * reply = ftp.getReplyCode(); 83 * 84 * if(!FTPReply.isPositiveCompletion(reply)) { 85 * ftp.disconnect(); 86 * System.err.println("FTP server refused connection."); 87 * System.exit(1); 88 * } 89 * ... // transfer files 90 * ftp.logout(); 91 * } catch(IOException e) { 92 * error = true; 93 * e.printStackTrace(); 94 * } finally { 95 * if(ftp.isConnected()) { 96 * try { 97 * ftp.disconnect(); 98 * } catch(IOException ioe) { 99 * // do nothing 100 * } 101 * } 102 * System.exit(error ? 1 : 0); 103 * } 104 * </pre> 105 * <p> 106 * Immediately after connecting is the only real time you need to check the 107 * reply code (because connect is of type void). The convention for all the 108 * FTP command methods in FTPClient is such that they either return a 109 * boolean value or some other value. 110 * The boolean methods return true on a successful completion reply from 111 * the FTP server and false on a reply resulting in an error condition or 112 * failure. The methods returning a value other than boolean return a value 113 * containing the higher level data produced by the FTP command, or null if a 114 * reply resulted in an error condition or failure. If you want to access 115 * the exact FTP reply code causing a success or failure, you must call 116 * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after 117 * a success or failure. 118 * <p> 119 * The default settings for FTPClient are for it to use 120 * <code> FTP.ASCII_FILE_TYPE </code>, 121 * <code> FTP.NON_PRINT_TEXT_FORMAT </code>, 122 * <code> FTP.STREAM_TRANSFER_MODE </code>, and 123 * <code> FTP.FILE_STRUCTURE </code>. The only file types directly supported 124 * are <code> FTP.ASCII_FILE_TYPE </code> and 125 * <code> FTP.BINARY_FILE_TYPE </code>. Because there are at least 4 126 * different EBCDIC encodings, we have opted not to provide direct support 127 * for EBCDIC. To transfer EBCDIC and other unsupported file types you 128 * must create your own filter InputStreams and OutputStreams and wrap 129 * them around the streams returned or required by the FTPClient methods. 130 * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII} 131 * filter streams to provide transparent handling of ASCII files. We will 132 * consider incorporating EBCDIC support if there is enough demand. 133 * <p> 134 * <code> FTP.NON_PRINT_TEXT_FORMAT </code>, 135 * <code> FTP.STREAM_TRANSFER_MODE </code>, and 136 * <code> FTP.FILE_STRUCTURE </code> are the only supported formats, 137 * transfer modes, and file structures. 138 * <p> 139 * Because the handling of sockets on different platforms can differ 140 * significantly, the FTPClient automatically issues a new PORT (or EPRT) command 141 * prior to every transfer requiring that the server connect to the client's 142 * data port. This ensures identical problem-free behavior on Windows, Unix, 143 * and Macintosh platforms. Additionally, it relieves programmers from 144 * having to issue the PORT (or EPRT) command themselves and dealing with platform 145 * dependent issues. 146 * <p> 147 * Additionally, for security purposes, all data connections to the 148 * client are verified to ensure that they originated from the intended 149 * party (host and port). If a data connection is initiated by an unexpected 150 * party, the command will close the socket and throw an IOException. You 151 * may disable this behavior with 152 * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}. 153 * <p> 154 * You should keep in mind that the FTP server may choose to prematurely 155 * close a connection if the client has been idle for longer than a 156 * given time period (usually 900 seconds). The FTPClient class will detect a 157 * premature FTP server connection closing when it receives a 158 * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE } 159 * response to a command. 160 * When that occurs, the FTP class method encountering that reply will throw 161 * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException} 162 * . 163 * <code>FTPConnectionClosedException</code> 164 * is a subclass of <code> IOException </code> and therefore need not be 165 * caught separately, but if you are going to catch it separately, its 166 * catch block must appear before the more general <code> IOException </code> 167 * catch block. When you encounter an 168 * {@link org.apache.commons.net.ftp.FTPConnectionClosedException} 169 * , you must disconnect the connection with 170 * {@link #disconnect disconnect() } to properly clean up the 171 * system resources used by FTPClient. Before disconnecting, you may check the 172 * last reply code and text with 173 * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode }, 174 * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString }, 175 * and 176 * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}. 177 * You may avoid server disconnections while the client is idle by 178 * periodically sending NOOP commands to the server. 179 * <p> 180 * Rather than list it separately for each method, we mention here that 181 * every method communicating with the server and throwing an IOException 182 * can also throw a 183 * {@link org.apache.commons.net.MalformedServerReplyException} 184 * , which is a subclass 185 * of IOException. A MalformedServerReplyException will be thrown when 186 * the reply received from the server deviates enough from the protocol 187 * specification that it cannot be interpreted in a useful manner despite 188 * attempts to be as lenient as possible. 189 * <p> 190 * Listing API Examples 191 * Both paged and unpaged examples of directory listings are available, 192 * as follows: 193 * <p> 194 * Unpaged (whole list) access, using a parser accessible by auto-detect: 195 * <pre> 196 * FTPClient f = new FTPClient(); 197 * f.connect(server); 198 * f.login(username, password); 199 * FTPFile[] files = f.listFiles(directory); 200 * </pre> 201 * <p> 202 * Paged access, using a parser not accessible by auto-detect. The class 203 * defined in the first parameter of initateListParsing should be derived 204 * from org.apache.commons.net.FTPFileEntryParser: 205 * <pre> 206 * FTPClient f = new FTPClient(); 207 * f.connect(server); 208 * f.login(username, password); 209 * FTPListParseEngine engine = 210 * f.initiateListParsing("com.whatever.YourOwnParser", directory); 211 * 212 * while (engine.hasNext()) { 213 * FTPFile[] files = engine.getNext(25); // "page size" you want 214 * //do whatever you want with these files, display them, etc. 215 * //expensive FTPFile objects not created until needed. 216 * } 217 * </pre> 218 * <p> 219 * Paged access, using a parser accessible by auto-detect: 220 * <pre> 221 * FTPClient f = new FTPClient(); 222 * f.connect(server); 223 * f.login(username, password); 224 * FTPListParseEngine engine = f.initiateListParsing(directory); 225 * 226 * while (engine.hasNext()) { 227 * FTPFile[] files = engine.getNext(25); // "page size" you want 228 * //do whatever you want with these files, display them, etc. 229 * //expensive FTPFile objects not created until needed. 230 * } 231 * </pre> 232 * <p> 233 * For examples of using FTPClient on servers whose directory listings 234 * <ul> 235 * <li>use languages other than English</li> 236 * <li>use date formats other than the American English "standard" <code>MM d yyyy</code></li> 237 * <li>are in different timezones and you need accurate timestamps for dependency checking 238 * as in Ant</li> 239 * </ul>see {@link FTPClientConfig FTPClientConfig}. 240 * <p> 241 * <b>Control channel keep-alive feature</b>:<br/> 242 * During file transfers, the data connection is busy, but the control connection is idle. 243 * FTP servers know that the control connection is in use, so won't close it through lack of activity, 244 * but it's a lot harder for network routers to know that the control and data connections are associated 245 * with each other. 246 * Some routers may treat the control connection as idle, and disconnect it if the transfer over the data 247 * connection takes longer than the allowable idle time for the router. 248 * <br/> 249 * One solution to this is to send a safe command (i.e. NOOP) over the control connection to reset the router's 250 * idle timer. This is enabled as follows: 251 * <pre> 252 * ftpClient.setControlKeepAliveTimeout(300); // set timeout to 5 minutes 253 * </pre> 254 * This will cause the file upload/download methods to send a NOOP approximately every 5 minutes. 255 * <p> 256 * The implementation currently uses a {@link CopyStreamListener} which is passed to the 257 * {@link Util#copyStream(InputStream, OutputStream, int, long, CopyStreamListener, boolean)} 258 * method, so the timing is partially dependent on how long each block transfer takes. 259 * <p> 260 * <b>Note:</b> this does not apply to the methods where the user is responsible for writing or reading 261 * the data stream, i.e. {@link #retrieveFileStream(String)} , {@link #storeFileStream(String)} 262 * and the other xxxFileStream methods 263 * <p> 264 * 265 * @see #FTP_SYSTEM_TYPE 266 * @see #SYSTEM_TYPE_PROPERTIES 267 * @see FTP 268 * @see FTPConnectionClosedException 269 * @see FTPFileEntryParser 270 * @see FTPFileEntryParserFactory 271 * @see DefaultFTPFileEntryParserFactory 272 * @see FTPClientConfig 273 * 274 * @see org.apache.commons.net.MalformedServerReplyException 275 */ 276 public class FTPClient extends FTP 277 implements Configurable 278 { 279 /** 280 * The system property ({@value}) which can be used to override the system type.<br/> 281 * If defined, the value will be used to create any automatically created parsers. 282 * 283 * @since 3.0 284 */ 285 public static final String FTP_SYSTEM_TYPE = "org.apache.commons.net.ftp.systemType"; 286 287 /** 288 * The system property ({@value}) which can be used as the default system type.<br/> 289 * If defined, the value will be used if the SYST command fails. 290 * 291 * @since 3.1 292 */ 293 public static final String FTP_SYSTEM_TYPE_DEFAULT = "org.apache.commons.net.ftp.systemType.default"; 294 295 /** 296 * The name of an optional systemType properties file ({@value}), which is loaded 297 * using {@link Class#getResourceAsStream(String)}.<br/> 298 * The entries are the systemType (as determined by {@link FTPClient#getSystemType}) 299 * and the values are the replacement type or parserClass, which is passed to 300 * {@link FTPFileEntryParserFactory#createFileEntryParser(String)}.<br/> 301 * For example: 302 * <pre> 303 * Plan 9=Unix 304 * OS410=org.apache.commons.net.ftp.parser.OS400FTPEntryParser 305 * </pre> 306 * 307 * @since 3.0 308 */ 309 public static final String SYSTEM_TYPE_PROPERTIES = "/systemType.properties"; 310 311 /** 312 * A constant indicating the FTP session is expecting all transfers 313 * to occur between the client (local) and server and that the server 314 * should connect to the client's data port to initiate a data transfer. 315 * This is the default data connection mode when and FTPClient instance 316 * is created. 317 */ 318 public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0; 319 /** 320 * A constant indicating the FTP session is expecting all transfers 321 * to occur between two remote servers and that the server 322 * the client is connected to should connect to the other server's 323 * data port to initiate a data transfer. 324 */ 325 public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1; 326 /** 327 * A constant indicating the FTP session is expecting all transfers 328 * to occur between the client (local) and server and that the server 329 * is in passive mode, requiring the client to connect to the 330 * server's data port to initiate a transfer. 331 */ 332 public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2; 333 /** 334 * A constant indicating the FTP session is expecting all transfers 335 * to occur between two remote servers and that the server 336 * the client is connected to is in passive mode, requiring the other 337 * server to connect to the first server's data port to initiate a data 338 * transfer. 339 */ 340 public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3; 341 342 private int __dataConnectionMode; 343 private int __dataTimeout; 344 private int __passivePort; 345 private String __passiveHost; 346 private final Random __random; 347 private int __activeMinPort; 348 private int __activeMaxPort; 349 private InetAddress __activeExternalHost; 350 private InetAddress __reportActiveExternalHost; // overrides __activeExternalHost in EPRT/PORT commands 351 /** The address to bind to on passive connections, if necessary. */ 352 private InetAddress __passiveLocalHost; 353 354 private int __fileType; 355 @SuppressWarnings("unused") // fields are written, but currently not read 356 private int __fileFormat; 357 @SuppressWarnings("unused") // field is written, but currently not read 358 private int __fileStructure; 359 @SuppressWarnings("unused") // field is written, but currently not read 360 private int __fileTransferMode; 361 private boolean __remoteVerificationEnabled; 362 private long __restartOffset; 363 private FTPFileEntryParserFactory __parserFactory; 364 private int __bufferSize; // buffersize for buffered data streams 365 private int __sendDataSocketBufferSize; 366 private int __receiveDataSocketBufferSize; 367 private boolean __listHiddenFiles; 368 private boolean __useEPSVwithIPv4; // whether to attempt EPSV with an IPv4 connection 369 370 // __systemName is a cached value that should not be referenced directly 371 // except when assigned in getSystemName and __initDefaults. 372 private String __systemName; 373 374 // __entryParser is a cached value that should not be referenced directly 375 // except when assigned in listFiles(String, String) and __initDefaults. 376 private FTPFileEntryParser __entryParser; 377 378 // Key used to create the parser; necessary to ensure that the parser type is not ignored 379 private String __entryParserKey; 380 381 private FTPClientConfig __configuration; 382 383 // Listener used by store/retrieve methods to handle keepalive 384 private CopyStreamListener __copyStreamListener; 385 386 // How long to wait before sending another control keep-alive message 387 private long __controlKeepAliveTimeout; 388 389 // How long to wait (ms) for keepalive message replies before continuing 390 // Most FTP servers don't seem to support concurrent control and data connection usage 391 private int __controlKeepAliveReplyTimeout=1000; 392 393 /** 394 * Enable or disable replacement of internal IP in passive mode. Default enabled. 395 */ 396 private boolean __passiveNatWorkaround = true; 397 398 /** Pattern for PASV mode responses. Groups: (n,n,n,n),(n),(n) */ 399 private static final java.util.regex.Pattern __PARMS_PAT; 400 static { 401 __PARMS_PAT = java.util.regex.Pattern.compile( 402 "(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})"); 403 } 404 405 /** Controls the automatic server encoding detection (only UTF-8 supported). */ 406 private boolean __autodetectEncoding = false; 407 408 /** Map of FEAT responses. If null, has not been initialised. */ 409 private HashMap<String, Set<String>> __featuresMap; 410 411 private static class PropertiesSingleton { 412 413 static final Properties PROPERTIES; 414 415 static { 416 InputStream resourceAsStream = FTPClient.class.getResourceAsStream(SYSTEM_TYPE_PROPERTIES); 417 Properties p = null; 418 if (resourceAsStream != null) { 419 p = new Properties(); 420 try { 421 p.load(resourceAsStream); 422 } catch (IOException e) { 423 } finally { 424 try { 425 resourceAsStream.close(); 426 } catch (IOException e) { 427 // Ignored 428 } 429 } 430 } 431 PROPERTIES = p; 432 } 433 434 } 435 private static Properties getOverrideProperties(){ 436 return PropertiesSingleton.PROPERTIES; 437 } 438 439 /** 440 * Default FTPClient constructor. Creates a new FTPClient instance 441 * with the data connection mode set to 442 * <code> ACTIVE_LOCAL_DATA_CONNECTION_MODE </code>, the file type 443 * set to <code> FTP.ASCII_FILE_TYPE </code>, the 444 * file format set to <code> FTP.NON_PRINT_TEXT_FORMAT </code>, 445 * the file structure set to <code> FTP.FILE_STRUCTURE </code>, and 446 * the transfer mode set to <code> FTP.STREAM_TRANSFER_MODE </code>. 447 * <p> 448 * The list parsing auto-detect feature can be configured to use lenient future 449 * dates (short dates may be up to one day in the future) as follows: 450 * <pre> 451 * FTPClient ftp = new FTPClient(); 452 * FTPClientConfig config = new FTPClientConfig(); 453 * config.setLenientFutureDates(true); 454 * ftp.configure(config ); 455 * </pre> 456 */ 457 public FTPClient() 458 { 459 __initDefaults(); 460 __dataTimeout = -1; 461 __remoteVerificationEnabled = true; 462 __parserFactory = new DefaultFTPFileEntryParserFactory(); 463 __configuration = null; 464 __listHiddenFiles = false; 465 __useEPSVwithIPv4 = false; 466 __random = new Random(); 467 __passiveLocalHost = null; 468 } 469 470 471 private void __initDefaults() 472 { 473 __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE; 474 __passiveHost = null; 475 __passivePort = -1; 476 __activeExternalHost = null; 477 __reportActiveExternalHost = null; 478 __activeMinPort = 0; 479 __activeMaxPort = 0; 480 __fileType = FTP.ASCII_FILE_TYPE; 481 __fileStructure = FTP.FILE_STRUCTURE; 482 __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; 483 __fileTransferMode = FTP.STREAM_TRANSFER_MODE; 484 __restartOffset = 0; 485 __systemName = null; 486 __entryParser = null; 487 __entryParserKey = ""; 488 __featuresMap = null; 489 } 490 491 /** 492 * Parse the pathname from a CWD reply. 493 * <p> 494 * According to RFC959 (http://www.ietf.org/rfc/rfc959.txt), 495 * it should be the same as for MKD i.e. 496 * {@code 257<space>"<directory-name>"[<space>commentary]} 497 * where any double-quotes in {@code <directory-name>} are doubled. 498 * Unlike MKD, the commentary is optional. 499 * <p> 500 * However, see NET-442 for an exception. 501 * 502 * @param reply 503 * @return the pathname, without enclosing quotes, 504 * or the full string after the reply code and space if the syntax is invalid 505 * (i.e. enclosing quotes are missing or embedded quotes are not doubled) 506 */ 507 // package protected for access by test cases 508 static String __parsePathname(String reply) 509 { 510 String param = reply.substring(REPLY_CODE_LEN + 1); 511 if (param.startsWith("\"")) { 512 StringBuilder sb = new StringBuilder(); 513 boolean quoteSeen = false; 514 // start after initial quote 515 for(int i=1; i < param.length(); i++) { 516 char ch = param.charAt(i); 517 if (ch=='"') { 518 if (quoteSeen) { 519 sb.append(ch); 520 quoteSeen=false; 521 } else { 522 // don't output yet, in case doubled 523 quoteSeen=true; 524 } 525 } else { 526 if (quoteSeen) { // found lone trailing quote within string 527 return sb.toString(); 528 } 529 sb.append(ch); // just another character 530 } 531 } 532 if (quoteSeen) { // found lone trailing quote at end of string 533 return sb.toString(); 534 } 535 } 536 // malformed reply, return all after reply code and space 537 return param; 538 } 539 540 /** 541 * @since 3.1 542 */ 543 protected void _parsePassiveModeReply(String reply) 544 throws MalformedServerReplyException 545 { 546 java.util.regex.Matcher m = __PARMS_PAT.matcher(reply); 547 if (!m.find()) { 548 throw new MalformedServerReplyException( 549 "Could not parse passive host information.\nServer Reply: " + reply); 550 } 551 552 __passiveHost = m.group(1).replace(',', '.'); // Fix up to look like IP address 553 554 try 555 { 556 int oct1 = Integer.parseInt(m.group(2)); 557 int oct2 = Integer.parseInt(m.group(3)); 558 __passivePort = (oct1 << 8) | oct2; 559 } 560 catch (NumberFormatException e) 561 { 562 throw new MalformedServerReplyException( 563 "Could not parse passive port information.\nServer Reply: " + reply); 564 } 565 566 if (__passiveNatWorkaround) { 567 try { 568 InetAddress host = InetAddress.getByName(__passiveHost); 569 // reply is a local address, but target is not - assume NAT box changed the PASV reply 570 if (host.isSiteLocalAddress()) { 571 InetAddress remote = getRemoteAddress(); 572 if (!remote.isSiteLocalAddress()){ 573 String hostAddress = remote.getHostAddress(); 574 fireReplyReceived(0, 575 "[Replacing site local address "+__passiveHost+" with "+hostAddress+"]\n"); 576 __passiveHost = hostAddress; 577 } 578 } 579 } catch (UnknownHostException e) { // Should not happen as we are passing in an IP address 580 throw new MalformedServerReplyException( 581 "Could not parse passive host information.\nServer Reply: " + reply); 582 } 583 } 584 } 585 586 protected void _parseExtendedPassiveModeReply(String reply) 587 throws MalformedServerReplyException 588 { 589 reply = reply.substring(reply.indexOf('(') + 1, 590 reply.indexOf(')')).trim(); 591 592 char delim1, delim2, delim3, delim4; 593 delim1 = reply.charAt(0); 594 delim2 = reply.charAt(1); 595 delim3 = reply.charAt(2); 596 delim4 = reply.charAt(reply.length()-1); 597 598 if (!(delim1 == delim2) || !(delim2 == delim3) 599 || !(delim3 == delim4)) { 600 throw new MalformedServerReplyException( 601 "Could not parse extended passive host information.\nServer Reply: " + reply); 602 } 603 604 int port; 605 try 606 { 607 port = Integer.parseInt(reply.substring(3, reply.length()-1)); 608 } 609 catch (NumberFormatException e) 610 { 611 throw new MalformedServerReplyException( 612 "Could not parse extended passive host information.\nServer Reply: " + reply); 613 } 614 615 616 // in EPSV mode, the passive host address is implicit 617 __passiveHost = getRemoteAddress().getHostAddress(); 618 __passivePort = port; 619 } 620 621 private boolean __storeFile(FTPCmd command, String remote, InputStream local) 622 throws IOException 623 { 624 return _storeFile(command.getCommand(), remote, local); 625 } 626 627 /** 628 * @since 3.1 629 */ 630 protected boolean _storeFile(String command, String remote, InputStream local) 631 throws IOException 632 { 633 Socket socket = _openDataConnection_(command, remote); 634 635 if (socket == null) { 636 return false; 637 } 638 639 OutputStream output = getBufferedOutputStream(socket.getOutputStream()); 640 641 if (__fileType == ASCII_FILE_TYPE) { 642 output = new ToNetASCIIOutputStream(output); 643 } 644 645 CSL csl = null; 646 if (__controlKeepAliveTimeout > 0) { 647 csl = new CSL(this, __controlKeepAliveTimeout, __controlKeepAliveReplyTimeout); 648 } 649 650 // Treat everything else as binary for now 651 try 652 { 653 Util.copyStream(local, output, getBufferSize(), 654 CopyStreamEvent.UNKNOWN_STREAM_SIZE, __mergeListeners(csl), 655 false); 656 } 657 catch (IOException e) 658 { 659 Util.closeQuietly(socket); // ignore close errors here 660 if (csl != null) { 661 csl.cleanUp(); // fetch any outstanding keepalive replies 662 } 663 throw e; 664 } 665 666 output.close(); // ensure the file is fully written 667 socket.close(); // done writing the file 668 if (csl != null) { 669 csl.cleanUp(); // fetch any outstanding keepalive replies 670 } 671 // Get the transfer response 672 boolean ok = completePendingCommand(); 673 return ok; 674 } 675 676 private OutputStream __storeFileStream(FTPCmd command, String remote) 677 throws IOException 678 { 679 return _storeFileStream(command.getCommand(), remote); 680 } 681 682 /** 683 * @since 3.1 684 */ 685 protected OutputStream _storeFileStream(String command, String remote) 686 throws IOException 687 { 688 Socket socket = _openDataConnection_(command, remote); 689 690 if (socket == null) { 691 return null; 692 } 693 694 OutputStream output = socket.getOutputStream(); 695 if (__fileType == ASCII_FILE_TYPE) { 696 // We buffer ascii transfers because the buffering has to 697 // be interposed between ToNetASCIIOutputSream and the underlying 698 // socket output stream. We don't buffer binary transfers 699 // because we don't want to impose a buffering policy on the 700 // programmer if possible. Programmers can decide on their 701 // own if they want to wrap the SocketOutputStream we return 702 // for file types other than ASCII. 703 output = getBufferedOutputStream(output); 704 output = new ToNetASCIIOutputStream(output); 705 706 } 707 return new org.apache.commons.net.io.SocketOutputStream(socket, output); 708 } 709 710 711 /** 712 * Establishes a data connection with the FTP server, returning 713 * a Socket for the connection if successful. If a restart 714 * offset has been set with {@link #setRestartOffset(long)}, 715 * a REST command is issued to the server with the offset as 716 * an argument before establishing the data connection. Active 717 * mode connections also cause a local PORT command to be issued. 718 * <p> 719 * @param command The int representation of the FTP command to send. 720 * @param arg The arguments to the FTP command. If this parameter is 721 * set to null, then the command is sent with no argument. 722 * @return A Socket corresponding to the established data connection. 723 * Null is returned if an FTP protocol error is reported at 724 * any point during the establishment and initialization of 725 * the connection. 726 * @exception IOException If an I/O error occurs while either sending a 727 * command to the server or receiving a reply from the server. 728 * @deprecated (3.3) Use {@link #_openDataConnection_(FTPCmd, String)} instead 729 */ 730 @Deprecated 731 protected Socket _openDataConnection_(int command, String arg) 732 throws IOException 733 { 734 return _openDataConnection_(FTPCommand.getCommand(command), arg); 735 } 736 737 /** 738 * Establishes a data connection with the FTP server, returning 739 * a Socket for the connection if successful. If a restart 740 * offset has been set with {@link #setRestartOffset(long)}, 741 * a REST command is issued to the server with the offset as 742 * an argument before establishing the data connection. Active 743 * mode connections also cause a local PORT command to be issued. 744 * <p> 745 * @param command The int representation of the FTP command to send. 746 * @param arg The arguments to the FTP command. If this parameter is 747 * set to null, then the command is sent with no argument. 748 * @return A Socket corresponding to the established data connection. 749 * Null is returned if an FTP protocol error is reported at 750 * any point during the establishment and initialization of 751 * the connection. 752 * @exception IOException If an I/O error occurs while either sending a 753 * command to the server or receiving a reply from the server. 754 * @since 3.3 755 */ 756 protected Socket _openDataConnection_(FTPCmd command, String arg) 757 throws IOException 758 { 759 return _openDataConnection_(command.getCommand(), arg); 760 } 761 762 /** 763 * Establishes a data connection with the FTP server, returning 764 * a Socket for the connection if successful. If a restart 765 * offset has been set with {@link #setRestartOffset(long)}, 766 * a REST command is issued to the server with the offset as 767 * an argument before establishing the data connection. Active 768 * mode connections also cause a local PORT command to be issued. 769 * <p> 770 * @param command The text representation of the FTP command to send. 771 * @param arg The arguments to the FTP command. If this parameter is 772 * set to null, then the command is sent with no argument. 773 * @return A Socket corresponding to the established data connection. 774 * Null is returned if an FTP protocol error is reported at 775 * any point during the establishment and initialization of 776 * the connection. 777 * @exception IOException If an I/O error occurs while either sending a 778 * command to the server or receiving a reply from the server. 779 * @since 3.1 780 */ 781 protected Socket _openDataConnection_(String command, String arg) 782 throws IOException 783 { 784 if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE && 785 __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE) { 786 return null; 787 } 788 789 final boolean isInet6Address = getRemoteAddress() instanceof Inet6Address; 790 791 Socket socket; 792 793 if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE) 794 { 795 // if no activePortRange was set (correctly) -> getActivePort() = 0 796 // -> new ServerSocket(0) -> bind to any free local port 797 ServerSocket server = _serverSocketFactory_.createServerSocket(getActivePort(), 1, getHostAddress()); 798 799 try { 800 // Try EPRT only if remote server is over IPv6, if not use PORT, 801 // because EPRT has no advantage over PORT on IPv4. 802 // It could even have the disadvantage, 803 // that EPRT will make the data connection fail, because 804 // today's intelligent NAT Firewalls are able to 805 // substitute IP addresses in the PORT command, 806 // but might not be able to recognize the EPRT command. 807 if (isInet6Address) { 808 if (!FTPReply.isPositiveCompletion(eprt(getReportHostAddress(), server.getLocalPort()))) { 809 return null; 810 } 811 } else { 812 if (!FTPReply.isPositiveCompletion(port(getReportHostAddress(), server.getLocalPort()))) { 813 return null; 814 } 815 } 816 817 if ((__restartOffset > 0) && !restart(__restartOffset)) { 818 return null; 819 } 820 821 if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) { 822 return null; 823 } 824 825 // For now, let's just use the data timeout value for waiting for 826 // the data connection. It may be desirable to let this be a 827 // separately configurable value. In any case, we really want 828 // to allow preventing the accept from blocking indefinitely. 829 if (__dataTimeout >= 0) { 830 server.setSoTimeout(__dataTimeout); 831 } 832 socket = server.accept(); 833 834 // Ensure the timeout is set before any commands are issued on the new socket 835 if (__dataTimeout >= 0) { 836 socket.setSoTimeout(__dataTimeout); 837 } 838 if (__receiveDataSocketBufferSize > 0) { 839 socket.setReceiveBufferSize(__receiveDataSocketBufferSize); 840 } 841 if (__sendDataSocketBufferSize > 0) { 842 socket.setSendBufferSize(__sendDataSocketBufferSize); 843 } 844 } finally { 845 server.close(); 846 } 847 } 848 else 849 { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE 850 851 // Try EPSV command first on IPv6 - and IPv4 if enabled. 852 // When using IPv4 with NAT it has the advantage 853 // to work with more rare configurations. 854 // E.g. if FTP server has a static PASV address (external network) 855 // and the client is coming from another internal network. 856 // In that case the data connection after PASV command would fail, 857 // while EPSV would make the client succeed by taking just the port. 858 boolean attemptEPSV = isUseEPSVwithIPv4() || isInet6Address; 859 if (attemptEPSV && epsv() == FTPReply.ENTERING_EPSV_MODE) 860 { 861 _parseExtendedPassiveModeReply(_replyLines.get(0)); 862 } 863 else 864 { 865 if (isInet6Address) { 866 return null; // Must use EPSV for IPV6 867 } 868 // If EPSV failed on IPV4, revert to PASV 869 if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) { 870 return null; 871 } 872 _parsePassiveModeReply(_replyLines.get(0)); 873 } 874 875 socket = _socketFactory_.createSocket(); 876 if (__receiveDataSocketBufferSize > 0) { 877 socket.setReceiveBufferSize(__receiveDataSocketBufferSize); 878 } 879 if (__sendDataSocketBufferSize > 0) { 880 socket.setSendBufferSize(__sendDataSocketBufferSize); 881 } 882 if (__passiveLocalHost != null) { 883 socket.bind(new InetSocketAddress(__passiveLocalHost, 0)); 884 } 885 886 // For now, let's just use the data timeout value for waiting for 887 // the data connection. It may be desirable to let this be a 888 // separately configurable value. In any case, we really want 889 // to allow preventing the accept from blocking indefinitely. 890 if (__dataTimeout >= 0) { 891 socket.setSoTimeout(__dataTimeout); 892 } 893 894 socket.connect(new InetSocketAddress(__passiveHost, __passivePort), connectTimeout); 895 if ((__restartOffset > 0) && !restart(__restartOffset)) 896 { 897 socket.close(); 898 return null; 899 } 900 901 if (!FTPReply.isPositivePreliminary(sendCommand(command, arg))) 902 { 903 socket.close(); 904 return null; 905 } 906 } 907 908 if (__remoteVerificationEnabled && !verifyRemote(socket)) 909 { 910 socket.close(); 911 912 throw new IOException( 913 "Host attempting data connection " + socket.getInetAddress().getHostAddress() + 914 " is not same as server " + getRemoteAddress().getHostAddress()); 915 } 916 917 return socket; 918 } 919 920 921 @Override 922 protected void _connectAction_() throws IOException 923 { 924 super._connectAction_(); // sets up _input_ and _output_ 925 __initDefaults(); 926 // must be after super._connectAction_(), because otherwise we get an 927 // Exception claiming we're not connected 928 if ( __autodetectEncoding ) 929 { 930 ArrayList<String> oldReplyLines = new ArrayList<String> (_replyLines); 931 int oldReplyCode = _replyCode; 932 if ( hasFeature("UTF8") || hasFeature("UTF-8")) // UTF8 appears to be the default 933 { 934 setControlEncoding("UTF-8"); 935 _controlInput_ = 936 new CRLFLineReader(new InputStreamReader(_input_, getControlEncoding())); 937 _controlOutput_ = 938 new BufferedWriter(new OutputStreamWriter(_output_, getControlEncoding())); 939 } 940 // restore the original reply (server greeting) 941 _replyLines.clear(); 942 _replyLines.addAll(oldReplyLines); 943 _replyCode = oldReplyCode; 944 } 945 } 946 947 948 /** 949 * Sets the timeout in milliseconds to use when reading from the 950 * data connection. This timeout will be set immediately after 951 * opening the data connection, provided that the value is ≥ 0. 952 * <p> 953 * <b>Note:</b> the timeout will also be applied when calling accept() 954 * whilst establishing an active local data connection. 955 * @param timeout The default timeout in milliseconds that is used when 956 * opening a data connection socket. The value 0 means an infinite timeout. 957 */ 958 public void setDataTimeout(int timeout) 959 { 960 __dataTimeout = timeout; 961 } 962 963 /** 964 * set the factory used for parser creation to the supplied factory object. 965 * 966 * @param parserFactory 967 * factory object used to create FTPFileEntryParsers 968 * 969 * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory 970 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 971 */ 972 public void setParserFactory(FTPFileEntryParserFactory parserFactory) { 973 __parserFactory = parserFactory; 974 } 975 976 977 /** 978 * Closes the connection to the FTP server and restores 979 * connection parameters to the default values. 980 * <p> 981 * @exception IOException If an error occurs while disconnecting. 982 */ 983 @Override 984 public void disconnect() throws IOException 985 { 986 super.disconnect(); 987 __initDefaults(); 988 } 989 990 991 /** 992 * Enable or disable verification that the remote host taking part 993 * of a data connection is the same as the host to which the control 994 * connection is attached. The default is for verification to be 995 * enabled. You may set this value at any time, whether the 996 * FTPClient is currently connected or not. 997 * <p> 998 * @param enable True to enable verification, false to disable verification. 999 */ 1000 public void setRemoteVerificationEnabled(boolean enable) 1001 { 1002 __remoteVerificationEnabled = enable; 1003 } 1004 1005 /** 1006 * Return whether or not verification of the remote host participating 1007 * in data connections is enabled. The default behavior is for 1008 * verification to be enabled. 1009 * <p> 1010 * @return True if verification is enabled, false if not. 1011 */ 1012 public boolean isRemoteVerificationEnabled() 1013 { 1014 return __remoteVerificationEnabled; 1015 } 1016 1017 /** 1018 * Login to the FTP server using the provided username and password. 1019 * <p> 1020 * @param username The username to login under. 1021 * @param password The password to use. 1022 * @return True if successfully completed, false if not. 1023 * @exception FTPConnectionClosedException 1024 * If the FTP server prematurely closes the connection as a result 1025 * of the client being idle or some other reason causing the server 1026 * to send FTP reply code 421. This exception may be caught either 1027 * as an IOException or independently as itself. 1028 * @exception IOException If an I/O error occurs while either sending a 1029 * command to the server or receiving a reply from the server. 1030 */ 1031 public boolean login(String username, String password) throws IOException 1032 { 1033 1034 user(username); 1035 1036 if (FTPReply.isPositiveCompletion(_replyCode)) { 1037 return true; 1038 } 1039 1040 // If we get here, we either have an error code, or an intermmediate 1041 // reply requesting password. 1042 if (!FTPReply.isPositiveIntermediate(_replyCode)) { 1043 return false; 1044 } 1045 1046 return FTPReply.isPositiveCompletion(pass(password)); 1047 } 1048 1049 1050 /** 1051 * Login to the FTP server using the provided username, password, 1052 * and account. If no account is required by the server, only 1053 * the username and password, the account information is not used. 1054 * <p> 1055 * @param username The username to login under. 1056 * @param password The password to use. 1057 * @param account The account to use. 1058 * @return True if successfully completed, false if not. 1059 * @exception FTPConnectionClosedException 1060 * If the FTP server prematurely closes the connection as a result 1061 * of the client being idle or some other reason causing the server 1062 * to send FTP reply code 421. This exception may be caught either 1063 * as an IOException or independently as itself. 1064 * @exception IOException If an I/O error occurs while either sending a 1065 * command to the server or receiving a reply from the server. 1066 */ 1067 public boolean login(String username, String password, String account) 1068 throws IOException 1069 { 1070 user(username); 1071 1072 if (FTPReply.isPositiveCompletion(_replyCode)) { 1073 return true; 1074 } 1075 1076 // If we get here, we either have an error code, or an intermmediate 1077 // reply requesting password. 1078 if (!FTPReply.isPositiveIntermediate(_replyCode)) { 1079 return false; 1080 } 1081 1082 pass(password); 1083 1084 if (FTPReply.isPositiveCompletion(_replyCode)) { 1085 return true; 1086 } 1087 1088 if (!FTPReply.isPositiveIntermediate(_replyCode)) { 1089 return false; 1090 } 1091 1092 return FTPReply.isPositiveCompletion(acct(account)); 1093 } 1094 1095 /** 1096 * Logout of the FTP server by sending the QUIT command. 1097 * <p> 1098 * @return True if successfully completed, false if not. 1099 * @exception FTPConnectionClosedException 1100 * If the FTP server prematurely closes the connection as a result 1101 * of the client being idle or some other reason causing the server 1102 * to send FTP reply code 421. This exception may be caught either 1103 * as an IOException or independently as itself. 1104 * @exception IOException If an I/O error occurs while either sending a 1105 * command to the server or receiving a reply from the server. 1106 */ 1107 public boolean logout() throws IOException 1108 { 1109 return FTPReply.isPositiveCompletion(quit()); 1110 } 1111 1112 1113 /** 1114 * Change the current working directory of the FTP session. 1115 * <p> 1116 * @param pathname The new current working directory. 1117 * @return True if successfully completed, false if not. 1118 * @exception FTPConnectionClosedException 1119 * If the FTP server prematurely closes the connection as a result 1120 * of the client being idle or some other reason causing the server 1121 * to send FTP reply code 421. This exception may be caught either 1122 * as an IOException or independently as itself. 1123 * @exception IOException If an I/O error occurs while either sending a 1124 * command to the server or receiving a reply from the server. 1125 */ 1126 public boolean changeWorkingDirectory(String pathname) throws IOException 1127 { 1128 return FTPReply.isPositiveCompletion(cwd(pathname)); 1129 } 1130 1131 1132 /** 1133 * Change to the parent directory of the current working directory. 1134 * <p> 1135 * @return True if successfully completed, false if not. 1136 * @exception FTPConnectionClosedException 1137 * If the FTP server prematurely closes the connection as a result 1138 * of the client being idle or some other reason causing the server 1139 * to send FTP reply code 421. This exception may be caught either 1140 * as an IOException or independently as itself. 1141 * @exception IOException If an I/O error occurs while either sending a 1142 * command to the server or receiving a reply from the server. 1143 */ 1144 public boolean changeToParentDirectory() throws IOException 1145 { 1146 return FTPReply.isPositiveCompletion(cdup()); 1147 } 1148 1149 1150 /** 1151 * Issue the FTP SMNT command. 1152 * <p> 1153 * @param pathname The pathname to mount. 1154 * @return True if successfully completed, false if not. 1155 * @exception FTPConnectionClosedException 1156 * If the FTP server prematurely closes the connection as a result 1157 * of the client being idle or some other reason causing the server 1158 * to send FTP reply code 421. This exception may be caught either 1159 * as an IOException or independently as itself. 1160 * @exception IOException If an I/O error occurs while either sending a 1161 * command to the server or receiving a reply from the server. 1162 */ 1163 public boolean structureMount(String pathname) throws IOException 1164 { 1165 return FTPReply.isPositiveCompletion(smnt(pathname)); 1166 } 1167 1168 /** 1169 * Reinitialize the FTP session. Not all FTP servers support this 1170 * command, which issues the FTP REIN command. 1171 * <p> 1172 * @return True if successfully completed, false if not. 1173 * @exception 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 * @exception IOException If an I/O error occurs while either sending a 1179 * command to the server or receiving a reply from the server. 1180 */ 1181 boolean reinitialize() throws IOException 1182 { 1183 rein(); 1184 1185 if (FTPReply.isPositiveCompletion(_replyCode) || 1186 (FTPReply.isPositivePreliminary(_replyCode) && 1187 FTPReply.isPositiveCompletion(getReply()))) 1188 { 1189 1190 __initDefaults(); 1191 1192 return true; 1193 } 1194 1195 return false; 1196 } 1197 1198 1199 /** 1200 * Set the current data connection mode to 1201 * <code>ACTIVE_LOCAL_DATA_CONNECTION_MODE</code>. No communication 1202 * with the FTP server is conducted, but this causes all future data 1203 * transfers to require the FTP server to connect to the client's 1204 * data port. Additionally, to accommodate differences between socket 1205 * implementations on different platforms, this method causes the 1206 * client to issue a PORT command before every data transfer. 1207 */ 1208 public void enterLocalActiveMode() 1209 { 1210 __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE; 1211 __passiveHost = null; 1212 __passivePort = -1; 1213 } 1214 1215 1216 /** 1217 * Set the current data connection mode to 1218 * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code>. Use this 1219 * method only for data transfers between the client and server. 1220 * This method causes a PASV (or EPSV) command to be issued to the server 1221 * before the opening of every data connection, telling the server to 1222 * open a data port to which the client will connect to conduct 1223 * data transfers. The FTPClient will stay in 1224 * <code> PASSIVE_LOCAL_DATA_CONNECTION_MODE </code> until the 1225 * mode is changed by calling some other method such as 1226 * {@link #enterLocalActiveMode enterLocalActiveMode() } 1227 * <p> 1228 * <b>N.B.</b> currently calling any connect method will reset the mode to 1229 * ACTIVE_LOCAL_DATA_CONNECTION_MODE. 1230 */ 1231 public void enterLocalPassiveMode() 1232 { 1233 __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE; 1234 // These will be set when just before a data connection is opened 1235 // in _openDataConnection_() 1236 __passiveHost = null; 1237 __passivePort = -1; 1238 } 1239 1240 1241 /** 1242 * Set the current data connection mode to 1243 * <code> ACTIVE_REMOTE_DATA_CONNECTION </code>. Use this method only 1244 * for server to server data transfers. This method issues a PORT 1245 * command to the server, indicating the other server and port to which 1246 * it should connect for data transfers. You must call this method 1247 * before EVERY server to server transfer attempt. The FTPClient will 1248 * NOT automatically continue to issue PORT commands. You also 1249 * must remember to call 1250 * {@link #enterLocalActiveMode enterLocalActiveMode() } if you 1251 * wish to return to the normal data connection mode. 1252 * <p> 1253 * @param host The passive mode server accepting connections for data 1254 * transfers. 1255 * @param port The passive mode server's data port. 1256 * @return True if successfully completed, false if not. 1257 * @exception FTPConnectionClosedException 1258 * If the FTP server prematurely closes the connection as a result 1259 * of the client being idle or some other reason causing the server 1260 * to send FTP reply code 421. This exception may be caught either 1261 * as an IOException or independently as itself. 1262 * @exception IOException If an I/O error occurs while either sending a 1263 * command to the server or receiving a reply from the server. 1264 */ 1265 public boolean enterRemoteActiveMode(InetAddress host, int port) 1266 throws IOException 1267 { 1268 if (FTPReply.isPositiveCompletion(port(host, port))) 1269 { 1270 __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE; 1271 __passiveHost = null; 1272 __passivePort = -1; 1273 return true; 1274 } 1275 return false; 1276 } 1277 1278 /** 1279 * Set the current data connection mode to 1280 * <code> PASSIVE_REMOTE_DATA_CONNECTION_MODE </code>. Use this 1281 * method only for server to server data transfers. 1282 * This method issues a PASV command to the server, telling it to 1283 * open a data port to which the active server will connect to conduct 1284 * data transfers. You must call this method 1285 * before EVERY server to server transfer attempt. The FTPClient will 1286 * NOT automatically continue to issue PASV commands. You also 1287 * must remember to call 1288 * {@link #enterLocalActiveMode enterLocalActiveMode() } if you 1289 * wish to return to the normal data connection mode. 1290 * <p> 1291 * @return True if successfully completed, false if not. 1292 * @exception FTPConnectionClosedException 1293 * If the FTP server prematurely closes the connection as a result 1294 * of the client being idle or some other reason causing the server 1295 * to send FTP reply code 421. This exception may be caught either 1296 * as an IOException or independently as itself. 1297 * @exception IOException If an I/O error occurs while either sending a 1298 * command to the server or receiving a reply from the server. 1299 */ 1300 public boolean enterRemotePassiveMode() throws IOException 1301 { 1302 if (pasv() != FTPReply.ENTERING_PASSIVE_MODE) { 1303 return false; 1304 } 1305 1306 __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE; 1307 _parsePassiveModeReply(_replyLines.get(0)); 1308 1309 return true; 1310 } 1311 1312 /** 1313 * Returns the hostname or IP address (in the form of a string) returned 1314 * by the server when entering passive mode. If not in passive mode, 1315 * returns null. This method only returns a valid value AFTER a 1316 * data connection has been opened after a call to 1317 * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. 1318 * This is because FTPClient sends a PASV command to the server only 1319 * just before opening a data connection, and not when you call 1320 * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. 1321 * <p> 1322 * @return The passive host name if in passive mode, otherwise null. 1323 */ 1324 public String getPassiveHost() 1325 { 1326 return __passiveHost; 1327 } 1328 1329 /** 1330 * If in passive mode, returns the data port of the passive host. 1331 * This method only returns a valid value AFTER a 1332 * data connection has been opened after a call to 1333 * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. 1334 * This is because FTPClient sends a PASV command to the server only 1335 * just before opening a data connection, and not when you call 1336 * {@link #enterLocalPassiveMode enterLocalPassiveMode()}. 1337 * <p> 1338 * @return The data port of the passive server. If not in passive 1339 * mode, undefined. 1340 */ 1341 public int getPassivePort() 1342 { 1343 return __passivePort; 1344 } 1345 1346 1347 /** 1348 * Returns the current data connection mode (one of the 1349 * <code> _DATA_CONNECTION_MODE </code> constants. 1350 * <p> 1351 * @return The current data connection mode (one of the 1352 * <code> _DATA_CONNECTION_MODE </code> constants. 1353 */ 1354 public int getDataConnectionMode() 1355 { 1356 return __dataConnectionMode; 1357 } 1358 1359 /** 1360 * Get the client port for active mode. 1361 * <p> 1362 * @return The client port for active mode. 1363 */ 1364 private int getActivePort() 1365 { 1366 if (__activeMinPort > 0 && __activeMaxPort >= __activeMinPort) 1367 { 1368 if (__activeMaxPort == __activeMinPort) { 1369 return __activeMaxPort; 1370 } 1371 // Get a random port between the min and max port range 1372 return __random.nextInt(__activeMaxPort - __activeMinPort + 1) + __activeMinPort; 1373 } 1374 else 1375 { 1376 // default port 1377 return 0; 1378 } 1379 } 1380 1381 /** 1382 * Get the host address for active mode; allows the local address to be overridden. 1383 * <p> 1384 * @return __activeExternalHost if non-null, else getLocalAddress() 1385 * @see #setActiveExternalIPAddress(String) 1386 */ 1387 private InetAddress getHostAddress() 1388 { 1389 if (__activeExternalHost != null) 1390 { 1391 return __activeExternalHost; 1392 } 1393 else 1394 { 1395 // default local address 1396 return getLocalAddress(); 1397 } 1398 } 1399 1400 /** 1401 * Get the reported host address for active mode EPRT/PORT commands; 1402 * allows override of {@link #getHostAddress()}. 1403 * 1404 * Useful for FTP Client behind Firewall NAT. 1405 * <p> 1406 * @return __reportActiveExternalHost if non-null, else getHostAddress(); 1407 */ 1408 private InetAddress getReportHostAddress() { 1409 if (__reportActiveExternalHost != null) { 1410 return __reportActiveExternalHost ; 1411 } else { 1412 return getHostAddress(); 1413 } 1414 } 1415 1416 /** 1417 * Set the client side port range in active mode. 1418 * <p> 1419 * @param minPort The lowest available port (inclusive). 1420 * @param maxPort The highest available port (inclusive). 1421 * @since 2.2 1422 */ 1423 public void setActivePortRange(int minPort, int maxPort) 1424 { 1425 this.__activeMinPort = minPort; 1426 this.__activeMaxPort = maxPort; 1427 } 1428 1429 /** 1430 * Set the external IP address in active mode. 1431 * Useful when there are multiple network cards. 1432 * <p> 1433 * @param ipAddress The external IP address of this machine. 1434 * @throws UnknownHostException if the ipAddress cannot be resolved 1435 * @since 2.2 1436 */ 1437 public void setActiveExternalIPAddress(String ipAddress) throws UnknownHostException 1438 { 1439 this.__activeExternalHost = InetAddress.getByName(ipAddress); 1440 } 1441 1442 /** 1443 * Set the local IP address to use in passive mode. 1444 * Useful when there are multiple network cards. 1445 * <p> 1446 * @param ipAddress The local IP address of this machine. 1447 * @throws UnknownHostException if the ipAddress cannot be resolved 1448 */ 1449 public void setPassiveLocalIPAddress(String ipAddress) throws UnknownHostException 1450 { 1451 this.__passiveLocalHost = InetAddress.getByName(ipAddress); 1452 } 1453 1454 /** 1455 * Set the local IP address to use in passive mode. 1456 * Useful when there are multiple network cards. 1457 * <p> 1458 * @param inetAddress The local IP address of this machine. 1459 */ 1460 public void setPassiveLocalIPAddress(InetAddress inetAddress) 1461 { 1462 this.__passiveLocalHost = inetAddress; 1463 } 1464 1465 /** 1466 * Set the local IP address in passive mode. 1467 * Useful when there are multiple network cards. 1468 * <p> 1469 * @return The local IP address in passive mode. 1470 */ 1471 public InetAddress getPassiveLocalIPAddress() 1472 { 1473 return this.__passiveLocalHost; 1474 } 1475 1476 /** 1477 * Set the external IP address to report in EPRT/PORT commands in active mode. 1478 * Useful when there are multiple network cards. 1479 * <p> 1480 * @param ipAddress The external IP address of this machine. 1481 * @throws UnknownHostException if the ipAddress cannot be resolved 1482 * @since 3.1 1483 * @see #getReportHostAddress() 1484 */ 1485 public void setReportActiveExternalIPAddress(String ipAddress) throws UnknownHostException 1486 { 1487 this.__reportActiveExternalHost = InetAddress.getByName(ipAddress); 1488 } 1489 1490 1491 /** 1492 * Sets the file type to be transferred. This should be one of 1493 * <code> FTP.ASCII_FILE_TYPE </code>, <code> FTP.BINARY_FILE_TYPE</code>, 1494 * etc. The file type only needs to be set when you want to change the 1495 * type. After changing it, the new type stays in effect until you change 1496 * it again. The default file type is <code> FTP.ASCII_FILE_TYPE </code> 1497 * if this method is never called. 1498 * <br> 1499 * The server default is supposed to be ASCII (see RFC 959), however many 1500 * ftp servers default to BINARY. <b>To ensure correct operation with all servers, 1501 * always specify the appropriate file type after connecting to the server.</b> 1502 * <br> 1503 * <p> 1504 * <b>N.B.</b> currently calling any connect method will reset the type to 1505 * FTP.ASCII_FILE_TYPE. 1506 * @param fileType The <code> _FILE_TYPE </code> constant indcating the 1507 * type of file. 1508 * @return True if successfully completed, false if not. 1509 * @exception FTPConnectionClosedException 1510 * If the FTP server prematurely closes the connection as a result 1511 * of the client being idle or some other reason causing the server 1512 * to send FTP reply code 421. This exception may be caught either 1513 * as an IOException or independently as itself. 1514 * @exception IOException If an I/O error occurs while either sending a 1515 * command to the server or receiving a reply from the server. 1516 */ 1517 public boolean setFileType(int fileType) throws IOException 1518 { 1519 if (FTPReply.isPositiveCompletion(type(fileType))) 1520 { 1521 __fileType = fileType; 1522 __fileFormat = FTP.NON_PRINT_TEXT_FORMAT; 1523 return true; 1524 } 1525 return false; 1526 } 1527 1528 1529 /** 1530 * Sets the file type to be transferred and the format. The type should be 1531 * one of <code> FTP.ASCII_FILE_TYPE </code>, 1532 * <code> FTP.BINARY_FILE_TYPE </code>, etc. The file type only needs to 1533 * be set when you want to change the type. After changing it, the new 1534 * type stays in effect until you change it again. The default file type 1535 * is <code> FTP.ASCII_FILE_TYPE </code> if this method is never called. 1536 * <br> 1537 * The server default is supposed to be ASCII (see RFC 959), however many 1538 * ftp servers default to BINARY. <b>To ensure correct operation with all servers, 1539 * always specify the appropriate file type after connecting to the server.</b> 1540 * <br> 1541 * The format should be one of the FTP class <code> TEXT_FORMAT </code> 1542 * constants, or if the type is <code> FTP.LOCAL_FILE_TYPE </code>, the 1543 * format should be the byte size for that type. The default format 1544 * is <code> FTP.NON_PRINT_TEXT_FORMAT </code> if this method is never 1545 * called. 1546 * <p> 1547 * <b>N.B.</b> currently calling any connect method will reset the type to 1548 * FTP.ASCII_FILE_TYPE and the formatOrByteSize to FTP.NON_PRINT_TEXT_FORMAT. 1549 * <p> 1550 * @param fileType The <code> _FILE_TYPE </code> constant indcating the 1551 * type of file. 1552 * @param formatOrByteSize The format of the file (one of the 1553 * <code>_FORMAT</code> constants. In the case of 1554 * <code>LOCAL_FILE_TYPE</code>, the byte size. 1555 * <p> 1556 * @return True if successfully completed, false if not. 1557 * @exception FTPConnectionClosedException 1558 * If the FTP server prematurely closes the connection as a result 1559 * of the client being idle or some other reason causing the server 1560 * to send FTP reply code 421. This exception may be caught either 1561 * as an IOException or independently as itself. 1562 * @exception IOException If an I/O error occurs while either sending a 1563 * command to the server or receiving a reply from the server. 1564 */ 1565 public boolean setFileType(int fileType, int formatOrByteSize) 1566 throws IOException 1567 { 1568 if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize))) 1569 { 1570 __fileType = fileType; 1571 __fileFormat = formatOrByteSize; 1572 return true; 1573 } 1574 return false; 1575 } 1576 1577 1578 /** 1579 * Sets the file structure. The default structure is 1580 * <code> FTP.FILE_STRUCTURE </code> if this method is never called 1581 * or if a connect method is called. 1582 * <p> 1583 * @param structure The structure of the file (one of the FTP class 1584 * <code>_STRUCTURE</code> constants). 1585 * @return True if successfully completed, false if not. 1586 * @exception FTPConnectionClosedException 1587 * If the FTP server prematurely closes the connection as a result 1588 * of the client being idle or some other reason causing the server 1589 * to send FTP reply code 421. This exception may be caught either 1590 * as an IOException or independently as itself. 1591 * @exception IOException If an I/O error occurs while either sending a 1592 * command to the server or receiving a reply from the server. 1593 */ 1594 public boolean setFileStructure(int structure) throws IOException 1595 { 1596 if (FTPReply.isPositiveCompletion(stru(structure))) 1597 { 1598 __fileStructure = structure; 1599 return true; 1600 } 1601 return false; 1602 } 1603 1604 1605 /** 1606 * Sets the transfer mode. The default transfer mode 1607 * <code> FTP.STREAM_TRANSFER_MODE </code> if this method is never called 1608 * or if a connect method is called. 1609 * <p> 1610 * @param mode The new transfer mode to use (one of the FTP class 1611 * <code>_TRANSFER_MODE</code> constants). 1612 * @return True if successfully completed, false if not. 1613 * @exception FTPConnectionClosedException 1614 * If the FTP server prematurely closes the connection as a result 1615 * of the client being idle or some other reason causing the server 1616 * to send FTP reply code 421. This exception may be caught either 1617 * as an IOException or independently as itself. 1618 * @exception IOException If an I/O error occurs while either sending a 1619 * command to the server or receiving a reply from the server. 1620 */ 1621 public boolean setFileTransferMode(int mode) throws IOException 1622 { 1623 if (FTPReply.isPositiveCompletion(mode(mode))) 1624 { 1625 __fileTransferMode = mode; 1626 return true; 1627 } 1628 return false; 1629 } 1630 1631 1632 /** 1633 * Initiate a server to server file transfer. This method tells the 1634 * server to which the client is connected to retrieve a given file from 1635 * the other server. 1636 * <p> 1637 * @param filename The name of the file to retrieve. 1638 * @return True if successfully completed, false if not. 1639 * @exception FTPConnectionClosedException 1640 * If the FTP server prematurely closes the connection as a result 1641 * of the client being idle or some other reason causing the server 1642 * to send FTP reply code 421. This exception may be caught either 1643 * as an IOException or independently as itself. 1644 * @exception IOException If an I/O error occurs while either sending a 1645 * command to the server or receiving a reply from the server. 1646 */ 1647 public boolean remoteRetrieve(String filename) throws IOException 1648 { 1649 if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || 1650 __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) { 1651 return FTPReply.isPositivePreliminary(retr(filename)); 1652 } 1653 return false; 1654 } 1655 1656 1657 /** 1658 * Initiate a server to server file transfer. This method tells the 1659 * server to which the client is connected to store a file on 1660 * the other server using the given filename. The other server must 1661 * have had a <code> remoteRetrieve </code> issued to it by another 1662 * FTPClient. 1663 * <p> 1664 * @param filename The name to call the file that is to be stored. 1665 * @return True if successfully completed, false if not. 1666 * @exception FTPConnectionClosedException 1667 * If the FTP server prematurely closes the connection as a result 1668 * of the client being idle or some other reason causing the server 1669 * to send FTP reply code 421. This exception may be caught either 1670 * as an IOException or independently as itself. 1671 * @exception IOException If an I/O error occurs while either sending a 1672 * command to the server or receiving a reply from the server. 1673 */ 1674 public boolean remoteStore(String filename) throws IOException 1675 { 1676 if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || 1677 __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) { 1678 return FTPReply.isPositivePreliminary(stor(filename)); 1679 } 1680 return false; 1681 } 1682 1683 1684 /** 1685 * Initiate a server to server file transfer. This method tells the 1686 * server to which the client is connected to store a file on 1687 * the other server using a unique filename based on the given filename. 1688 * The other server must have had a <code> remoteRetrieve </code> issued 1689 * to it by another FTPClient. 1690 * <p> 1691 * @param filename The name on which to base the filename of the file 1692 * that is to be stored. 1693 * @return True if successfully completed, false if not. 1694 * @exception FTPConnectionClosedException 1695 * If the FTP server prematurely closes the connection as a result 1696 * of the client being idle or some other reason causing the server 1697 * to send FTP reply code 421. This exception may be caught either 1698 * as an IOException or independently as itself. 1699 * @exception IOException If an I/O error occurs while either sending a 1700 * command to the server or receiving a reply from the server. 1701 */ 1702 public boolean remoteStoreUnique(String filename) throws IOException 1703 { 1704 if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || 1705 __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) { 1706 return FTPReply.isPositivePreliminary(stou(filename)); 1707 } 1708 return false; 1709 } 1710 1711 1712 /** 1713 * Initiate a server to server file transfer. This method tells the 1714 * server to which the client is connected to store a file on 1715 * the other server using a unique filename. 1716 * The other server must have had a <code> remoteRetrieve </code> issued 1717 * to it by another FTPClient. Many FTP servers require that a base 1718 * filename be given from which the unique filename can be derived. For 1719 * those servers use the other version of <code> remoteStoreUnique</code> 1720 * <p> 1721 * @return True if successfully completed, false if not. 1722 * @exception FTPConnectionClosedException 1723 * If the FTP server prematurely closes the connection as a result 1724 * of the client being idle or some other reason causing the server 1725 * to send FTP reply code 421. This exception may be caught either 1726 * as an IOException or independently as itself. 1727 * @exception IOException If an I/O error occurs while either sending a 1728 * command to the server or receiving a reply from the server. 1729 */ 1730 public boolean remoteStoreUnique() throws IOException 1731 { 1732 if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || 1733 __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) { 1734 return FTPReply.isPositivePreliminary(stou()); 1735 } 1736 return false; 1737 } 1738 1739 // For server to server transfers 1740 /** 1741 * Initiate a server to server file transfer. This method tells the 1742 * server to which the client is connected to append to a given file on 1743 * the other server. The other server must have had a 1744 * <code> remoteRetrieve </code> issued to it by another FTPClient. 1745 * <p> 1746 * @param filename The name of the file to be appended to, or if the 1747 * file does not exist, the name to call the file being stored. 1748 * <p> 1749 * @return True if successfully completed, false if not. 1750 * @exception FTPConnectionClosedException 1751 * If the FTP server prematurely closes the connection as a result 1752 * of the client being idle or some other reason causing the server 1753 * to send FTP reply code 421. This exception may be caught either 1754 * as an IOException or independently as itself. 1755 * @exception IOException If an I/O error occurs while either sending a 1756 * command to the server or receiving a reply from the server. 1757 */ 1758 public boolean remoteAppend(String filename) throws IOException 1759 { 1760 if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE || 1761 __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE) { 1762 return FTPReply.isPositivePreliminary(appe(filename)); 1763 } 1764 return false; 1765 } 1766 1767 /** 1768 * There are a few FTPClient methods that do not complete the 1769 * entire sequence of FTP commands to complete a transaction. These 1770 * commands require some action by the programmer after the reception 1771 * of a positive intermediate command. After the programmer's code 1772 * completes its actions, it must call this method to receive 1773 * the completion reply from the server and verify the success of the 1774 * entire transaction. 1775 * <p> 1776 * For example, 1777 * <pre> 1778 * InputStream input; 1779 * OutputStream output; 1780 * input = new FileInputStream("foobaz.txt"); 1781 * output = ftp.storeFileStream("foobar.txt") 1782 * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) { 1783 * input.close(); 1784 * output.close(); 1785 * ftp.logout(); 1786 * ftp.disconnect(); 1787 * System.err.println("File transfer failed."); 1788 * System.exit(1); 1789 * } 1790 * Util.copyStream(input, output); 1791 * input.close(); 1792 * output.close(); 1793 * // Must call completePendingCommand() to finish command. 1794 * if(!ftp.completePendingCommand()) { 1795 * ftp.logout(); 1796 * ftp.disconnect(); 1797 * System.err.println("File transfer failed."); 1798 * System.exit(1); 1799 * } 1800 * </pre> 1801 * <p> 1802 * @return True if successfully completed, false if not. 1803 * @exception FTPConnectionClosedException 1804 * If the FTP server prematurely closes the connection as a result 1805 * of the client being idle or some other reason causing the server 1806 * to send FTP reply code 421. This exception may be caught either 1807 * as an IOException or independently as itself. 1808 * @exception IOException If an I/O error occurs while either sending a 1809 * command to the server or receiving a reply from the server. 1810 */ 1811 public boolean completePendingCommand() throws IOException 1812 { 1813 return FTPReply.isPositiveCompletion(getReply()); 1814 } 1815 1816 1817 /** 1818 * Retrieves a named file from the server and writes it to the given 1819 * OutputStream. This method does NOT close the given OutputStream. 1820 * If the current file type is ASCII, line separators in the file are 1821 * converted to the local representation. 1822 * <p> 1823 * Note: if you have used {@link #setRestartOffset(long)}, 1824 * the file data will start from the selected offset. 1825 * @param remote The name of the remote file. 1826 * @param local The local OutputStream to which to write the file. 1827 * @return True if successfully completed, false if not. 1828 * @exception FTPConnectionClosedException 1829 * If the FTP server prematurely closes the connection as a result 1830 * of the client being idle or some other reason causing the server 1831 * to send FTP reply code 421. This exception may be caught either 1832 * as an IOException or independently as itself. 1833 * @exception org.apache.commons.net.io.CopyStreamException 1834 * If an I/O error occurs while actually 1835 * transferring the file. The CopyStreamException allows you to 1836 * determine the number of bytes transferred and the IOException 1837 * causing the error. This exception may be caught either 1838 * as an IOException or independently as itself. 1839 * @exception IOException If an I/O error occurs while either sending a 1840 * command to the server or receiving a reply from the server. 1841 */ 1842 public boolean retrieveFile(String remote, OutputStream local) 1843 throws IOException 1844 { 1845 return _retrieveFile(FTPCmd.RETR.getCommand(), remote, local); 1846 } 1847 1848 /** 1849 * @since 3.1 1850 */ 1851 protected boolean _retrieveFile(String command, String remote, OutputStream local) 1852 throws IOException 1853 { 1854 Socket socket = _openDataConnection_(command, remote); 1855 1856 if (socket == null) { 1857 return false; 1858 } 1859 1860 InputStream input = getBufferedInputStream(socket.getInputStream()); 1861 if (__fileType == ASCII_FILE_TYPE) { 1862 input = new FromNetASCIIInputStream(input); 1863 } 1864 1865 CSL csl = null; 1866 if (__controlKeepAliveTimeout > 0) { 1867 csl = new CSL(this, __controlKeepAliveTimeout, __controlKeepAliveReplyTimeout); 1868 } 1869 1870 // Treat everything else as binary for now 1871 try 1872 { 1873 Util.copyStream(input, local, getBufferSize(), 1874 CopyStreamEvent.UNKNOWN_STREAM_SIZE, __mergeListeners(csl), 1875 false); 1876 } finally { 1877 Util.closeQuietly(input); 1878 Util.closeQuietly(socket); 1879 if (csl != null) { 1880 csl.cleanUp(); // fetch any outstanding keepalive replies 1881 } 1882 } 1883 1884 // Get the transfer response 1885 boolean ok = completePendingCommand(); 1886 return ok; 1887 } 1888 1889 /** 1890 * Returns an InputStream from which a named file from the server 1891 * can be read. If the current file type is ASCII, the returned 1892 * InputStream will convert line separators in the file to 1893 * the local representation. You must close the InputStream when you 1894 * finish reading from it. The InputStream itself will take care of 1895 * closing the parent data connection socket upon being closed. To 1896 * finalize the file transfer you must call 1897 * {@link #completePendingCommand completePendingCommand } and 1898 * check its return value to verify success. 1899 * <p> 1900 * Note: if you have used {@link #setRestartOffset(long)}, 1901 * the file data will start from the selected offset. 1902 * 1903 * @param remote The name of the remote file. 1904 * @return An InputStream from which the remote file can be read. If 1905 * the data connection cannot be opened (e.g., the file does not 1906 * exist), null is returned (in which case you may check the reply 1907 * code to determine the exact reason for failure). 1908 * @exception FTPConnectionClosedException 1909 * If the FTP server prematurely closes the connection as a result 1910 * of the client being idle or some other reason causing the server 1911 * to send FTP reply code 421. This exception may be caught either 1912 * as an IOException or independently as itself. 1913 * @exception IOException If an I/O error occurs while either sending a 1914 * command to the server or receiving a reply from the server. 1915 */ 1916 public InputStream retrieveFileStream(String remote) throws IOException 1917 { 1918 return _retrieveFileStream(FTPCmd.RETR.getCommand(), remote); 1919 } 1920 1921 /** 1922 * @since 3.1 1923 */ 1924 protected InputStream _retrieveFileStream(String command, String remote) 1925 throws IOException 1926 { 1927 Socket socket = _openDataConnection_(command, remote); 1928 1929 if (socket == null) { 1930 return null; 1931 } 1932 1933 InputStream input = socket.getInputStream(); 1934 if (__fileType == ASCII_FILE_TYPE) { 1935 // We buffer ascii transfers because the buffering has to 1936 // be interposed between FromNetASCIIOutputSream and the underlying 1937 // socket input stream. We don't buffer binary transfers 1938 // because we don't want to impose a buffering policy on the 1939 // programmer if possible. Programmers can decide on their 1940 // own if they want to wrap the SocketInputStream we return 1941 // for file types other than ASCII. 1942 input = getBufferedInputStream(input); 1943 input = new FromNetASCIIInputStream(input); 1944 } 1945 return new org.apache.commons.net.io.SocketInputStream(socket, input); 1946 } 1947 1948 1949 /** 1950 * Stores a file on the server using the given name and taking input 1951 * from the given InputStream. This method does NOT close the given 1952 * InputStream. If the current file type is ASCII, line separators in 1953 * the file are transparently converted to the NETASCII format (i.e., 1954 * you should not attempt to create a special InputStream to do this). 1955 * <p> 1956 * @param remote The name to give the remote file. 1957 * @param local The local InputStream from which to read the file. 1958 * @return True if successfully completed, false if not. 1959 * @exception FTPConnectionClosedException 1960 * If the FTP server prematurely closes the connection as a result 1961 * of the client being idle or some other reason causing the server 1962 * to send FTP reply code 421. This exception may be caught either 1963 * as an IOException or independently as itself. 1964 * @exception org.apache.commons.net.io.CopyStreamException 1965 * If an I/O error occurs while actually 1966 * transferring the file. The CopyStreamException allows you to 1967 * determine the number of bytes transferred and the IOException 1968 * causing the error. This exception may be caught either 1969 * as an IOException or independently as itself. 1970 * @exception IOException If an I/O error occurs while either sending a 1971 * command to the server or receiving a reply from the server. 1972 */ 1973 public boolean storeFile(String remote, InputStream local) 1974 throws IOException 1975 { 1976 return __storeFile(FTPCmd.STOR, remote, local); 1977 } 1978 1979 1980 /** 1981 * Returns an OutputStream through which data can be written to store 1982 * a file on the server using the given name. If the current file type 1983 * is ASCII, the returned OutputStream will convert line separators in 1984 * the file to the NETASCII format (i.e., you should not attempt to 1985 * create a special OutputStream to do this). You must close the 1986 * OutputStream when you finish writing to it. The OutputStream itself 1987 * will take care of closing the parent data connection socket upon being 1988 * closed. To finalize the file transfer you must call 1989 * {@link #completePendingCommand completePendingCommand } and 1990 * check its return value to verify success. 1991 * <p> 1992 * @param remote The name to give the remote file. 1993 * @return An OutputStream through which the remote file can be written. If 1994 * the data connection cannot be opened (e.g., the file does not 1995 * exist), null is returned (in which case you may check the reply 1996 * code to determine the exact reason for failure). 1997 * @exception FTPConnectionClosedException 1998 * If the FTP server prematurely closes the connection as a result 1999 * of the client being idle or some other reason causing the server 2000 * to send FTP reply code 421. This exception may be caught either 2001 * as an IOException or independently as itself. 2002 * @exception IOException If an I/O error occurs while either sending a 2003 * command to the server or receiving a reply from the server. 2004 */ 2005 public OutputStream storeFileStream(String remote) throws IOException 2006 { 2007 return __storeFileStream(FTPCmd.STOR, remote); 2008 } 2009 2010 /** 2011 * Appends to a file on the server with the given name, taking input 2012 * from the given InputStream. This method does NOT close the given 2013 * InputStream. If the current file type is ASCII, line separators in 2014 * the file are transparently converted to the NETASCII format (i.e., 2015 * you should not attempt to create a special InputStream to do this). 2016 * <p> 2017 * @param remote The name of the remote file. 2018 * @param local The local InputStream from which to read the data to 2019 * be appended to the remote file. 2020 * @return True if successfully completed, false if not. 2021 * @exception FTPConnectionClosedException 2022 * If the FTP server prematurely closes the connection as a result 2023 * of the client being idle or some other reason causing the server 2024 * to send FTP reply code 421. This exception may be caught either 2025 * as an IOException or independently as itself. 2026 * @exception org.apache.commons.net.io.CopyStreamException 2027 * If an I/O error occurs while actually 2028 * transferring the file. The CopyStreamException allows you to 2029 * determine the number of bytes transferred and the IOException 2030 * causing the error. This exception may be caught either 2031 * as an IOException or independently as itself. 2032 * @exception IOException If an I/O error occurs while either sending a 2033 * command to the server or receiving a reply from the server. 2034 */ 2035 public boolean appendFile(String remote, InputStream local) 2036 throws IOException 2037 { 2038 return __storeFile(FTPCmd.APPE, remote, local); 2039 } 2040 2041 /** 2042 * Returns an OutputStream through which data can be written to append 2043 * to a file on the server with the given name. If the current file type 2044 * is ASCII, the returned OutputStream will convert line separators in 2045 * the file to the NETASCII format (i.e., you should not attempt to 2046 * create a special OutputStream to do this). You must close the 2047 * OutputStream when you finish writing to it. The OutputStream itself 2048 * will take care of closing the parent data connection socket upon being 2049 * closed. To finalize the file transfer you must call 2050 * {@link #completePendingCommand completePendingCommand } and 2051 * check its return value to verify success. 2052 * <p> 2053 * @param remote The name of the remote file. 2054 * @return An OutputStream through which the remote file can be appended. 2055 * If the data connection cannot be opened (e.g., the file does not 2056 * exist), null is returned (in which case you may check the reply 2057 * code to determine the exact reason for failure). 2058 * @exception FTPConnectionClosedException 2059 * If the FTP server prematurely closes the connection as a result 2060 * of the client being idle or some other reason causing the server 2061 * to send FTP reply code 421. This exception may be caught either 2062 * as an IOException or independently as itself. 2063 * @exception IOException If an I/O error occurs while either sending a 2064 * command to the server or receiving a reply from the server. 2065 */ 2066 public OutputStream appendFileStream(String remote) throws IOException 2067 { 2068 return __storeFileStream(FTPCmd.APPE, remote); 2069 } 2070 2071 /** 2072 * Stores a file on the server using a unique name derived from the 2073 * given name and taking input 2074 * from the given InputStream. This method does NOT close the given 2075 * InputStream. If the current file type is ASCII, line separators in 2076 * the file are transparently converted to the NETASCII format (i.e., 2077 * you should not attempt to create a special InputStream to do this). 2078 * <p> 2079 * @param remote The name on which to base the unique name given to 2080 * the remote file. 2081 * @param local The local InputStream from which to read the file. 2082 * @return True if successfully completed, false if not. 2083 * @exception FTPConnectionClosedException 2084 * If the FTP server prematurely closes the connection as a result 2085 * of the client being idle or some other reason causing the server 2086 * to send FTP reply code 421. This exception may be caught either 2087 * as an IOException or independently as itself. 2088 * @exception org.apache.commons.net.io.CopyStreamException 2089 * If an I/O error occurs while actually 2090 * transferring the file. The CopyStreamException allows you to 2091 * determine the number of bytes transferred and the IOException 2092 * causing the error. This exception may be caught either 2093 * as an IOException or independently as itself. 2094 * @exception IOException If an I/O error occurs while either sending a 2095 * command to the server or receiving a reply from the server. 2096 */ 2097 public boolean storeUniqueFile(String remote, InputStream local) 2098 throws IOException 2099 { 2100 return __storeFile(FTPCmd.STOU, remote, local); 2101 } 2102 2103 2104 /** 2105 * Returns an OutputStream through which data can be written to store 2106 * a file on the server using a unique name derived from the given name. 2107 * If the current file type 2108 * is ASCII, the returned OutputStream will convert line separators in 2109 * the file to the NETASCII format (i.e., you should not attempt to 2110 * create a special OutputStream to do this). You must close the 2111 * OutputStream when you finish writing to it. The OutputStream itself 2112 * will take care of closing the parent data connection socket upon being 2113 * closed. To finalize the file transfer you must call 2114 * {@link #completePendingCommand completePendingCommand } and 2115 * check its return value to verify success. 2116 * <p> 2117 * @param remote The name on which to base the unique name given to 2118 * the remote file. 2119 * @return An OutputStream through which the remote file can be written. If 2120 * the data connection cannot be opened (e.g., the file does not 2121 * exist), null is returned (in which case you may check the reply 2122 * code to determine the exact reason for failure). 2123 * @exception FTPConnectionClosedException 2124 * If the FTP server prematurely closes the connection as a result 2125 * of the client being idle or some other reason causing the server 2126 * to send FTP reply code 421. This exception may be caught either 2127 * as an IOException or independently as itself. 2128 * @exception IOException If an I/O error occurs while either sending a 2129 * command to the server or receiving a reply from the server. 2130 */ 2131 public OutputStream storeUniqueFileStream(String remote) throws IOException 2132 { 2133 return __storeFileStream(FTPCmd.STOU, remote); 2134 } 2135 2136 /** 2137 * Stores a file on the server using a unique name assigned by the 2138 * server and taking input from the given InputStream. This method does 2139 * NOT close the given 2140 * InputStream. If the current file type is ASCII, line separators in 2141 * the file are transparently converted to the NETASCII format (i.e., 2142 * you should not attempt to create a special InputStream to do this). 2143 * <p> 2144 * @param local The local InputStream from which to read the file. 2145 * @return True if successfully completed, false if not. 2146 * @exception FTPConnectionClosedException 2147 * If the FTP server prematurely closes the connection as a result 2148 * of the client being idle or some other reason causing the server 2149 * to send FTP reply code 421. This exception may be caught either 2150 * as an IOException or independently as itself. 2151 * @exception org.apache.commons.net.io.CopyStreamException 2152 * If an I/O error occurs while actually 2153 * transferring the file. The CopyStreamException allows you to 2154 * determine the number of bytes transferred and the IOException 2155 * causing the error. This exception may be caught either 2156 * as an IOException or independently as itself. 2157 * @exception IOException If an I/O error occurs while either sending a 2158 * command to the server or receiving a reply from the server. 2159 */ 2160 public boolean storeUniqueFile(InputStream local) throws IOException 2161 { 2162 return __storeFile(FTPCmd.STOU, null, local); 2163 } 2164 2165 /** 2166 * Returns an OutputStream through which data can be written to store 2167 * a file on the server using a unique name assigned by the server. 2168 * If the current file type 2169 * is ASCII, the returned OutputStream will convert line separators in 2170 * the file to the NETASCII format (i.e., you should not attempt to 2171 * create a special OutputStream to do this). You must close the 2172 * OutputStream when you finish writing to it. The OutputStream itself 2173 * will take care of closing the parent data connection socket upon being 2174 * closed. To finalize the file transfer you must call 2175 * {@link #completePendingCommand completePendingCommand } and 2176 * check its return value to verify success. 2177 * <p> 2178 * @return An OutputStream through which the remote file can be written. If 2179 * the data connection cannot be opened (e.g., the file does not 2180 * exist), null is returned (in which case you may check the reply 2181 * code to determine the exact reason for failure). 2182 * @exception FTPConnectionClosedException 2183 * If the FTP server prematurely closes the connection as a result 2184 * of the client being idle or some other reason causing the server 2185 * to send FTP reply code 421. This exception may be caught either 2186 * as an IOException or independently as itself. 2187 * @exception IOException If an I/O error occurs while either sending a 2188 * command to the server or receiving a reply from the server. 2189 */ 2190 public OutputStream storeUniqueFileStream() throws IOException 2191 { 2192 return __storeFileStream(FTPCmd.STOU, null); 2193 } 2194 2195 /** 2196 * Reserve a number of bytes on the server for the next file transfer. 2197 * <p> 2198 * @param bytes The number of bytes which the server should allocate. 2199 * @return True if successfully completed, false if not. 2200 * @exception FTPConnectionClosedException 2201 * If the FTP server prematurely closes the connection as a result 2202 * of the client being idle or some other reason causing the server 2203 * to send FTP reply code 421. This exception may be caught either 2204 * as an IOException or independently as itself. 2205 * @exception IOException If an I/O error occurs while either sending a 2206 * command to the server or receiving a reply from the server. 2207 */ 2208 public boolean allocate(int bytes) throws IOException 2209 { 2210 return FTPReply.isPositiveCompletion(allo(bytes)); 2211 } 2212 2213 /** 2214 * Query the server for supported features. The server may reply with a list of server-supported exensions. 2215 * For example, a typical client-server interaction might be (from RFC 2389): 2216 * <pre> 2217 C> feat 2218 S> 211-Extensions supported: 2219 S> MLST size*;create;modify*;perm;media-type 2220 S> SIZE 2221 S> COMPRESSION 2222 S> MDTM 2223 S> 211 END 2224 * </pre> 2225 * @see <a href="http://www.faqs.org/rfcs/rfc2389.html">http://www.faqs.org/rfcs/rfc2389.html</a> 2226 * @return True if successfully completed, false if not. 2227 * @throws IOException 2228 * @since 2.2 2229 */ 2230 public boolean features() throws IOException { 2231 return FTPReply.isPositiveCompletion(feat()); 2232 } 2233 2234 /** 2235 * Query the server for a supported feature, and returns its values (if any). 2236 * Caches the parsed response to avoid resending the command repeatedly. 2237 * 2238 * @return if the feature is present, returns the feature values (empty array if none) 2239 * Returns {@code null} if the feature is not found or the command failed. 2240 * Check {@link #getReplyCode()} or {@link #getReplyString()} if so. 2241 * @throws IOException 2242 * @since 3.0 2243 */ 2244 public String[] featureValues(String feature) throws IOException { 2245 if (!initFeatureMap()) { 2246 return null; 2247 } 2248 Set<String> entries = __featuresMap.get(feature.toUpperCase(Locale.ENGLISH)); 2249 if (entries != null) { 2250 return entries.toArray(new String[entries.size()]); 2251 } 2252 return null; 2253 } 2254 2255 /** 2256 * Query the server for a supported feature, and returns the its value (if any). 2257 * Caches the parsed response to avoid resending the command repeatedly. 2258 * 2259 * @return if the feature is present, returns the feature value or the empty string 2260 * if the feature exists but has no value. 2261 * Returns {@code null} if the feature is not found or the command failed. 2262 * Check {@link #getReplyCode()} or {@link #getReplyString()} if so. 2263 * @throws IOException 2264 * @since 3.0 2265 */ 2266 public String featureValue(String feature) throws IOException { 2267 String [] values = featureValues(feature); 2268 if (values != null) { 2269 return values[0]; 2270 } 2271 return null; 2272 } 2273 2274 /** 2275 * Query the server for a supported feature. 2276 * Caches the parsed response to avoid resending the command repeatedly. 2277 * 2278 * @param feature the name of the feature; it is converted to upper case. 2279 * @return {@code true} if the feature is present, {@code false} if the feature is not present 2280 * or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()} 2281 * if it is necessary to distinguish these cases. 2282 * 2283 * @throws IOException 2284 * @since 3.0 2285 */ 2286 public boolean hasFeature(String feature) throws IOException { 2287 if (!initFeatureMap()) { 2288 return false; 2289 } 2290 return __featuresMap.containsKey(feature.toUpperCase(Locale.ENGLISH)); 2291 } 2292 2293 /** 2294 * Query the server for a supported feature with particular value, 2295 * for example "AUTH SSL" or "AUTH TLS". 2296 * Caches the parsed response to avoid resending the command repeatedly. 2297 * 2298 * @param feature the name of the feature; it is converted to upper case. 2299 * @param value the value to find. 2300 * 2301 * @return {@code true} if the feature is present, {@code false} if the feature is not present 2302 * or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()} 2303 * if it is necessary to distinguish these cases. 2304 * 2305 * @throws IOException 2306 * @since 3.0 2307 */ 2308 public boolean hasFeature(String feature, String value) throws IOException { 2309 if (!initFeatureMap()) { 2310 return false; 2311 } 2312 Set<String> entries = __featuresMap.get(feature.toUpperCase(Locale.ENGLISH)); 2313 if (entries != null) { 2314 return entries.contains(value); 2315 } 2316 return false; 2317 } 2318 2319 /* 2320 * Create the feature map if not already created. 2321 */ 2322 private boolean initFeatureMap() throws IOException { 2323 if (__featuresMap == null) { 2324 // Don't create map here, because next line may throw exception 2325 boolean success = FTPReply.isPositiveCompletion(feat()); 2326 // we init the map here, so we don't keep trying if we know the command will fail 2327 __featuresMap = new HashMap<String, Set<String>>(); 2328 if (!success) { 2329 return false; 2330 } 2331 for (String l : getReplyStrings()) { 2332 if (l.startsWith(" ")) { // it's a FEAT entry 2333 String key; 2334 String value=""; 2335 int varsep = l.indexOf(' ', 1); 2336 if (varsep > 0) { 2337 key = l.substring(1, varsep); 2338 value = l.substring(varsep+1); 2339 } else { 2340 key = l.substring(1); 2341 } 2342 key = key.toUpperCase(Locale.ENGLISH); 2343 Set<String> entries = __featuresMap.get(key); 2344 if (entries == null) { 2345 entries = new HashSet<String>(); 2346 __featuresMap.put(key, entries); 2347 } 2348 entries.add(value); 2349 } 2350 } 2351 } 2352 return true; 2353 } 2354 2355 /** 2356 * Reserve space on the server for the next file transfer. 2357 * <p> 2358 * @param bytes The number of bytes which the server should allocate. 2359 * @param recordSize The size of a file record. 2360 * @return True if successfully completed, false if not. 2361 * @exception FTPConnectionClosedException 2362 * If the FTP server prematurely closes the connection as a result 2363 * of the client being idle or some other reason causing the server 2364 * to send FTP reply code 421. This exception may be caught either 2365 * as an IOException or independently as itself. 2366 * @exception IOException If an I/O error occurs while either sending a 2367 * command to the server or receiving a reply from the server. 2368 */ 2369 public boolean allocate(int bytes, int recordSize) throws IOException 2370 { 2371 return FTPReply.isPositiveCompletion(allo(bytes, recordSize)); 2372 } 2373 2374 2375 /** 2376 * Issue a command and wait for the reply. 2377 * <p> 2378 * Should only be used with commands that return replies on the 2379 * command channel - do not use for LIST, NLST, MLSD etc. 2380 * <p> 2381 * @param command The command to invoke 2382 * @param params The parameters string, may be {@code null} 2383 * @return True if successfully completed, false if not, in which case 2384 * call {@link #getReplyCode()} or {@link #getReplyString()} 2385 * to get the reason. 2386 * 2387 * @exception IOException If an I/O error occurs while either sending a 2388 * command to the server or receiving a reply from the server. 2389 * @since 3.0 2390 */ 2391 public boolean doCommand(String command, String params) throws IOException 2392 { 2393 return FTPReply.isPositiveCompletion(sendCommand(command, params)); 2394 } 2395 2396 /** 2397 * Issue a command and wait for the reply, returning it as an array of strings. 2398 * <p> 2399 * Should only be used with commands that return replies on the 2400 * command channel - do not use for LIST, NLST, MLSD etc. 2401 * <p> 2402 * @param command The command to invoke 2403 * @param params The parameters string, may be {@code null} 2404 * @return The array of replies, or {@code null} if the command failed, in which case 2405 * call {@link #getReplyCode()} or {@link #getReplyString()} 2406 * to get the reason. 2407 * 2408 * @exception IOException If an I/O error occurs while either sending a 2409 * command to the server or receiving a reply from the server. 2410 * @since 3.0 2411 */ 2412 public String[] doCommandAsStrings(String command, String params) throws IOException 2413 { 2414 boolean success = FTPReply.isPositiveCompletion(sendCommand(command, params)); 2415 if (success){ 2416 return getReplyStrings(); 2417 } else { 2418 return null; 2419 } 2420 } 2421 2422 /** 2423 * Get file details using the MLST command 2424 * 2425 * @param pathname the file or directory to list, may be {@code} null 2426 * @return the file details, may be {@code null} 2427 * @throws IOException 2428 * @since 3.0 2429 */ 2430 public FTPFile mlistFile(String pathname) throws IOException 2431 { 2432 boolean success = FTPReply.isPositiveCompletion(sendCommand(FTPCmd.MLST, pathname)); 2433 if (success){ 2434 String entry = getReplyStrings()[1].substring(1); // skip leading space for parser 2435 return MLSxEntryParser.parseEntry(entry); 2436 } else { 2437 return null; 2438 } 2439 } 2440 2441 /** 2442 * Generate a directory listing for the current directory using the MLSD command. 2443 * 2444 * @return the array of file entries 2445 * @throws IOException 2446 * @since 3.0 2447 */ 2448 public FTPFile[] mlistDir() throws IOException 2449 { 2450 return mlistDir(null); 2451 } 2452 2453 /** 2454 * Generate a directory listing using the MLSD command. 2455 * 2456 * @param pathname the directory name, may be {@code null} 2457 * @return the array of file entries 2458 * @throws IOException 2459 * @since 3.0 2460 */ 2461 public FTPFile[] mlistDir(String pathname) throws IOException 2462 { 2463 FTPListParseEngine engine = initiateMListParsing( pathname); 2464 return engine.getFiles(); 2465 } 2466 2467 /** 2468 * Generate a directory listing using the MLSD command. 2469 * 2470 * @param pathname the directory name, may be {@code null} 2471 * @param filter the filter to apply to the responses 2472 * @return the array of file entries 2473 * @throws IOException 2474 * @since 3.0 2475 */ 2476 public FTPFile[] mlistDir(String pathname, FTPFileFilter filter) throws IOException 2477 { 2478 FTPListParseEngine engine = initiateMListParsing( pathname); 2479 return engine.getFiles(filter); 2480 } 2481 2482 /** 2483 * Restart a <code>STREAM_TRANSFER_MODE</code> file transfer starting 2484 * from the given offset. This will only work on FTP servers supporting 2485 * the REST comand for the stream transfer mode. However, most FTP 2486 * servers support this. Any subsequent file transfer will start 2487 * reading or writing the remote file from the indicated offset. 2488 * <p> 2489 * @param offset The offset into the remote file at which to start the 2490 * next file transfer. 2491 * @return True if successfully completed, false if not. 2492 * @exception FTPConnectionClosedException 2493 * If the FTP server prematurely closes the connection as a result 2494 * of the client being idle or some other reason causing the server 2495 * to send FTP reply code 421. This exception may be caught either 2496 * as an IOException or independently as itself. 2497 * @exception IOException If an I/O error occurs while either sending a 2498 * command to the server or receiving a reply from the server. 2499 * @since 3.1 (changed from private to protected) 2500 */ 2501 protected boolean restart(long offset) throws IOException 2502 { 2503 __restartOffset = 0; 2504 return FTPReply.isPositiveIntermediate(rest(Long.toString(offset))); 2505 } 2506 2507 /** 2508 * Sets the restart offset for file transfers. 2509 * <p> 2510 * The restart command is not sent to the server immediately. 2511 * It is sent when a data connection is created as part of a 2512 * subsequent command. 2513 * The restart marker is reset to zero after use. 2514 * </p> 2515 * <p> 2516 * <b>Note: This method should only be invoked immediately prior to 2517 * the transfer to which it applies.</b> 2518 * 2519 * @param offset The offset into the remote file at which to start the 2520 * next file transfer. This must be a value greater than or 2521 * equal to zero. 2522 */ 2523 public void setRestartOffset(long offset) 2524 { 2525 if (offset >= 0) { 2526 __restartOffset = offset; 2527 } 2528 } 2529 2530 /** 2531 * Fetches the restart offset. 2532 * <p> 2533 * @return offset The offset into the remote file at which to start the 2534 * next file transfer. 2535 */ 2536 public long getRestartOffset() 2537 { 2538 return __restartOffset; 2539 } 2540 2541 2542 2543 /** 2544 * Renames a remote file. 2545 * <p> 2546 * @param from The name of the remote file to rename. 2547 * @param to The new name of the remote file. 2548 * @return True if successfully completed, false if not. 2549 * @exception FTPConnectionClosedException 2550 * If the FTP server prematurely closes the connection as a result 2551 * of the client being idle or some other reason causing the server 2552 * to send FTP reply code 421. This exception may be caught either 2553 * as an IOException or independently as itself. 2554 * @exception IOException If an I/O error occurs while either sending a 2555 * command to the server or receiving a reply from the server. 2556 */ 2557 public boolean rename(String from, String to) throws IOException 2558 { 2559 if (!FTPReply.isPositiveIntermediate(rnfr(from))) { 2560 return false; 2561 } 2562 2563 return FTPReply.isPositiveCompletion(rnto(to)); 2564 } 2565 2566 2567 /** 2568 * Abort a transfer in progress. 2569 * <p> 2570 * @return True if successfully completed, false if not. 2571 * @exception FTPConnectionClosedException 2572 * If the FTP server prematurely closes the connection as a result 2573 * of the client being idle or some other reason causing the server 2574 * to send FTP reply code 421. This exception may be caught either 2575 * as an IOException or independently as itself. 2576 * @exception IOException If an I/O error occurs while either sending a 2577 * command to the server or receiving a reply from the server. 2578 */ 2579 public boolean abort() throws IOException 2580 { 2581 return FTPReply.isPositiveCompletion(abor()); 2582 } 2583 2584 /** 2585 * Deletes a file on the FTP server. 2586 * <p> 2587 * @param pathname The pathname of the file to be deleted. 2588 * @return True if successfully completed, false if not. 2589 * @exception FTPConnectionClosedException 2590 * If the FTP server prematurely closes the connection as a result 2591 * of the client being idle or some other reason causing the server 2592 * to send FTP reply code 421. This exception may be caught either 2593 * as an IOException or independently as itself. 2594 * @exception IOException If an I/O error occurs while either sending a 2595 * command to the server or receiving a reply from the server. 2596 */ 2597 public boolean deleteFile(String pathname) throws IOException 2598 { 2599 return FTPReply.isPositiveCompletion(dele(pathname)); 2600 } 2601 2602 2603 /** 2604 * Removes a directory on the FTP server (if empty). 2605 * <p> 2606 * @param pathname The pathname of the directory to remove. 2607 * @return True if successfully completed, false if not. 2608 * @exception FTPConnectionClosedException 2609 * If the FTP server prematurely closes the connection as a result 2610 * of the client being idle or some other reason causing the server 2611 * to send FTP reply code 421. This exception may be caught either 2612 * as an IOException or independently as itself. 2613 * @exception IOException If an I/O error occurs while either sending a 2614 * command to the server or receiving a reply from the server. 2615 */ 2616 public boolean removeDirectory(String pathname) throws IOException 2617 { 2618 return FTPReply.isPositiveCompletion(rmd(pathname)); 2619 } 2620 2621 2622 /** 2623 * Creates a new subdirectory on the FTP server in the current directory 2624 * (if a relative pathname is given) or where specified (if an absolute 2625 * pathname is given). 2626 * <p> 2627 * @param pathname The pathname of the directory to create. 2628 * @return True if successfully completed, false if not. 2629 * @exception FTPConnectionClosedException 2630 * If the FTP server prematurely closes the connection as a result 2631 * of the client being idle or some other reason causing the server 2632 * to send FTP reply code 421. This exception may be caught either 2633 * as an IOException or independently as itself. 2634 * @exception IOException If an I/O error occurs while either sending a 2635 * command to the server or receiving a reply from the server. 2636 */ 2637 public boolean makeDirectory(String pathname) throws IOException 2638 { 2639 return FTPReply.isPositiveCompletion(mkd(pathname)); 2640 } 2641 2642 2643 /** 2644 * Returns the pathname of the current working directory. 2645 * <p> 2646 * @return The pathname of the current working directory. If it cannot 2647 * be obtained, returns null. 2648 * @exception FTPConnectionClosedException 2649 * If the FTP server prematurely closes the connection as a result 2650 * of the client being idle or some other reason causing the server 2651 * to send FTP reply code 421. This exception may be caught either 2652 * as an IOException or independently as itself. 2653 * @exception IOException If an I/O error occurs while either sending a 2654 * command to the server or receiving a reply from the server. 2655 */ 2656 public String printWorkingDirectory() throws IOException 2657 { 2658 if (pwd() != FTPReply.PATHNAME_CREATED) { 2659 return null; 2660 } 2661 2662 return __parsePathname(_replyLines.get( _replyLines.size() - 1)); 2663 } 2664 2665 2666 /** 2667 * Send a site specific command. 2668 * @param arguments The site specific command and arguments. 2669 * @return True if successfully completed, false if not. 2670 * @exception FTPConnectionClosedException 2671 * If the FTP server prematurely closes the connection as a result 2672 * of the client being idle or some other reason causing the server 2673 * to send FTP reply code 421. This exception may be caught either 2674 * as an IOException or independently as itself. 2675 * @exception IOException If an I/O error occurs while either sending a 2676 * command to the server or receiving a reply from the server. 2677 */ 2678 public boolean sendSiteCommand(String arguments) throws IOException 2679 { 2680 return FTPReply.isPositiveCompletion(site(arguments)); 2681 } 2682 2683 2684 /** 2685 * Fetches the system type from the server and returns the string. 2686 * This value is cached for the duration of the connection after the 2687 * first call to this method. In other words, only the first time 2688 * that you invoke this method will it issue a SYST command to the 2689 * FTP server. FTPClient will remember the value and return the 2690 * cached value until a call to disconnect. 2691 * <p> 2692 * If the SYST command fails, and the system property 2693 * {@link #FTP_SYSTEM_TYPE_DEFAULT} is defined, then this is used instead. 2694 * @return The system type obtained from the server. Never null. 2695 * @exception FTPConnectionClosedException 2696 * If the FTP server prematurely closes the connection as a result 2697 * of the client being idle or some other reason causing the server 2698 * to send FTP reply code 421. This exception may be caught either 2699 * as an IOException or independently as itself. 2700 * @exception IOException If an I/O error occurs while either sending a 2701 * command to the server or receiving a reply from the server (and the default 2702 * system type property is not defined) 2703 * @since 2.2 2704 */ 2705 public String getSystemType() throws IOException 2706 { 2707 //if (syst() == FTPReply.NAME_SYSTEM_TYPE) 2708 // Technically, we should expect a NAME_SYSTEM_TYPE response, but 2709 // in practice FTP servers deviate, so we soften the condition to 2710 // a positive completion. 2711 if (__systemName == null){ 2712 if (FTPReply.isPositiveCompletion(syst())) { 2713 // Assume that response is not empty here (cannot be null) 2714 __systemName = _replyLines.get(_replyLines.size() - 1).substring(4); 2715 } else { 2716 // Check if the user has provided a default for when the SYST command fails 2717 String systDefault = System.getProperty(FTP_SYSTEM_TYPE_DEFAULT); 2718 if (systDefault != null) { 2719 __systemName = systDefault; 2720 } else { 2721 throw new IOException("Unable to determine system type - response: " + getReplyString()); 2722 } 2723 } 2724 } 2725 return __systemName; 2726 } 2727 2728 2729 /** 2730 * Fetches the system help information from the server and returns the 2731 * full string. 2732 * <p> 2733 * @return The system help string obtained from the server. null if the 2734 * information could not be obtained. 2735 * @exception FTPConnectionClosedException 2736 * If the FTP server prematurely closes the connection as a result 2737 * of the client being idle or some other reason causing the server 2738 * to send FTP reply code 421. This exception may be caught either 2739 * as an IOException or independently as itself. 2740 * @exception IOException If an I/O error occurs while either sending a 2741 * command to the server or receiving a reply from the server. 2742 */ 2743 public String listHelp() throws IOException 2744 { 2745 if (FTPReply.isPositiveCompletion(help())) { 2746 return getReplyString(); 2747 } 2748 return null; 2749 } 2750 2751 2752 /** 2753 * Fetches the help information for a given command from the server and 2754 * returns the full string. 2755 * @param command The command on which to ask for help. 2756 * @return The command help string obtained from the server. null if the 2757 * information could not be obtained. 2758 * @exception FTPConnectionClosedException 2759 * If the FTP server prematurely closes the connection as a result 2760 * of the client being idle or some other reason causing the server 2761 * to send FTP reply code 421. This exception may be caught either 2762 * as an IOException or independently as itself. 2763 * @exception IOException If an I/O error occurs while either sending a 2764 * command to the server or receiving a reply from the server. 2765 */ 2766 public String listHelp(String command) throws IOException 2767 { 2768 if (FTPReply.isPositiveCompletion(help(command))) { 2769 return getReplyString(); 2770 } 2771 return null; 2772 } 2773 2774 2775 /** 2776 * Sends a NOOP command to the FTP server. This is useful for preventing 2777 * server timeouts. 2778 * <p> 2779 * @return True if successfully completed, false if not. 2780 * @exception FTPConnectionClosedException 2781 * If the FTP server prematurely closes the connection as a result 2782 * of the client being idle or some other reason causing the server 2783 * to send FTP reply code 421. This exception may be caught either 2784 * as an IOException or independently as itself. 2785 * @exception IOException If an I/O error occurs while either sending a 2786 * command to the server or receiving a reply from the server. 2787 */ 2788 public boolean sendNoOp() throws IOException 2789 { 2790 return FTPReply.isPositiveCompletion(noop()); 2791 } 2792 2793 2794 /** 2795 * Obtain a list of filenames in a directory (or just the name of a given 2796 * file, which is not particularly useful). This information is obtained 2797 * through the NLST command. If the given pathname is a directory and 2798 * contains no files, a zero length array is returned only 2799 * if the FTP server returned a positive completion code, otherwise 2800 * null is returned (the FTP server returned a 550 error No files found.). 2801 * If the directory is not empty, an array of filenames in the directory is 2802 * returned. If the pathname corresponds 2803 * to a file, only that file will be listed. The server may or may not 2804 * expand glob expressions. 2805 * <p> 2806 * @param pathname The file or directory to list. 2807 * Warning: the server may treat a leading '-' as an 2808 * option introducer. If so, try using an absolute path, 2809 * or prefix the path with ./ (unix style servers). 2810 * Some servers may support "--" as meaning end of options, 2811 * in which case "-- -xyz" should work. 2812 * @return The list of filenames contained in the given path. null if 2813 * the list could not be obtained. If there are no filenames in 2814 * the directory, a zero-length array is returned. 2815 * @exception FTPConnectionClosedException 2816 * If the FTP server prematurely closes the connection as a result 2817 * of the client being idle or some other reason causing the server 2818 * to send FTP reply code 421. This exception may be caught either 2819 * as an IOException or independently as itself. 2820 * @exception IOException If an I/O error occurs while either sending a 2821 * command to the server or receiving a reply from the server. 2822 */ 2823 public String[] listNames(String pathname) throws IOException 2824 { 2825 Socket socket = _openDataConnection_(FTPCmd.NLST, getListArguments(pathname)); 2826 2827 if (socket == null) { 2828 return null; 2829 } 2830 2831 BufferedReader reader = 2832 new BufferedReader(new InputStreamReader(socket.getInputStream(), getControlEncoding())); 2833 2834 ArrayList<String> results = new ArrayList<String>(); 2835 String line; 2836 while ((line = reader.readLine()) != null) { 2837 results.add(line); 2838 } 2839 2840 reader.close(); 2841 socket.close(); 2842 2843 if (completePendingCommand()) 2844 { 2845 String[] names = new String[ results.size() ]; 2846 return results.toArray(names); 2847 } 2848 2849 return null; 2850 } 2851 2852 2853 /** 2854 * Obtain a list of filenames in the current working directory 2855 * This information is obtained through the NLST command. If the current 2856 * directory contains no files, a zero length array is returned only 2857 * if the FTP server returned a positive completion code, otherwise, 2858 * null is returned (the FTP server returned a 550 error No files found.). 2859 * If the directory is not empty, an array of filenames in the directory is 2860 * returned. 2861 * <p> 2862 * @return The list of filenames contained in the current working 2863 * directory. null if the list could not be obtained. 2864 * If there are no filenames in the directory, a zero-length array 2865 * is returned. 2866 * @exception FTPConnectionClosedException 2867 * If the FTP server prematurely closes the connection as a result 2868 * of the client being idle or some other reason causing the server 2869 * to send FTP reply code 421. This exception may be caught either 2870 * as an IOException or independently as itself. 2871 * @exception IOException If an I/O error occurs while either sending a 2872 * command to the server or receiving a reply from the server. 2873 */ 2874 public String[] listNames() throws IOException 2875 { 2876 return listNames(null); 2877 } 2878 2879 2880 2881 /** 2882 * Using the default system autodetect mechanism, obtain a 2883 * list of file information for the current working directory 2884 * or for just a single file. 2885 * <p> 2886 * This information is obtained through the LIST command. The contents of 2887 * the returned array is determined by the<code> FTPFileEntryParser </code> 2888 * used. 2889 * <p> 2890 * @param pathname The file or directory to list. Since the server may 2891 * or may not expand glob expressions, using them here 2892 * is not recommended and may well cause this method to 2893 * fail. 2894 * Also, some servers treat a leading '-' as being an option. 2895 * To avoid this interpretation, use an absolute pathname 2896 * or prefix the pathname with ./ (unix style servers). 2897 * Some servers may support "--" as meaning end of options, 2898 * in which case "-- -xyz" should work. 2899 * 2900 * @return The list of file information contained in the given path in 2901 * the format determined by the autodetection mechanism 2902 * @exception FTPConnectionClosedException 2903 * If the FTP server prematurely closes the connection 2904 * as a result of the client being idle or some other 2905 * reason causing the server to send FTP reply code 421. 2906 * This exception may be caught either as an IOException 2907 * or independently as itself. 2908 * @exception IOException 2909 * If an I/O error occurs while either sending a 2910 * command to the server or receiving a reply 2911 * from the server. 2912 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 2913 * Thrown if the parserKey parameter cannot be 2914 * resolved by the selected parser factory. 2915 * In the DefaultFTPEntryParserFactory, this will 2916 * happen when parserKey is neither 2917 * the fully qualified class name of a class 2918 * implementing the interface 2919 * org.apache.commons.net.ftp.FTPFileEntryParser 2920 * nor a string containing one of the recognized keys 2921 * mapping to such a parser or if class loader 2922 * security issues prevent its being loaded. 2923 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 2924 * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory 2925 * @see org.apache.commons.net.ftp.FTPFileEntryParser 2926 */ 2927 public FTPFile[] listFiles(String pathname) 2928 throws IOException 2929 { 2930 FTPListParseEngine engine = initiateListParsing((String) null, pathname); 2931 return engine.getFiles(); 2932 2933 } 2934 2935 /** 2936 * Using the default system autodetect mechanism, obtain a 2937 * list of file information for the current working directory. 2938 * <p> 2939 * This information is obtained through the LIST command. The contents of 2940 * the returned array is determined by the<code> FTPFileEntryParser </code> 2941 * used. 2942 * <p> 2943 * @return The list of file information contained in the current directory 2944 * in the format determined by the autodetection mechanism. 2945 * <p><b> 2946 * NOTE:</b> This array may contain null members if any of the 2947 * individual file listings failed to parse. The caller should 2948 * check each entry for null before referencing it. 2949 * @exception FTPConnectionClosedException 2950 * If the FTP server prematurely closes the connection 2951 * as a result of the client being idle or some other 2952 * reason causing the server to send FTP reply code 421. 2953 * This exception may be caught either as an IOException 2954 * or independently as itself. 2955 * @exception IOException 2956 * If an I/O error occurs while either sending a 2957 * command to the server or receiving a reply 2958 * from the server. 2959 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 2960 * Thrown if the parserKey parameter cannot be 2961 * resolved by the selected parser factory. 2962 * In the DefaultFTPEntryParserFactory, this will 2963 * happen when parserKey is neither 2964 * the fully qualified class name of a class 2965 * implementing the interface 2966 * org.apache.commons.net.ftp.FTPFileEntryParser 2967 * nor a string containing one of the recognized keys 2968 * mapping to such a parser or if class loader 2969 * security issues prevent its being loaded. 2970 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 2971 * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory 2972 * @see org.apache.commons.net.ftp.FTPFileEntryParser 2973 */ 2974 public FTPFile[] listFiles() 2975 throws IOException 2976 { 2977 return listFiles((String) null); 2978 } 2979 2980 /** 2981 * Version of {@link #listFiles(String)} which allows a filter to be provided. 2982 * For example: <code>listFiles("site", FTPFileFilters.DIRECTORY);</code> 2983 * @param pathname the initial path, may be null 2984 * @param filter the filter, non-null 2985 * @return the list of FTPFile entries. 2986 * @throws IOException 2987 * @since 2.2 2988 */ 2989 public FTPFile[] listFiles(String pathname, FTPFileFilter filter) 2990 throws IOException 2991 { 2992 FTPListParseEngine engine = initiateListParsing((String) null, pathname); 2993 return engine.getFiles(filter); 2994 2995 } 2996 2997 /** 2998 * Using the default system autodetect mechanism, obtain a 2999 * list of directories contained in the current working directory. 3000 * <p> 3001 * This information is obtained through the LIST command. The contents of 3002 * the returned array is determined by the<code> FTPFileEntryParser </code> 3003 * used. 3004 * <p> 3005 * @return The list of directories contained in the current directory 3006 * in the format determined by the autodetection mechanism. 3007 * 3008 * @exception FTPConnectionClosedException 3009 * If the FTP server prematurely closes the connection 3010 * as a result of the client being idle or some other 3011 * reason causing the server to send FTP reply code 421. 3012 * This exception may be caught either as an IOException 3013 * or independently as itself. 3014 * @exception IOException 3015 * If an I/O error occurs while either sending a 3016 * command to the server or receiving a reply 3017 * from the server. 3018 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 3019 * Thrown if the parserKey parameter cannot be 3020 * resolved by the selected parser factory. 3021 * In the DefaultFTPEntryParserFactory, this will 3022 * happen when parserKey is neither 3023 * the fully qualified class name of a class 3024 * implementing the interface 3025 * org.apache.commons.net.ftp.FTPFileEntryParser 3026 * nor a string containing one of the recognized keys 3027 * mapping to such a parser or if class loader 3028 * security issues prevent its being loaded. 3029 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 3030 * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory 3031 * @see org.apache.commons.net.ftp.FTPFileEntryParser 3032 * @since 3.0 3033 */ 3034 public FTPFile[] listDirectories() throws IOException { 3035 return listDirectories((String) null); 3036 } 3037 3038 /** 3039 * Using the default system autodetect mechanism, obtain a 3040 * list of directories contained in the specified directory. 3041 * <p> 3042 * This information is obtained through the LIST command. The contents of 3043 * the returned array is determined by the<code> FTPFileEntryParser </code> 3044 * used. 3045 * <p> 3046 * @return The list of directories contained in the specified directory 3047 * in the format determined by the autodetection mechanism. 3048 * 3049 * @exception FTPConnectionClosedException 3050 * If the FTP server prematurely closes the connection 3051 * as a result of the client being idle or some other 3052 * reason causing the server to send FTP reply code 421. 3053 * This exception may be caught either as an IOException 3054 * or independently as itself. 3055 * @exception IOException 3056 * If an I/O error occurs while either sending a 3057 * command to the server or receiving a reply 3058 * from the server. 3059 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 3060 * Thrown if the parserKey parameter cannot be 3061 * resolved by the selected parser factory. 3062 * In the DefaultFTPEntryParserFactory, this will 3063 * happen when parserKey is neither 3064 * the fully qualified class name of a class 3065 * implementing the interface 3066 * org.apache.commons.net.ftp.FTPFileEntryParser 3067 * nor a string containing one of the recognized keys 3068 * mapping to such a parser or if class loader 3069 * security issues prevent its being loaded. 3070 * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory 3071 * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory 3072 * @see org.apache.commons.net.ftp.FTPFileEntryParser 3073 * @since 3.0 3074 */ 3075 public FTPFile[] listDirectories(String parent) throws IOException { 3076 return listFiles(parent, FTPFileFilters.DIRECTORIES); 3077 } 3078 3079 /** 3080 * Using the default autodetect mechanism, initialize an FTPListParseEngine 3081 * object containing a raw file information for the current working 3082 * directory on the server 3083 * This information is obtained through the LIST command. This object 3084 * is then capable of being iterated to return a sequence of FTPFile 3085 * objects with information filled in by the 3086 * <code> FTPFileEntryParser </code> used. 3087 * <p> 3088 * This method differs from using the listFiles() methods in that 3089 * expensive FTPFile objects are not created until needed which may be 3090 * an advantage on large lists. 3091 * 3092 * @return A FTPListParseEngine object that holds the raw information and 3093 * is capable of providing parsed FTPFile objects, one for each file 3094 * containing information contained in the given path in the format 3095 * determined by the <code> parser </code> parameter. Null will be 3096 * returned if a data connection cannot be opened. If the current working 3097 * directory contains no files, an empty array will be the return. 3098 * 3099 * @exception FTPConnectionClosedException 3100 * If the FTP server prematurely closes the connection as a result 3101 * of the client being idle or some other reason causing the server 3102 * to send FTP reply code 421. This exception may be caught either 3103 * as an IOException or independently as itself. 3104 * @exception IOException 3105 * If an I/O error occurs while either sending a 3106 * command to the server or receiving a reply from the server. 3107 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 3108 * Thrown if the autodetect mechanism cannot 3109 * resolve the type of system we are connected with. 3110 * @see FTPListParseEngine 3111 */ 3112 public FTPListParseEngine initiateListParsing() 3113 throws IOException 3114 { 3115 return initiateListParsing((String) null); 3116 } 3117 3118 /** 3119 * Using the default autodetect mechanism, initialize an FTPListParseEngine 3120 * object containing a raw file information for the supplied directory. 3121 * This information is obtained through the LIST command. This object 3122 * is then capable of being iterated to return a sequence of FTPFile 3123 * objects with information filled in by the 3124 * <code> FTPFileEntryParser </code> used. 3125 * <p> 3126 * The server may or may not expand glob expressions. You should avoid 3127 * using glob expressions because the return format for glob listings 3128 * differs from server to server and will likely cause this method to fail. 3129 * <p> 3130 * This method differs from using the listFiles() methods in that 3131 * expensive FTPFile objects are not created until needed which may be 3132 * an advantage on large lists. 3133 * <p> 3134 * <pre> 3135 * FTPClient f=FTPClient(); 3136 * f.connect(server); 3137 * f.login(username, password); 3138 * FTPListParseEngine engine = f.initiateListParsing(directory); 3139 * 3140 * while (engine.hasNext()) { 3141 * FTPFile[] files = engine.getNext(25); // "page size" you want 3142 * //do whatever you want with these files, display them, etc. 3143 * //expensive FTPFile objects not created until needed. 3144 * } 3145 * </pre> 3146 * 3147 * @return A FTPListParseEngine object that holds the raw information and 3148 * is capable of providing parsed FTPFile objects, one for each file 3149 * containing information contained in the given path in the format 3150 * determined by the <code> parser </code> parameter. Null will be 3151 * returned if a data connection cannot be opened. If the current working 3152 * directory contains no files, an empty array will be the return. 3153 * 3154 * @exception FTPConnectionClosedException 3155 * If the FTP server prematurely closes the connection as a result 3156 * of the client being idle or some other reason causing the server 3157 * to send FTP reply code 421. This exception may be caught either 3158 * as an IOException or independently as itself. 3159 * @exception IOException 3160 * If an I/O error occurs while either sending a 3161 * command to the server or receiving a reply from the server. 3162 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 3163 * Thrown if the autodetect mechanism cannot 3164 * resolve the type of system we are connected with. 3165 * @see FTPListParseEngine 3166 */ 3167 public FTPListParseEngine initiateListParsing( 3168 String pathname) 3169 throws IOException 3170 { 3171 return initiateListParsing((String) null, pathname); 3172 } 3173 3174 /** 3175 * Using the supplied parser key, initialize an FTPListParseEngine 3176 * object containing a raw file information for the supplied directory. 3177 * This information is obtained through the LIST command. This object 3178 * is then capable of being iterated to return a sequence of FTPFile 3179 * objects with information filled in by the 3180 * <code> FTPFileEntryParser </code> used. 3181 * <p> 3182 * The server may or may not expand glob expressions. You should avoid 3183 * using glob expressions because the return format for glob listings 3184 * differs from server to server and will likely cause this method to fail. 3185 * <p> 3186 * This method differs from using the listFiles() methods in that 3187 * expensive FTPFile objects are not created until needed which may be 3188 * an advantage on large lists. 3189 * 3190 * @param parserKey A string representing a designated code or fully-qualified 3191 * class name of an <code> FTPFileEntryParser </code> that should be 3192 * used to parse each server file listing. 3193 * May be {@code null}, in which case the code checks first 3194 * the system property {@link #FTP_SYSTEM_TYPE}, and if that is 3195 * not defined the SYST command is used to provide the value. 3196 * To allow for arbitrary system types, the return from the 3197 * SYST command is used to look up an alias for the type in the 3198 * {@link #SYSTEM_TYPE_PROPERTIES} properties file if it is available. 3199 * 3200 * @return A FTPListParseEngine object that holds the raw information and 3201 * is capable of providing parsed FTPFile objects, one for each file 3202 * containing information contained in the given path in the format 3203 * determined by the <code> parser </code> parameter. Null will be 3204 * returned if a data connection cannot be opened. If the current working 3205 * directory contains no files, an empty array will be the return. 3206 * 3207 * @exception FTPConnectionClosedException 3208 * If the FTP server prematurely closes the connection as a result 3209 * of the client being idle or some other reason causing the server 3210 * to send FTP reply code 421. This exception may be caught either 3211 * as an IOException or independently as itself. 3212 * @exception IOException 3213 * If an I/O error occurs while either sending a 3214 * command to the server or receiving a reply from the server. 3215 * @exception org.apache.commons.net.ftp.parser.ParserInitializationException 3216 * Thrown if the parserKey parameter cannot be 3217 * resolved by the selected parser factory. 3218 * In the DefaultFTPEntryParserFactory, this will 3219 * happen when parserKey is neither 3220 * the fully qualified class name of a class 3221 * implementing the interface 3222 * org.apache.commons.net.ftp.FTPFileEntryParser 3223 * nor a string containing one of the recognized keys 3224 * mapping to such a parser or if class loader 3225 * security issues prevent its being loaded. 3226 * @see FTPListParseEngine 3227 */ 3228 public FTPListParseEngine initiateListParsing( 3229 String parserKey, String pathname) 3230 throws IOException 3231 { 3232 // We cache the value to avoid creation of a new object every 3233 // time a file listing is generated. 3234 if(__entryParser == null || ! __entryParserKey.equals(parserKey)) { 3235 if (null != parserKey) { 3236 // if a parser key was supplied in the parameters, 3237 // use that to create the parser 3238 __entryParser = 3239 __parserFactory.createFileEntryParser(parserKey); 3240 __entryParserKey = parserKey; 3241 3242 } else { 3243 // if no parserKey was supplied, check for a configuration 3244 // in the params, and if non-null, use that. 3245 if (null != __configuration) { 3246 __entryParser = 3247 __parserFactory.createFileEntryParser(__configuration); 3248 __entryParserKey = __configuration.getServerSystemKey(); 3249 } else { 3250 // if a parserKey hasn't been supplied, and a configuration 3251 // hasn't been supplied, and the override property is not set 3252 // then autodetect by calling 3253 // the SYST command and use that to choose the parser. 3254 String systemType = System.getProperty(FTP_SYSTEM_TYPE); 3255 if (systemType == null) { 3256 systemType = getSystemType(); // cannot be null 3257 Properties override = getOverrideProperties(); 3258 if (override != null) { 3259 String newType = override.getProperty(systemType); 3260 if (newType != null) { 3261 systemType = newType; 3262 } 3263 } 3264 } 3265 __entryParser = __parserFactory.createFileEntryParser(systemType); 3266 __entryParserKey = systemType; 3267 } 3268 } 3269 } 3270 3271 return initiateListParsing(__entryParser, pathname); 3272 3273 } 3274 3275 /** 3276 * private method through which all listFiles() and 3277 * initiateListParsing methods pass once a parser is determined. 3278 * 3279 * @exception FTPConnectionClosedException 3280 * If the FTP server prematurely closes the connection as a result 3281 * of the client being idle or some other reason causing the server 3282 * to send FTP reply code 421. This exception may be caught either 3283 * as an IOException or independently as itself. 3284 * @exception IOException 3285 * If an I/O error occurs while either sending a 3286 * command to the server or receiving a reply from the server. 3287 * @see FTPListParseEngine 3288 */ 3289 private FTPListParseEngine initiateListParsing( 3290 FTPFileEntryParser parser, String pathname) 3291 throws IOException 3292 { 3293 Socket socket = _openDataConnection_(FTPCmd.LIST, getListArguments(pathname)); 3294 3295 FTPListParseEngine engine = new FTPListParseEngine(parser); 3296 if (socket == null) 3297 { 3298 return engine; 3299 } 3300 3301 try { 3302 engine.readServerList(socket.getInputStream(), getControlEncoding()); 3303 } 3304 finally { 3305 Util.closeQuietly(socket); 3306 } 3307 3308 completePendingCommand(); 3309 return engine; 3310 } 3311 3312 /** 3313 * Initiate list parsing for MLSD listings. 3314 * 3315 * @param pathname 3316 * @return the engine 3317 * @throws IOException 3318 */ 3319 private FTPListParseEngine initiateMListParsing(String pathname) throws IOException 3320 { 3321 Socket socket = _openDataConnection_(FTPCmd.MLSD, pathname); 3322 FTPListParseEngine engine = new FTPListParseEngine(MLSxEntryParser.getInstance()); 3323 if (socket == null) 3324 { 3325 return engine; 3326 } 3327 3328 try { 3329 engine.readServerList(socket.getInputStream(), getControlEncoding()); 3330 } 3331 finally { 3332 Util.closeQuietly(socket); 3333 completePendingCommand(); 3334 } 3335 return engine; 3336 } 3337 3338 /** 3339 * @since 2.0 3340 */ 3341 protected String getListArguments(String pathname) { 3342 if (getListHiddenFiles()) 3343 { 3344 if (pathname != null) 3345 { 3346 StringBuilder sb = new StringBuilder(pathname.length() + 3); 3347 sb.append("-a "); 3348 sb.append(pathname); 3349 return sb.toString(); 3350 } 3351 else 3352 { 3353 return "-a"; 3354 } 3355 } 3356 3357 return pathname; 3358 } 3359 3360 3361 /** 3362 * Issue the FTP STAT command to the server. 3363 * <p> 3364 * @return The status information returned by the server. 3365 * @exception FTPConnectionClosedException 3366 * If the FTP server prematurely closes the connection as a result 3367 * of the client being idle or some other reason causing the server 3368 * to send FTP reply code 421. This exception may be caught either 3369 * as an IOException or independently as itself. 3370 * @exception IOException If an I/O error occurs while either sending a 3371 * command to the server or receiving a reply from the server. 3372 */ 3373 public String getStatus() throws IOException 3374 { 3375 if (FTPReply.isPositiveCompletion(stat())) { 3376 return getReplyString(); 3377 } 3378 return null; 3379 } 3380 3381 3382 /** 3383 * Issue the FTP STAT command to the server for a given pathname. This 3384 * should produce a listing of the file or directory. 3385 * <p> 3386 * @return The status information returned by the server. 3387 * @exception FTPConnectionClosedException 3388 * If the FTP server prematurely closes the connection as a result 3389 * of the client being idle or some other reason causing the server 3390 * to send FTP reply code 421. This exception may be caught either 3391 * as an IOException or independently as itself. 3392 * @exception IOException If an I/O error occurs while either sending a 3393 * command to the server or receiving a reply from the server. 3394 */ 3395 public String getStatus(String pathname) throws IOException 3396 { 3397 if (FTPReply.isPositiveCompletion(stat(pathname))) { 3398 return getReplyString(); 3399 } 3400 return null; 3401 } 3402 3403 3404 /** 3405 * Issue the FTP MDTM command (not supported by all servers to retrieve the last 3406 * modification time of a file. The modification string should be in the 3407 * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in 3408 * GMT, but not all FTP servers honour this. 3409 * 3410 * @param pathname The file path to query. 3411 * @return A string representing the last file modification time in <code>YYYYMMDDhhmmss</code> format. 3412 * @throws IOException if an I/O error occurs. 3413 * @since 2.0 3414 */ 3415 public String getModificationTime(String pathname) throws IOException { 3416 if (FTPReply.isPositiveCompletion(mdtm(pathname))) { 3417 return getReplyString(); 3418 } 3419 return null; 3420 } 3421 3422 3423 /** 3424 * Issue the FTP MFMT command (not supported by all servers) which sets the last 3425 * modified time of a file. 3426 * 3427 * The timestamp should be in the form <code>YYYYMMDDhhmmss</code>. It should also 3428 * be in GMT, but not all servers honour this. 3429 * 3430 * An FTP server would indicate its support of this feature by including "MFMT" 3431 * in its response to the FEAT command, which may be retrieved by FTPClient.features() 3432 * 3433 * @param pathname The file path for which last modified time is to be changed. 3434 * @param timeval The timestamp to set to, in <code>YYYYMMDDhhmmss</code> format. 3435 * @return true if successfully set, false if not 3436 * @throws IOException if an I/O error occurs. 3437 * @since 2.2 3438 * @see <a href="http://tools.ietf.org/html/draft-somers-ftp-mfxx-04">http://tools.ietf.org/html/draft-somers-ftp-mfxx-04</a> 3439 */ 3440 public boolean setModificationTime(String pathname, String timeval) throws IOException { 3441 return (FTPReply.isPositiveCompletion(mfmt(pathname, timeval))); 3442 } 3443 3444 3445 /** 3446 * Set the internal buffer size for buffered data streams. 3447 * 3448 * @param bufSize The size of the buffer. Use a non-positive value to use the default. 3449 */ 3450 public void setBufferSize(int bufSize) { 3451 __bufferSize = bufSize; 3452 } 3453 3454 /** 3455 * Retrieve the current internal buffer size for buffered data streams. 3456 * @return The current buffer size. 3457 */ 3458 public int getBufferSize() { 3459 return __bufferSize; 3460 } 3461 3462 /** 3463 * Sets the value to be used for the data socket SO_SNDBUF option. 3464 * If the value is positive, the option will be set when the data socket has been created. 3465 * 3466 * @param bufSize The size of the buffer, zero or negative means the value is ignored. 3467 * @since 3.3 3468 */ 3469 public void setSendDataSocketBufferSize(int bufSize) { 3470 __sendDataSocketBufferSize = bufSize; 3471 } 3472 3473 /** 3474 * Retrieve the value to be used for the data socket SO_SNDBUF option. 3475 * @return The current buffer size. 3476 * @since 3.3 3477 */ 3478 public int getSendDataSocketBufferSize() { 3479 return __sendDataSocketBufferSize; 3480 } 3481 3482 /** 3483 * Sets the value to be used for the data socket SO_RCVBUF option. 3484 * If the value is positive, the option will be set when the data socket has been created. 3485 * 3486 * @param bufSize The size of the buffer, zero or negative means the value is ignored. 3487 * @since 3.3 3488 */ 3489 public void setReceieveDataSocketBufferSize(int bufSize) { 3490 __receiveDataSocketBufferSize = bufSize; 3491 } 3492 3493 /** 3494 * Retrieve the value to be used for the data socket SO_RCVBUF option. 3495 * @return The current buffer size. 3496 * @since 3.3 3497 */ 3498 public int getReceiveDataSocketBufferSize() { 3499 return __receiveDataSocketBufferSize; 3500 } 3501 3502 /** 3503 * Implementation of the {@link Configurable Configurable} interface. 3504 * In the case of this class, configuring merely makes the config object available for the 3505 * factory methods that construct parsers. 3506 * @param config {@link FTPClientConfig FTPClientConfig} object used to 3507 * provide non-standard configurations to the parser. 3508 * @since 1.4 3509 */ 3510 // @Override 3511 public void configure(FTPClientConfig config) { 3512 this.__configuration = config; 3513 } 3514 3515 /** 3516 * You can set this to true if you would like to get hidden files when {@link #listFiles} too. 3517 * A <code>LIST -a</code> will be issued to the ftp server. 3518 * It depends on your ftp server if you need to call this method, also dont expect to get rid 3519 * of hidden files if you call this method with "false". 3520 * 3521 * @param listHiddenFiles true if hidden files should be listed 3522 * @since 2.0 3523 */ 3524 public void setListHiddenFiles(boolean listHiddenFiles) { 3525 this.__listHiddenFiles = listHiddenFiles; 3526 } 3527 3528 /** 3529 * @see #setListHiddenFiles(boolean) 3530 * @return the current state 3531 * @since 2.0 3532 */ 3533 public boolean getListHiddenFiles() { 3534 return this.__listHiddenFiles; 3535 } 3536 3537 /** 3538 * Whether should attempt to use EPSV with IPv4. 3539 * Default (if not set) is <code>false</code> 3540 * @return true if should attempt EPSV 3541 * @since 2.2 3542 */ 3543 public boolean isUseEPSVwithIPv4() { 3544 return __useEPSVwithIPv4; 3545 } 3546 3547 3548 /** 3549 * Set whether to use EPSV with IPv4. 3550 * Might be worth enabling in some circumstances. 3551 * 3552 * For example, when using IPv4 with NAT it 3553 * may work with some rare configurations. 3554 * E.g. if FTP server has a static PASV address (external network) 3555 * and the client is coming from another internal network. 3556 * In that case the data connection after PASV command would fail, 3557 * while EPSV would make the client succeed by taking just the port. 3558 * 3559 * @param selected value to set. 3560 * @since 2.2 3561 */ 3562 public void setUseEPSVwithIPv4(boolean selected) { 3563 this.__useEPSVwithIPv4 = selected; 3564 } 3565 3566 /** 3567 * Set the listener to be used when performing store/retrieve operations. 3568 * The default value (if not set) is {@code null}. 3569 * 3570 * @param listener to be used, may be {@code null} to disable 3571 * @since 3.0 3572 */ 3573 public void setCopyStreamListener(CopyStreamListener listener){ 3574 __copyStreamListener = listener; 3575 } 3576 3577 /** 3578 * Obtain the currently active listener. 3579 * 3580 * @return the listener, may be {@code null} 3581 * @since 3.0 3582 */ 3583 public CopyStreamListener getCopyStreamListener(){ 3584 return __copyStreamListener; 3585 } 3586 3587 /** 3588 * Set the time to wait between sending control connection keepalive messages 3589 * when processing file upload or download. 3590 * 3591 * @param controlIdle the wait (in secs) between keepalive messages. Zero (or less) disables. 3592 * @since 3.0 3593 * @see #setControlKeepAliveReplyTimeout(int) 3594 */ 3595 public void setControlKeepAliveTimeout(long controlIdle){ 3596 __controlKeepAliveTimeout = controlIdle * 1000; 3597 } 3598 3599 /** 3600 * Get the time to wait between sending control connection keepalive messages. 3601 * @return the number of seconds between keepalive messages. 3602 * @since 3.0 3603 */ 3604 public long getControlKeepAliveTimeout() { 3605 return __controlKeepAliveTimeout / 1000; 3606 } 3607 3608 /** 3609 * Set how long to wait for control keep-alive message replies. 3610 * 3611 * @param timeout number of milliseconds to wait (defaults to 1000) 3612 * @since 3.0 3613 * @see #setControlKeepAliveTimeout(long) 3614 */ 3615 public void setControlKeepAliveReplyTimeout(int timeout) { 3616 __controlKeepAliveReplyTimeout = timeout; 3617 } 3618 3619 /** 3620 * Get how long to wait for control keep-alive message replies. 3621 * @since 3.0 3622 */ 3623 public int getControlKeepAliveReplyTimeout() { 3624 return __controlKeepAliveReplyTimeout; 3625 } 3626 3627 /** 3628 * Enable or disable passive mode NAT workaround. 3629 * If enabled, a site-local PASV mode reply address will be replaced with the 3630 * remote host address to which the PASV mode request was sent 3631 * (unless that is also a site local address). 3632 * This gets around the problem that some NAT boxes may change the 3633 * reply. 3634 * 3635 * The default is true, i.e. site-local replies are replaced. 3636 * @param enabled true to enable replacing internal IP's in passive 3637 * mode. 3638 */ 3639 public void setPassiveNatWorkaround(boolean enabled) { 3640 this.__passiveNatWorkaround = enabled; 3641 } 3642 3643 private OutputStream getBufferedOutputStream(OutputStream outputStream) { 3644 if (__bufferSize > 0) { 3645 return new BufferedOutputStream(outputStream, __bufferSize); 3646 } 3647 return new BufferedOutputStream(outputStream); 3648 } 3649 3650 private InputStream getBufferedInputStream(InputStream inputStream) { 3651 if (__bufferSize > 0) { 3652 return new BufferedInputStream(inputStream, __bufferSize); 3653 } 3654 return new BufferedInputStream(inputStream); 3655 } 3656 3657 // @since 3.0 3658 private static class CSL implements CopyStreamListener { 3659 3660 private final FTPClient parent; 3661 private final long idle; 3662 private final int currentSoTimeout; 3663 3664 private long time = System.currentTimeMillis(); 3665 private int notAcked; 3666 3667 CSL(FTPClient parent, long idleTime, int maxWait) throws SocketException { 3668 this.idle = idleTime; 3669 this.parent = parent; 3670 this.currentSoTimeout = parent.getSoTimeout(); 3671 parent.setSoTimeout(maxWait); 3672 } 3673 3674 // @Override 3675 public void bytesTransferred(CopyStreamEvent event) { 3676 bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize()); 3677 } 3678 3679 // @Override 3680 public void bytesTransferred(long totalBytesTransferred, 3681 int bytesTransferred, long streamSize) { 3682 long now = System.currentTimeMillis(); 3683 if (now - time > idle) { 3684 try { 3685 parent.__noop(); 3686 } catch (SocketTimeoutException e) { 3687 notAcked++; 3688 } catch (IOException e) { 3689 } 3690 time = now; 3691 } 3692 } 3693 3694 void cleanUp() throws IOException { 3695 try { 3696 while(notAcked-- > 0) { 3697 parent.__getReplyNoReport(); 3698 } 3699 } finally { 3700 parent.setSoTimeout(currentSoTimeout); 3701 } 3702 } 3703 3704 } 3705 3706 /** 3707 * Merge two copystream listeners, either or both of which may be null. 3708 * 3709 * @param local the listener used by this class, may be null 3710 * @return a merged listener or a single listener or null 3711 * @since 3.0 3712 */ 3713 private CopyStreamListener __mergeListeners(CopyStreamListener local) { 3714 if (local == null) { 3715 return __copyStreamListener; 3716 } 3717 if (__copyStreamListener == null) { 3718 return local; 3719 } 3720 // Both are non-null 3721 CopyStreamAdapter merged = new CopyStreamAdapter(); 3722 merged.addCopyStreamListener(local); 3723 merged.addCopyStreamListener(__copyStreamListener); 3724 return merged; 3725 } 3726 3727 /** 3728 * Enables or disables automatic server encoding detection (only UTF-8 supported). 3729 * <p> 3730 * Does not affect existing connections; must be invoked before a connection is established. 3731 * 3732 * @param autodetect If true, automatic server encoding detection will be enabled. 3733 */ 3734 public void setAutodetectUTF8(boolean autodetect) 3735 { 3736 __autodetectEncoding = autodetect; 3737 } 3738 3739 /** 3740 * Tells if automatic server encoding detection is enabled or disabled. 3741 * @return true, if automatic server encoding detection is enabled. 3742 */ 3743 public boolean getAutodetectUTF8() 3744 { 3745 return __autodetectEncoding; 3746 } 3747 3748 // DEPRECATED METHODS - for API compatibility only - DO NOT USE 3749 3750 /** 3751 * @deprecated use {@link #getSystemType()} instead 3752 */ 3753 @Deprecated 3754 public String getSystemName() throws IOException 3755 { 3756 if (__systemName == null && FTPReply.isPositiveCompletion(syst())) { 3757 __systemName = _replyLines.get(_replyLines.size() - 1).substring(4); 3758 } 3759 return __systemName; 3760 } 3761 } 3762 3763 /* Emacs configuration 3764 * Local variables: ** 3765 * mode: java ** 3766 * c-basic-offset: 4 ** 3767 * indent-tabs-mode: nil ** 3768 * End: ** 3769 */ 3770 /* kate: indent-width 4; replace-tabs on; */