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