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