View Javadoc
1   /**
2    * This file is part of Waarp Project.
3    * 
4    * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
5    * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
6    * 
7    * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
8    * the GNU General Public License as published by the Free Software Foundation, either version 3 of
9    * the License, or (at your option) any later version.
10   * 
11   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
12   * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13   * Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License along with Waarp . If not, see
16   * <http://www.gnu.org/licenses/>.
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   * This is the FTPClient example from Apache Commons-Net<br>
42   * 
43   * This is an example program demonstrating how to use the FTPClient class. This program connects to
44   * an FTP server and retrieves the specified file. If the -s flag is used, it stores the local file
45   * at the FTP server. Just so you can see what's happening, all reply strings are printed. If the -b
46   * flag is used, a binary transfer is assumed (default is ASCII). See below for further options.
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; // listings require 3 params
102         String protocol = null; // SSL protocol
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) // server, user, pass, remote, local [protocol]
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) { // Just protocol
241                     ftps = new FTPSClient(protocol);
242                 } else { // protocol,true|false
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         // suppress login details
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             // After connection attempt, you should check the reply code to verify
286             // success.
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                     // do nothing
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             // Use passive mode as default because most of us are
336             // behind firewalls these days.
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                 // boolean feature check
396                 if (remote != null) { // See if the command is present
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                     // Strings feature check
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                         // Command listener has already printed the output
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                     // Command listener has already printed the output
432                     // for(String s : ftp.getReplyStrings()) {
433                     // System.out.println(s);
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(); // check that control connection is working OK
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                     // do nothing
472                 }
473             }
474         }
475 
476         System.exit(error ? 1 : 0);
477     } // end main
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 }