| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.net.examples.ftp; |
| |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.Arrays; |
| |
| import org.apache.commons.net.PrintCommandListener; |
| import org.apache.commons.net.ftp.FTP; |
| import org.apache.commons.net.ftp.FTPClient; |
| import org.apache.commons.net.ftp.FTPHTTPClient; |
| import org.apache.commons.net.ftp.FTPClientConfig; |
| import org.apache.commons.net.ftp.FTPConnectionClosedException; |
| import org.apache.commons.net.ftp.FTPFile; |
| import org.apache.commons.net.ftp.FTPReply; |
| import org.apache.commons.net.ftp.FTPSClient; |
| import org.apache.commons.net.io.CopyStreamEvent; |
| import org.apache.commons.net.io.CopyStreamListener; |
| import org.apache.commons.net.util.TrustManagerUtils; |
| |
| /** |
| * This is an example program demonstrating how to use the FTPClient class. |
| * This program connects to an FTP server and retrieves the specified |
| * file. If the -s flag is used, it stores the local file at the FTP server. |
| * Just so you can see what's happening, all reply strings are printed. |
| * If the -b flag is used, a binary transfer is assumed (default is ASCII). |
| * See below for further options. |
| */ |
| public final class FTPClientExample |
| { |
| |
| public static final String USAGE = |
| "Expected Parameters: [options] <hostname> <username> <password> [<remote file> [<local file>]]\n" + |
| "\nDefault behavior is to download a file and use ASCII transfer mode.\n" + |
| "\t-a - use local active mode (default is local passive)\n" + |
| "\t-A - anonymous login (omit username and password parameters)\n" + |
| "\t-b - use binary transfer mode\n" + |
| "\t-c cmd - issue arbitrary command (remote is used as a parameter if provided) \n" + |
| "\t-d - list directory details using MLSD (remote is used as the pathname if provided)\n" + |
| "\t-e - use EPSV with IPv4 (default false)\n" + |
| "\t-E - encoding to use for control channel\n" + |
| "\t-f - issue FEAT command (remote and local files are ignored)\n" + |
| "\t-h - list hidden files (applies to -l and -n only)\n" + |
| "\t-i - issue SIZE command for a file\n" + |
| "\t-k secs - use keep-alive timer (setControlKeepAliveTimeout)\n" + |
| "\t-l - list files using LIST (remote is used as the pathname if provided)\n" + |
| "\t Files are listed twice: first in raw mode, then as the formatted parsed data.\n" + |
| "\t N.B. if the wrong server-type is used, output may be lost. Use -U or -S as necessary.\n" + |
| "\t-L - use lenient future dates (server dates may be up to 1 day into future)\n" + |
| "\t-m - list file details using MDTM (remote is used as the pathname if provided)\n" + |
| "\t-n - list file names using NLST (remote is used as the pathname if provided)\n" + |
| "\t-p true|false|protocol[,true|false] - use FTPSClient with the specified protocol and/or isImplicit setting\n" + |
| "\t-s - store file on server (upload)\n" + |
| "\t-S - systemType set server system type (e.g. UNIX VMS WINDOWS)\n" + |
| "\t-t - list file details using MLST (remote is used as the pathname if provided)\n" + |
| "\t-U - save unparseable responses\n" + |
| "\t-w msec - wait time for keep-alive reply (setControlKeepAliveReplyTimeout)\n" + |
| "\t-T all|valid|none - use one of the built-in TrustManager implementations (none = JVM default)\n" + |
| "\t-y format - set default date format string\n" + |
| "\t-Y format - set recent date format string\n" + |
| "\t-Z timezone - set the server timezone for parsing LIST responses\n" + |
| "\t-z timezone - set the timezone for displaying MDTM, LIST, MLSD, MLST responses\n" + |
| "\t-PrH server[:port] - HTTP Proxy host and optional port[80] \n" + |
| "\t-PrU user - HTTP Proxy server username\n" + |
| "\t-PrP password - HTTP Proxy server password\n" + |
| "\t-# - add hash display during transfers\n"; |
| |
| public static void main(String[] args) throws UnknownHostException |
| { |
| boolean storeFile = false, binaryTransfer = false, error = false, listFiles = false, listNames = false, hidden = false; |
| boolean localActive = false, useEpsvWithIPv4 = false, feat = false, printHash = false; |
| boolean mlst = false, mlsd = false, mdtm = false, saveUnparseable = false; |
| boolean size = false; |
| boolean lenient = false; |
| long keepAliveTimeout = -1; |
| int controlKeepAliveReplyTimeout = -1; |
| int minParams = 5; // listings require 3 params |
| String protocol = null; // SSL protocol |
| String doCommand = null; |
| String trustmgr = null; |
| String proxyHost = null; |
| int proxyPort = 80; |
| String proxyUser = null; |
| String proxyPassword = null; |
| String username = null; |
| String password = null; |
| String encoding = null; |
| String serverTimeZoneId = null; |
| String displayTimeZoneId = null; |
| String serverType = null; |
| String defaultDateFormat = null; |
| String recentDateFormat = null; |
| |
| |
| int base = 0; |
| for (base = 0; base < args.length; base++) |
| { |
| if (args[base].equals("-s")) { |
| storeFile = true; |
| } |
| else if (args[base].equals("-a")) { |
| localActive = true; |
| } |
| else if (args[base].equals("-A")) { |
| username = "anonymous"; |
| password = System.getProperty("user.name")+"@"+InetAddress.getLocalHost().getHostName(); |
| } |
| else if (args[base].equals("-b")) { |
| binaryTransfer = true; |
| } |
| else if (args[base].equals("-c")) { |
| doCommand = args[++base]; |
| minParams = 3; |
| } |
| else if (args[base].equals("-d")) { |
| mlsd = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-e")) { |
| useEpsvWithIPv4 = true; |
| } |
| else if (args[base].equals("-E")) { |
| encoding = args[++base]; |
| } |
| else if (args[base].equals("-f")) { |
| feat = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-h")) { |
| hidden = true; |
| } |
| else if (args[base].equals("-i")) { |
| size = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-k")) { |
| keepAliveTimeout = Long.parseLong(args[++base]); |
| } |
| else if (args[base].equals("-l")) { |
| listFiles = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-m")) { |
| mdtm = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-L")) { |
| lenient = true; |
| } |
| else if (args[base].equals("-n")) { |
| listNames = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-p")) { |
| protocol = args[++base]; |
| } |
| else if (args[base].equals("-S")) { |
| serverType = args[++base]; |
| } |
| else if (args[base].equals("-t")) { |
| mlst = true; |
| minParams = 3; |
| } |
| else if (args[base].equals("-U")) { |
| saveUnparseable = true; |
| } |
| else if (args[base].equals("-w")) { |
| controlKeepAliveReplyTimeout = Integer.parseInt(args[++base]); |
| } |
| else if (args[base].equals("-T")) { |
| trustmgr = args[++base]; |
| } |
| else if (args[base].equals("-y")) { |
| defaultDateFormat = args[++base]; |
| } |
| else if (args[base].equals("-Y")) { |
| recentDateFormat = args[++base]; |
| } |
| else if (args[base].equals("-Z")) { |
| serverTimeZoneId = args[++base]; |
| } |
| else if (args[base].equals("-z")) { |
| displayTimeZoneId = args[++base]; |
| } |
| else if (args[base].equals("-PrH")) { |
| proxyHost = args[++base]; |
| String parts[] = proxyHost.split(":"); |
| if (parts.length == 2){ |
| proxyHost=parts[0]; |
| proxyPort=Integer.parseInt(parts[1]); |
| } |
| } |
| else if (args[base].equals("-PrU")) { |
| proxyUser = args[++base]; |
| } |
| else if (args[base].equals("-PrP")) { |
| proxyPassword = args[++base]; |
| } |
| else if (args[base].equals("-#")) { |
| printHash = true; |
| } |
| else { |
| break; |
| } |
| } |
| |
| int remain = args.length - base; |
| if (username != null) { |
| minParams -= 2; |
| } |
| if (remain < minParams) // server, user, pass, remote, local [protocol] |
| { |
| if (args.length > 0) { |
| System.err.println("Actual Parameters: " + Arrays.toString(args)); |
| } |
| System.err.println(USAGE); |
| System.exit(1); |
| } |
| |
| String server = args[base++]; |
| int port = 0; |
| String parts[] = server.split(":"); |
| if (parts.length == 2){ |
| server=parts[0]; |
| port=Integer.parseInt(parts[1]); |
| } |
| if (username == null) { |
| username = args[base++]; |
| password = args[base++]; |
| } |
| |
| String remote = null; |
| if (args.length - base > 0) { |
| remote = args[base++]; |
| } |
| |
| String local = null; |
| if (args.length - base > 0) { |
| local = args[base++]; |
| } |
| |
| final FTPClient ftp; |
| if (protocol == null ) { |
| if(proxyHost !=null) { |
| System.out.println("Using HTTP proxy server: " + proxyHost); |
| ftp = new FTPHTTPClient(proxyHost, proxyPort, proxyUser, proxyPassword); |
| } |
| else { |
| ftp = new FTPClient(); |
| } |
| } else { |
| FTPSClient ftps; |
| if (protocol.equals("true")) { |
| ftps = new FTPSClient(true); |
| } else if (protocol.equals("false")) { |
| ftps = new FTPSClient(false); |
| } else { |
| String prot[] = protocol.split(","); |
| if (prot.length == 1) { // Just protocol |
| ftps = new FTPSClient(protocol); |
| } else { // protocol,true|false |
| ftps = new FTPSClient(prot[0], Boolean.parseBoolean(prot[1])); |
| } |
| } |
| ftp = ftps; |
| if ("all".equals(trustmgr)) { |
| ftps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); |
| } else if ("valid".equals(trustmgr)) { |
| ftps.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager()); |
| } else if ("none".equals(trustmgr)) { |
| ftps.setTrustManager(null); |
| } |
| } |
| |
| if (printHash) { |
| ftp.setCopyStreamListener(createListener()); |
| } |
| if (keepAliveTimeout >= 0) { |
| ftp.setControlKeepAliveTimeout(keepAliveTimeout); |
| } |
| if (controlKeepAliveReplyTimeout >= 0) { |
| ftp.setControlKeepAliveReplyTimeout(controlKeepAliveReplyTimeout); |
| } |
| if (encoding != null) { |
| ftp.setControlEncoding(encoding); |
| } |
| ftp.setListHiddenFiles(hidden); |
| |
| // suppress login details |
| ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true)); |
| |
| final FTPClientConfig config; |
| if (serverType != null) { |
| config = new FTPClientConfig(serverType); |
| } else { |
| config = new FTPClientConfig(); |
| } |
| config.setUnparseableEntries(saveUnparseable); |
| if (defaultDateFormat != null) { |
| config.setDefaultDateFormatStr(defaultDateFormat); |
| } |
| if (recentDateFormat != null) { |
| config.setRecentDateFormatStr(recentDateFormat); |
| } |
| ftp.configure(config); |
| |
| try |
| { |
| int reply; |
| if (port > 0) { |
| ftp.connect(server, port); |
| } else { |
| ftp.connect(server); |
| } |
| System.out.println("Connected to " + server + " on " + (port>0 ? port : ftp.getDefaultPort())); |
| |
| // After connection attempt, you should check the reply code to verify |
| // success. |
| reply = ftp.getReplyCode(); |
| |
| if (!FTPReply.isPositiveCompletion(reply)) |
| { |
| ftp.disconnect(); |
| System.err.println("FTP server refused connection."); |
| System.exit(1); |
| } |
| } |
| catch (IOException e) |
| { |
| if (ftp.isConnected()) |
| { |
| try |
| { |
| ftp.disconnect(); |
| } |
| catch (IOException f) |
| { |
| // do nothing |
| } |
| } |
| System.err.println("Could not connect to server."); |
| e.printStackTrace(); |
| System.exit(1); |
| } |
| |
| __main: |
| try |
| { |
| if (!ftp.login(username, password)) |
| { |
| ftp.logout(); |
| error = true; |
| break __main; |
| } |
| |
| System.out.println("Remote system is " + ftp.getSystemType()); |
| |
| if (binaryTransfer) { |
| ftp.setFileType(FTP.BINARY_FILE_TYPE); |
| } else { |
| // in theory this should not be necessary as servers should default to ASCII |
| // but they don't all do so - see NET-500 |
| ftp.setFileType(FTP.ASCII_FILE_TYPE); |
| } |
| |
| // Use passive mode as default because most of us are |
| // behind firewalls these days. |
| if (localActive) { |
| ftp.enterLocalActiveMode(); |
| } else { |
| ftp.enterLocalPassiveMode(); |
| } |
| |
| ftp.setUseEPSVwithIPv4(useEpsvWithIPv4); |
| |
| if (storeFile) |
| { |
| InputStream input; |
| |
| input = new FileInputStream(local); |
| |
| ftp.storeFile(remote, input); |
| |
| input.close(); |
| |
| if (keepAliveTimeout > 0) { |
| showCslStats(ftp); |
| } |
| } |
| // Allow multiple list types for single invocation |
| else if (listFiles || mlsd || mdtm || mlst || listNames || size) |
| { |
| if (mlsd) { |
| for (FTPFile f : ftp.mlistDir(remote)) { |
| System.out.println(f.getRawListing()); |
| System.out.println(f.toFormattedString(displayTimeZoneId)); |
| } |
| } |
| if (mdtm) { |
| FTPFile f = ftp.mdtmFile(remote); |
| if (f != null) { |
| System.out.println(f.getRawListing()); |
| System.out.println(f.toFormattedString(displayTimeZoneId)); |
| } else { |
| System.out.println("File not found"); |
| } |
| } |
| if (mlst) { |
| FTPFile f = ftp.mlistFile(remote); |
| if (f != null){ |
| System.out.println(f.toFormattedString(displayTimeZoneId)); |
| } |
| } |
| if (listNames) { |
| for (String s : ftp.listNames(remote)) { |
| System.out.println(s); |
| } |
| } |
| if (size) { |
| System.out.println("Size="+ftp.getSize(remote)); |
| } |
| // Do this last because it changes the client |
| if (listFiles) { |
| if (lenient || serverTimeZoneId != null) { |
| config.setLenientFutureDates(lenient); |
| if (serverTimeZoneId != null) { |
| config.setServerTimeZoneId(serverTimeZoneId); |
| } |
| ftp.configure(config ); |
| } |
| |
| for (FTPFile f : ftp.listFiles(remote)) { |
| System.out.println(f.getRawListing()); |
| System.out.println(f.toFormattedString(displayTimeZoneId)); |
| } |
| } |
| } |
| else if (feat) |
| { |
| // boolean feature check |
| if (remote != null) { // See if the command is present |
| if (ftp.hasFeature(remote)) { |
| System.out.println("Has feature: "+remote); |
| } else { |
| if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) { |
| System.out.println("FEAT "+remote+" was not detected"); |
| } else { |
| System.out.println("Command failed: "+ftp.getReplyString()); |
| } |
| } |
| |
| // Strings feature check |
| String []features = ftp.featureValues(remote); |
| if (features != null) { |
| for(String f : features) { |
| System.out.println("FEAT "+remote+"="+f+"."); |
| } |
| } else { |
| if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) { |
| System.out.println("FEAT "+remote+" is not present"); |
| } else { |
| System.out.println("Command failed: "+ftp.getReplyString()); |
| } |
| } |
| } else { |
| if (ftp.features()) { |
| // Command listener has already printed the output |
| } else { |
| System.out.println("Failed: "+ftp.getReplyString()); |
| } |
| } |
| } |
| else if (doCommand != null) |
| { |
| if (ftp.doCommand(doCommand, remote)) { |
| // Command listener has already printed the output |
| // for(String s : ftp.getReplyStrings()) { |
| // System.out.println(s); |
| // } |
| } else { |
| System.out.println("Failed: "+ftp.getReplyString()); |
| } |
| } |
| else |
| { |
| OutputStream output; |
| |
| output = new FileOutputStream(local); |
| |
| ftp.retrieveFile(remote, output); |
| |
| output.close(); |
| |
| if (keepAliveTimeout > 0) { |
| showCslStats(ftp); |
| } |
| } |
| |
| ftp.noop(); // check that control connection is working OK |
| |
| ftp.logout(); |
| } |
| catch (FTPConnectionClosedException e) |
| { |
| error = true; |
| System.err.println("Server closed connection."); |
| e.printStackTrace(); |
| } |
| catch (IOException e) |
| { |
| error = true; |
| e.printStackTrace(); |
| } |
| finally |
| { |
| if (ftp.isConnected()) |
| { |
| try |
| { |
| ftp.disconnect(); |
| } |
| catch (IOException f) |
| { |
| // do nothing |
| } |
| } |
| } |
| |
| System.exit(error ? 1 : 0); |
| } // end main |
| |
| private static void showCslStats(FTPClient ftp) { |
| @SuppressWarnings("deprecation") // debug code |
| int []stats = ftp.getCslDebug(); |
| System.out.println("CslDebug="+Arrays.toString(stats)); |
| |
| } |
| |
| private static CopyStreamListener createListener(){ |
| return new CopyStreamListener(){ |
| private long megsTotal = 0; |
| |
| @Override |
| public void bytesTransferred(CopyStreamEvent event) { |
| bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize()); |
| } |
| |
| @Override |
| public void bytesTransferred(long totalBytesTransferred, |
| int bytesTransferred, long streamSize) { |
| long megs = totalBytesTransferred / 1000000; |
| for (long l = megsTotal; l < megs; l++) { |
| System.err.print("#"); |
| } |
| megsTotal = megs; |
| } |
| }; |
| } |
| } |
| |