1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.waarp.ftp.client;
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
27 import org.apache.commons.net.PrintCommandListener;
28 import org.apache.commons.net.ftp.FTP;
29 import org.apache.commons.net.ftp.FTPClient;
30 import org.apache.commons.net.ftp.FTPHTTPClient;
31 import org.apache.commons.net.ftp.FTPClientConfig;
32 import org.apache.commons.net.ftp.FTPConnectionClosedException;
33 import org.apache.commons.net.ftp.FTPFile;
34 import org.apache.commons.net.ftp.FTPReply;
35 import org.apache.commons.net.ftp.FTPSClient;
36 import org.apache.commons.net.io.CopyStreamEvent;
37 import org.apache.commons.net.io.CopyStreamListener;
38 import org.apache.commons.net.util.TrustManagerUtils;
39
40
41
42
43
44
45
46
47
48 public final class FTPClientExample
49 {
50
51 public static final String USAGE =
52 "Usage: ftp [options] <hostname> <username> <password> <account> [<remote file> [<local file>]]\n"
53 +
54 "\nDefault behavior is to download a file and use ASCII transfer mode.\n"
55 +
56 "\t-a - use local active mode (default is local passive)\n"
57 +
58 "\t-b - use binary transfer mode\n"
59 +
60 "\t-c cmd - issue arbitrary command (remote is used as a parameter if provided) \n"
61 +
62 "\t-d - list directory details using MLSD (remote is used as the pathname if provided)\n"
63 +
64 "\t-e - use EPSV with IPv4 (default false)\n"
65 +
66 "\t-f - issue FEAT command (remote and local files are ignored)\n"
67 +
68 "\t-h - list hidden files (applies to -l and -n only)\n"
69 +
70 "\t-k secs - use keep-alive timer (setControlKeepAliveTimeout)\n"
71 +
72 "\t-l - list files using LIST (remote is used as the pathname if provided)\n"
73 +
74 "\t-L - use lenient future dates (server dates may be up to 1 day into future)\n"
75 +
76 "\t-n - list file names using NLST (remote is used as the pathname if provided)\n"
77 +
78 "\t-p true|false|protocol[,true|false] - use FTPSClient with the specified protocol and/or isImplicit setting\n"
79 +
80 "\t-s - store file on server (upload)\n"
81 +
82 "\t-t - list file details using MLST (remote is used as the pathname if provided)\n"
83 +
84 "\t-w msec - wait time for keep-alive reply (setControlKeepAliveReplyTimeout)\n"
85 +
86 "\t-T all|valid|none - use one of the built-in TrustManager implementations (none = JVM default)\n"
87 +
88 "\t-PrH server[:port] - HTTP Proxy host and optional port[80] \n" +
89 "\t-PrU user - HTTP Proxy server username\n" +
90 "\t-PrP password - HTTP Proxy server password\n" +
91 "\t-# - add hash display during transfers\n";
92
93 public static final void main(String[] args)
94 {
95 boolean storeFile = false, binaryTransfer = false, error = false, listFiles = false, listNames = false, hidden = false;
96 boolean localActive = false, useEpsvWithIPv4 = false, feat = false, printHash = false;
97 boolean mlst = false, mlsd = false;
98 boolean lenient = false;
99 long keepAliveTimeout = -1;
100 int controlKeepAliveReplyTimeout = -1;
101 int minParams = 5;
102 String protocol = null;
103 String doCommand = null;
104 String trustmgr = null;
105 String proxyHost = null;
106 int proxyPort = 80;
107 String proxyUser = null;
108 String proxyPassword = null;
109
110 int base = 0;
111 for (base = 0; base < args.length; base++)
112 {
113 if (args[base].equals("-s")) {
114 storeFile = true;
115 }
116 else if (args[base].equals("-a")) {
117 localActive = true;
118 }
119 else if (args[base].equals("-b")) {
120 binaryTransfer = true;
121 }
122 else if (args[base].equals("-c")) {
123 doCommand = args[++base];
124 minParams = 3;
125 }
126 else if (args[base].equals("-d")) {
127 mlsd = true;
128 minParams = 3;
129 }
130 else if (args[base].equals("-e")) {
131 useEpsvWithIPv4 = true;
132 }
133 else if (args[base].equals("-f")) {
134 feat = true;
135 minParams = 3;
136 }
137 else if (args[base].equals("-h")) {
138 hidden = true;
139 }
140 else if (args[base].equals("-k")) {
141 keepAliveTimeout = Long.parseLong(args[++base]);
142 }
143 else if (args[base].equals("-l")) {
144 listFiles = true;
145 minParams = 3;
146 }
147 else if (args[base].equals("-L")) {
148 lenient = true;
149 }
150 else if (args[base].equals("-n")) {
151 listNames = true;
152 minParams = 3;
153 }
154 else if (args[base].equals("-p")) {
155 protocol = args[++base];
156 }
157 else if (args[base].equals("-t")) {
158 mlst = true;
159 minParams = 3;
160 }
161 else if (args[base].equals("-w")) {
162 controlKeepAliveReplyTimeout = Integer.parseInt(args[++base]);
163 }
164 else if (args[base].equals("-T")) {
165 trustmgr = args[++base];
166 }
167 else if (args[base].equals("-PrH")) {
168 proxyHost = args[++base];
169 String parts[] = proxyHost.split(":");
170 if (parts.length == 2) {
171 proxyHost = parts[0];
172 proxyPort = Integer.parseInt(parts[1]);
173 }
174 }
175 else if (args[base].equals("-PrU")) {
176 proxyUser = args[++base];
177 }
178 else if (args[base].equals("-PrP")) {
179 proxyPassword = args[++base];
180 }
181 else if (args[base].equals("-#")) {
182 printHash = true;
183 }
184 else {
185 break;
186 }
187 }
188
189 int remain = args.length - base;
190 if (remain < minParams)
191 {
192 System.err.println(USAGE);
193 System.exit(1);
194 }
195
196 String server = args[base++];
197 int port = 0;
198 String parts[] = server.split(":");
199 if (parts.length == 2) {
200 server = parts[0];
201 port = Integer.parseInt(parts[1]);
202 }
203 String username = args[base++];
204 String password = args[base++];
205 String account = args[base++];
206
207 String remote = null;
208 if (args.length - base > 0) {
209 remote = args[base++];
210 }
211
212 String local = null;
213 if (args.length - base > 0) {
214 local = args[base++];
215 }
216
217 boolean mustCallProtP = false;
218 final FTPClient ftp;
219 if (protocol == null) {
220 if (proxyHost != null) {
221 System.out.println("Using HTTP proxy server: " + proxyHost);
222 ftp = new FTPHTTPClient(proxyHost, proxyPort, proxyUser, proxyPassword);
223 }
224 else {
225 ftp = new FTPClient();
226 }
227 } else {
228 FTPSClient ftps;
229 if (protocol.equals("true")) {
230 System.out.println("Implicit FTPS");
231 ftps = new FTPSClient(true);
232 } else if (protocol.equals("false")) {
233 System.out.println("Explicit FTPS");
234 ftps = new FTPSClient(false);
235 mustCallProtP = true;
236 } else {
237 String prot[] = protocol.split(",");
238 System.out.println("Protocl FTPS: " + protocol);
239
240 if (prot.length == 1) {
241 ftps = new FTPSClient(protocol);
242 } else {
243 mustCallProtP = !Boolean.parseBoolean(prot[1]);
244 ftps = new FTPSClient(prot[0], !mustCallProtP);
245 }
246 }
247 ftp = ftps;
248 if ("all".equals(trustmgr)) {
249 System.out.println("Accept all");
250 ftps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
251 } else if ("valid".equals(trustmgr)) {
252 System.out.println("Accept after valid");
253 ftps.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager());
254 } else if ("none".equals(trustmgr)) {
255 System.out.println("Accept none");
256 ftps.setTrustManager(null);
257 }
258 }
259
260 if (printHash) {
261 ftp.setCopyStreamListener(createListener());
262 }
263 if (keepAliveTimeout >= 0) {
264 ftp.setControlKeepAliveTimeout(keepAliveTimeout);
265 }
266 if (controlKeepAliveReplyTimeout >= 0) {
267 ftp.setControlKeepAliveReplyTimeout(controlKeepAliveReplyTimeout);
268 }
269 ftp.setListHiddenFiles(hidden);
270
271
272 ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
273
274 try
275 {
276 int reply;
277 if (port > 0) {
278 ftp.connect(server, port);
279 } else {
280 ftp.connect(server);
281 }
282 System.out.println("Connected to " + server + " on "
283 + (port > 0 ? port : ftp.getDefaultPort()));
284
285
286
287 reply = ftp.getReplyCode();
288
289 if (!FTPReply.isPositiveCompletion(reply))
290 {
291 ftp.disconnect();
292 System.err.println("FTP server refused connection.");
293 System.exit(1);
294 }
295 } catch (IOException e)
296 {
297 if (ftp.getDataConnectionMode() == FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE)
298 {
299 try
300 {
301 ftp.disconnect();
302 } catch (IOException f)
303 {
304
305 }
306 }
307 System.err.println("Could not connect to server.");
308 e.printStackTrace();
309 System.exit(1);
310 }
311
312 __main: try
313 {
314 if (account == null) {
315 if (!ftp.login(username, password))
316 {
317 ftp.logout();
318 error = true;
319 break __main;
320 }
321 } else {
322 if (!ftp.login(username, password, account))
323 {
324 ftp.logout();
325 error = true;
326 break __main;
327 }
328 }
329 System.out.println("Remote system is " + ftp.getSystemType());
330
331 if (binaryTransfer) {
332 ftp.setFileType(FTP.BINARY_FILE_TYPE);
333 }
334
335
336
337 if (localActive) {
338 ftp.enterLocalActiveMode();
339 } else {
340 ftp.enterLocalPassiveMode();
341 }
342
343 ftp.setUseEPSVwithIPv4(useEpsvWithIPv4);
344
345 if (mustCallProtP) {
346 ((FTPSClient) ftp).execPBSZ(0);
347 ((FTPSClient) ftp).execPROT("P");
348 }
349
350 if (storeFile)
351 {
352 InputStream input;
353
354 input = new FileInputStream(local);
355
356 ftp.storeFile(remote, input);
357
358 input.close();
359 }
360 else if (listFiles)
361 {
362 if (lenient) {
363 FTPClientConfig config = new FTPClientConfig();
364 config.setLenientFutureDates(true);
365 ftp.configure(config);
366 }
367
368 for (FTPFile f : ftp.listFiles(remote)) {
369 System.out.println(f.getRawListing());
370 System.out.println(f.toFormattedString());
371 }
372 }
373 else if (mlsd)
374 {
375 for (FTPFile f : ftp.mlistDir(remote)) {
376 System.out.println(f.getRawListing());
377 System.out.println(f.toFormattedString());
378 }
379 }
380 else if (mlst)
381 {
382 FTPFile f = ftp.mlistFile(remote);
383 if (f != null) {
384 System.out.println(f.toFormattedString());
385 }
386 }
387 else if (listNames)
388 {
389 for (String s : ftp.listNames(remote)) {
390 System.out.println(s);
391 }
392 }
393 else if (feat)
394 {
395
396 if (remote != null) {
397 if (ftp.hasFeature(remote)) {
398 System.out.println("Has feature: " + remote);
399 } else {
400 if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
401 System.out.println("FEAT " + remote + " was not detected");
402 } else {
403 System.out.println("Command failed: " + ftp.getReplyString());
404 }
405 }
406
407
408 String[] features = ftp.featureValues(remote);
409 if (features != null) {
410 for (String f : features) {
411 System.out.println("FEAT " + remote + "=" + f + ".");
412 }
413 } else {
414 if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
415 System.out.println("FEAT " + remote + " is not present");
416 } else {
417 System.out.println("Command failed: " + ftp.getReplyString());
418 }
419 }
420 } else {
421 if (ftp.features()) {
422
423 } else {
424 System.out.println("Failed: " + ftp.getReplyString());
425 }
426 }
427 }
428 else if (doCommand != null)
429 {
430 if (ftp.doCommand(doCommand, remote)) {
431
432
433
434
435 } else {
436 System.out.println("Failed: " + ftp.getReplyString());
437 }
438 }
439 else
440 {
441 OutputStream output;
442
443 output = new FileOutputStream(local);
444
445 ftp.retrieveFile(remote, output);
446
447 output.close();
448 }
449
450 ftp.noop();
451
452 ftp.logout();
453 } catch (FTPConnectionClosedException e)
454 {
455 error = true;
456 System.err.println("Server closed connection.");
457 e.printStackTrace();
458 } catch (IOException e)
459 {
460 error = true;
461 e.printStackTrace();
462 } finally
463 {
464 if (ftp.getDataConnectionMode() == FTPClient.ACTIVE_LOCAL_DATA_CONNECTION_MODE)
465 {
466 try
467 {
468 ftp.disconnect();
469 } catch (IOException f)
470 {
471
472 }
473 }
474 }
475
476 System.exit(error ? 1 : 0);
477 }
478
479 private static CopyStreamListener createListener() {
480 return new CopyStreamListener() {
481 private long megsTotal = 0;
482
483 public void bytesTransferred(CopyStreamEvent event) {
484 bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(),
485 event.getStreamSize());
486 }
487
488 public void bytesTransferred(long totalBytesTransferred,
489 int bytesTransferred, long streamSize) {
490 long megs = totalBytesTransferred / 1000000;
491 for (long l = megsTotal; l < megs; l++) {
492 System.err.print("#");
493 }
494 megsTotal = megs;
495 }
496 };
497 }
498 }