1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.examples.ftp;
19
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.io.PrintWriter;
26 import java.net.InetAddress;
27 import java.net.UnknownHostException;
28 import java.util.Arrays;
29
30 import org.apache.commons.net.PrintCommandListener;
31 import org.apache.commons.net.ftp.FTP;
32 import org.apache.commons.net.ftp.FTPClient;
33 import org.apache.commons.net.ftp.FTPClientConfig;
34 import org.apache.commons.net.ftp.FTPConnectionClosedException;
35 import org.apache.commons.net.ftp.FTPFile;
36 import org.apache.commons.net.ftp.FTPHTTPClient;
37 import org.apache.commons.net.ftp.FTPReply;
38 import org.apache.commons.net.ftp.FTPSClient;
39 import org.apache.commons.net.io.CopyStreamEvent;
40 import org.apache.commons.net.io.CopyStreamListener;
41 import org.apache.commons.net.util.TrustManagerUtils;
42
43
44
45
46
47
48
49
50
51 public final class FTPClientExample
52 {
53
54 public static final String USAGE =
55 "Expected Parameters: [options] <hostname> <username> <password> [<remote file> [<local file>]]\n" +
56 "\nDefault behavior is to download a file and use ASCII transfer mode.\n" +
57 "\t-a - use local active mode (default is local passive)\n" +
58 "\t-A - anonymous login (omit username and password parameters)\n" +
59 "\t-b - use binary transfer mode\n" +
60 "\t-c cmd - issue arbitrary command (remote is used as a parameter if provided) \n" +
61 "\t-d - list directory details using MLSD (remote is used as the pathname if provided)\n" +
62 "\t-e - use EPSV with IPv4 (default false)\n" +
63 "\t-E - encoding to use for control channel\n" +
64 "\t-f - issue FEAT command (remote and local files are ignored)\n" +
65 "\t-h - list hidden files (applies to -l and -n only)\n" +
66 "\t-i - issue SIZE command for a file\n" +
67 "\t-k secs - use keep-alive timer (setControlKeepAliveTimeout)\n" +
68 "\t-l - list files using LIST (remote is used as the pathname if provided)\n" +
69 "\t Files are listed twice: first in raw mode, then as the formatted parsed data.\n" +
70 "\t N.B. if the wrong server-type is used, output may be lost. Use -U or -S as necessary.\n" +
71 "\t-L - use lenient future dates (server dates may be up to 1 day into future)\n" +
72 "\t-m - list file details using MDTM (remote is used as the pathname if provided)\n" +
73 "\t-n - list file names using NLST (remote is used as the pathname if provided)\n" +
74 "\t-p true|false|protocol[,true|false] - use FTPSClient with the specified protocol and/or isImplicit setting\n" +
75 "\t-s - store file on server (upload)\n" +
76 "\t-S - systemType set server system type (e.g. UNIX VMS WINDOWS)\n" +
77 "\t-t - list file details using MLST (remote is used as the pathname if provided)\n" +
78 "\t-U - save unparseable responses\n" +
79 "\t-w msec - wait time for keep-alive reply (setControlKeepAliveReplyTimeout)\n" +
80 "\t-T all|valid|none - use one of the built-in TrustManager implementations (none = JVM default)\n" +
81 "\t-y format - set default date format string\n" +
82 "\t-Y format - set recent date format string\n" +
83 "\t-Z timezone - set the server time zone for parsing LIST responses\n" +
84 "\t-z timezone - set the time zone for displaying MDTM, LIST, MLSD, MLST responses\n" +
85 "\t-PrH server[:port] - HTTP Proxy host and optional port[80] \n" +
86 "\t-PrU user - HTTP Proxy server username\n" +
87 "\t-PrP password - HTTP Proxy server password\n" +
88 "\t-# - add hash display during transfers\n";
89
90 public static void main(final String[] args) throws UnknownHostException
91 {
92 boolean storeFile = false, binaryTransfer = false, error = false, listFiles = false, listNames = false, hidden = false;
93 boolean localActive = false, useEpsvWithIPv4 = false, feat = false, printHash = false;
94 boolean mlst = false, mlsd = false, mdtm = false, saveUnparseable = false;
95 boolean size = false;
96 boolean lenient = false;
97 long keepAliveTimeoutSeconds = -1;
98 int controlKeepAliveReplyTimeoutMillis = -1;
99 int minParams = 5;
100 String protocol = null;
101 String doCommand = null;
102 String trustmgr = null;
103 String proxyHost = null;
104 int proxyPort = 80;
105 String proxyUser = null;
106 String proxyPassword = null;
107 String username = null;
108 String password = null;
109 String encoding = null;
110 String serverTimeZoneId = null;
111 String displayTimeZoneId = null;
112 String serverType = null;
113 String defaultDateFormat = null;
114 String recentDateFormat = null;
115
116
117 int base = 0;
118 for (base = 0; base < args.length; base++)
119 {
120 if (args[base].equals("-s")) {
121 storeFile = true;
122 }
123 else if (args[base].equals("-a")) {
124 localActive = true;
125 }
126 else if (args[base].equals("-A")) {
127 username = "anonymous";
128 password = System.getProperty("user.name")+"@"+InetAddress.getLocalHost().getHostName();
129 }
130 else if (args[base].equals("-b")) {
131 binaryTransfer = true;
132 }
133 else if (args[base].equals("-c")) {
134 doCommand = args[++base];
135 minParams = 3;
136 }
137 else if (args[base].equals("-d")) {
138 mlsd = true;
139 minParams = 3;
140 }
141 else if (args[base].equals("-e")) {
142 useEpsvWithIPv4 = true;
143 }
144 else if (args[base].equals("-E")) {
145 encoding = args[++base];
146 }
147 else if (args[base].equals("-f")) {
148 feat = true;
149 minParams = 3;
150 }
151 else if (args[base].equals("-h")) {
152 hidden = true;
153 }
154 else if (args[base].equals("-i")) {
155 size = true;
156 minParams = 3;
157 }
158 else if (args[base].equals("-k")) {
159 keepAliveTimeoutSeconds = Long.parseLong(args[++base]);
160 }
161 else if (args[base].equals("-l")) {
162 listFiles = true;
163 minParams = 3;
164 }
165 else if (args[base].equals("-m")) {
166 mdtm = true;
167 minParams = 3;
168 }
169 else if (args[base].equals("-L")) {
170 lenient = true;
171 }
172 else if (args[base].equals("-n")) {
173 listNames = true;
174 minParams = 3;
175 }
176 else if (args[base].equals("-p")) {
177 protocol = args[++base];
178 }
179 else if (args[base].equals("-S")) {
180 serverType = args[++base];
181 }
182 else if (args[base].equals("-t")) {
183 mlst = true;
184 minParams = 3;
185 }
186 else if (args[base].equals("-U")) {
187 saveUnparseable = true;
188 }
189 else if (args[base].equals("-w")) {
190 controlKeepAliveReplyTimeoutMillis = Integer.parseInt(args[++base]);
191 }
192 else if (args[base].equals("-T")) {
193 trustmgr = args[++base];
194 }
195 else if (args[base].equals("-y")) {
196 defaultDateFormat = args[++base];
197 }
198 else if (args[base].equals("-Y")) {
199 recentDateFormat = args[++base];
200 }
201 else if (args[base].equals("-Z")) {
202 serverTimeZoneId = args[++base];
203 }
204 else if (args[base].equals("-z")) {
205 displayTimeZoneId = args[++base];
206 }
207 else if (args[base].equals("-PrH")) {
208 proxyHost = args[++base];
209 final String parts[] = proxyHost.split(":");
210 if (parts.length == 2){
211 proxyHost=parts[0];
212 proxyPort=Integer.parseInt(parts[1]);
213 }
214 }
215 else if (args[base].equals("-PrU")) {
216 proxyUser = args[++base];
217 }
218 else if (args[base].equals("-PrP")) {
219 proxyPassword = args[++base];
220 }
221 else if (args[base].equals("-#")) {
222 printHash = true;
223 }
224 else {
225 break;
226 }
227 }
228
229 final int remain = args.length - base;
230 if (username != null) {
231 minParams -= 2;
232 }
233 if (remain < minParams)
234 {
235 if (args.length > 0) {
236 System.err.println("Actual Parameters: " + Arrays.toString(args));
237 }
238 System.err.println(USAGE);
239 System.exit(1);
240 }
241
242 String server = args[base++];
243 int port = 0;
244 final String parts[] = server.split(":");
245 if (parts.length == 2){
246 server=parts[0];
247 port=Integer.parseInt(parts[1]);
248 }
249 if (username == null) {
250 username = args[base++];
251 password = args[base++];
252 }
253
254 String remote = null;
255 if (args.length - base > 0) {
256 remote = args[base++];
257 }
258
259 String local = null;
260 if (args.length - base > 0) {
261 local = args[base++];
262 }
263
264 final FTPClient ftp;
265 if (protocol == null ) {
266 if(proxyHost !=null) {
267 System.out.println("Using HTTP proxy server: " + proxyHost);
268 ftp = new FTPHTTPClient(proxyHost, proxyPort, proxyUser, proxyPassword);
269 }
270 else {
271 ftp = new FTPClient();
272 }
273 } else {
274 final FTPSClient ftps;
275 if (protocol.equals("true")) {
276 ftps = new FTPSClient(true);
277 } else if (protocol.equals("false")) {
278 ftps = new FTPSClient(false);
279 } else {
280 final String prot[] = protocol.split(",");
281 if (prot.length == 1) {
282 ftps = new FTPSClient(protocol);
283 } else {
284 ftps = new FTPSClient(prot[0], Boolean.parseBoolean(prot[1]));
285 }
286 }
287 ftp = ftps;
288 if ("all".equals(trustmgr)) {
289 ftps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
290 } else if ("valid".equals(trustmgr)) {
291 ftps.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager());
292 } else if ("none".equals(trustmgr)) {
293 ftps.setTrustManager(null);
294 }
295 }
296
297 if (printHash) {
298 ftp.setCopyStreamListener(createListener());
299 }
300 if (keepAliveTimeoutSeconds >= 0) {
301 ftp.setControlKeepAliveTimeout(keepAliveTimeoutSeconds);
302 }
303 if (controlKeepAliveReplyTimeoutMillis >= 0) {
304 ftp.setControlKeepAliveReplyTimeout(controlKeepAliveReplyTimeoutMillis);
305 }
306 if (encoding != null) {
307 ftp.setControlEncoding(encoding);
308 }
309 ftp.setListHiddenFiles(hidden);
310
311
312 ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
313
314 final FTPClientConfig config;
315 if (serverType != null) {
316 config = new FTPClientConfig(serverType);
317 } else {
318 config = new FTPClientConfig();
319 }
320 config.setUnparseableEntries(saveUnparseable);
321 if (defaultDateFormat != null) {
322 config.setDefaultDateFormatStr(defaultDateFormat);
323 }
324 if (recentDateFormat != null) {
325 config.setRecentDateFormatStr(recentDateFormat);
326 }
327 ftp.configure(config);
328
329 try
330 {
331 final int reply;
332 if (port > 0) {
333 ftp.connect(server, port);
334 } else {
335 ftp.connect(server);
336 }
337 System.out.println("Connected to " + server + " on " + (port>0 ? port : ftp.getDefaultPort()));
338
339
340
341 reply = ftp.getReplyCode();
342
343 if (!FTPReply.isPositiveCompletion(reply))
344 {
345 ftp.disconnect();
346 System.err.println("FTP server refused connection.");
347 System.exit(1);
348 }
349 }
350 catch (final IOException e)
351 {
352 if (ftp.isConnected())
353 {
354 try
355 {
356 ftp.disconnect();
357 }
358 catch (final IOException f)
359 {
360
361 }
362 }
363 System.err.println("Could not connect to server.");
364 e.printStackTrace();
365 System.exit(1);
366 }
367
368 __main:
369 try
370 {
371 if (!ftp.login(username, password))
372 {
373 ftp.logout();
374 error = true;
375 break __main;
376 }
377
378 System.out.println("Remote system is " + ftp.getSystemType());
379
380 if (binaryTransfer) {
381 ftp.setFileType(FTP.BINARY_FILE_TYPE);
382 } else {
383
384
385 ftp.setFileType(FTP.ASCII_FILE_TYPE);
386 }
387
388
389
390 if (localActive) {
391 ftp.enterLocalActiveMode();
392 } else {
393 ftp.enterLocalPassiveMode();
394 }
395
396 ftp.setUseEPSVwithIPv4(useEpsvWithIPv4);
397
398 if (storeFile)
399 {
400 try (final InputStream input = new FileInputStream(local)) {
401 ftp.storeFile(remote, input);
402 }
403
404 if (keepAliveTimeoutSeconds > 0) {
405 showCslStats(ftp);
406 }
407 }
408
409 else if (listFiles || mlsd || mdtm || mlst || listNames || size)
410 {
411 if (mlsd) {
412 for (final FTPFile f : ftp.mlistDir(remote)) {
413 System.out.println(f.getRawListing());
414 System.out.println(f.toFormattedString(displayTimeZoneId));
415 }
416 }
417 if (mdtm) {
418 final FTPFile f = ftp.mdtmFile(remote);
419 if (f != null) {
420 System.out.println(f.getRawListing());
421 System.out.println(f.toFormattedString(displayTimeZoneId));
422 } else {
423 System.out.println("File not found");
424 }
425 }
426 if (mlst) {
427 final FTPFile f = ftp.mlistFile(remote);
428 if (f != null){
429 System.out.println(f.toFormattedString(displayTimeZoneId));
430 }
431 }
432 if (listNames) {
433 for (final String s : ftp.listNames(remote)) {
434 System.out.println(s);
435 }
436 }
437 if (size) {
438 System.out.println("Size="+ftp.getSize(remote));
439 }
440
441 if (listFiles) {
442 if (lenient || serverTimeZoneId != null) {
443 config.setLenientFutureDates(lenient);
444 if (serverTimeZoneId != null) {
445 config.setServerTimeZoneId(serverTimeZoneId);
446 }
447 ftp.configure(config );
448 }
449
450 for (final FTPFile f : ftp.listFiles(remote)) {
451 System.out.println(f.getRawListing());
452 System.out.println(f.toFormattedString(displayTimeZoneId));
453 }
454 }
455 }
456 else if (feat)
457 {
458
459 if (remote != null) {
460 if (ftp.hasFeature(remote)) {
461 System.out.println("Has feature: "+remote);
462 } else {
463 if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
464 System.out.println("FEAT "+remote+" was not detected");
465 } else {
466 System.out.println("Command failed: "+ftp.getReplyString());
467 }
468 }
469
470
471 final String []features = ftp.featureValues(remote);
472 if (features != null) {
473 for(final String f : features) {
474 System.out.println("FEAT "+remote+"="+f+".");
475 }
476 } else {
477 if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
478 System.out.println("FEAT "+remote+" is not present");
479 } else {
480 System.out.println("Command failed: "+ftp.getReplyString());
481 }
482 }
483 } else {
484 if (ftp.features()) {
485
486 } else {
487 System.out.println("Failed: "+ftp.getReplyString());
488 }
489 }
490 }
491 else if (doCommand != null)
492 {
493 if (ftp.doCommand(doCommand, remote)) {
494
495
496
497
498 } else {
499 System.out.println("Failed: "+ftp.getReplyString());
500 }
501 }
502 else
503 {
504 try (final OutputStream output = new FileOutputStream(local)) {
505 ftp.retrieveFile(remote, output);
506 }
507
508 if (keepAliveTimeoutSeconds > 0) {
509 showCslStats(ftp);
510 }
511 }
512
513 ftp.noop();
514
515 ftp.logout();
516 }
517 catch (final FTPConnectionClosedException e)
518 {
519 error = true;
520 System.err.println("Server closed connection.");
521 e.printStackTrace();
522 }
523 catch (final IOException e)
524 {
525 error = true;
526 e.printStackTrace();
527 }
528 finally
529 {
530 if (ftp.isConnected())
531 {
532 try
533 {
534 ftp.disconnect();
535 }
536 catch (final IOException f)
537 {
538
539 }
540 }
541 }
542
543 System.exit(error ? 1 : 0);
544 }
545
546 private static void showCslStats(final FTPClient ftp) {
547 @SuppressWarnings("deprecation")
548 final
549 int []stats = ftp.getCslDebug();
550 System.out.println("CslDebug="+Arrays.toString(stats));
551
552 }
553
554 private static CopyStreamListener createListener(){
555 return new CopyStreamListener(){
556 private long megsTotal;
557
558 @Override
559 public void bytesTransferred(final CopyStreamEvent event) {
560 bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
561 }
562
563 @Override
564 public void bytesTransferred(final long totalBytesTransferred,
565 final int bytesTransferred, final long streamSize) {
566 final long megs = totalBytesTransferred / 1000000;
567 for (long l = megsTotal; l < megs; l++) {
568 System.err.print("#");
569 }
570 megsTotal = megs;
571 }
572 };
573 }
574 }
575