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