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