View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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   * This is an example program demonstrating how to use the FTPClient class.
44   * This program connects to an FTP server and retrieves the specified
45   * file.  If the -s flag is used, it stores the local file at the FTP server.
46   * Just so you can see what's happening, all reply strings are printed.
47   * If the -b flag is used, a binary transfer is assumed (default is ASCII).
48   * See below for further options.
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; // listings require 3 params
88          String protocol = null; // SSL protocol
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) // server, user, pass, remote, local [protocol]
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) { // Just protocol
231                     ftps = new FTPSClient(protocol);
232                 } else { // protocol,true|false
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         // suppress login details
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             // After connection attempt, you should check the reply code to verify
271             // success.
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                     // do nothing
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                 // in theory this should not be necessary as servers should default to ASCII
315                 // but they don't all do so - see NET-500
316                 ftp.setFileType(FTP.ASCII_FILE_TYPE);
317             }
318 
319             // Use passive mode as default because most of us are
320             // behind firewalls these days.
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                 // boolean feature check
375                 if (remote != null) { // See if the command is present
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                     // Strings feature check
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 //                        Command listener has already printed the output
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 //                  Command listener has already printed the output
411 //                    for(String s : ftp.getReplyStrings()) {
412 //                        System.out.println(s);
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(); // check that control connection is working OK
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                     // do nothing
455                 }
456             }
457         }
458 
459         System.exit(error ? 1 : 0);
460     } // end main
461 
462     private static CopyStreamListener createListener(){
463         return new CopyStreamListener(){
464             private long megsTotal = 0;
465 //            @Override
466             public void bytesTransferred(CopyStreamEvent event) {
467                 bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
468             }
469 
470 //            @Override
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