151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 2382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.net.ftp.impl; 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.*; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.*; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.AccessController; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedAction; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.PrivilegedExceptionAction; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.text.DateFormat; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.text.ParseException; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.text.SimpleDateFormat; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList; 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Calendar; 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Iterator; 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List; 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.TimeZone; 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Vector; 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.regex.Matcher; 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.regex.Pattern; 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport javax.net.ssl.SSLSocket; 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport javax.net.ssl.SSLSocketFactory; 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.BASE64Decoder; 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.BASE64Encoder; 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.net.ftp.*; 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.util.logging.PlatformLogger; 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class FtpClient extends sun.net.ftp.FtpClient { 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int defaultSoTimeout; 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int defaultConnectTimeout; 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final PlatformLogger logger = 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski PlatformLogger.getLogger("sun.net.ftp.FtpClient"); 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Proxy proxy; 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Socket server; 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private PrintStream out; 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private InputStream in; 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int readTimeout = -1; 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int connectTimeout = -1; 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* Name of encoding to use for output */ 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static String encoding = "ISO8859_1"; 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** remember the ftp server name because we may need it */ 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private InetSocketAddress serverAddr; 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean replyPending = false; 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean loggedIn = false; 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean useCrypto = false; 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private SSLSocketFactory sslFact; 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Socket oldSocket; 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Array of strings (usually 1 entry) for the last reply from the server. */ 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Vector<String> serverResponse = new Vector<String>(1); 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** The last reply code from the ftp daemon. */ 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FtpReplyCode lastReplyCode = null; 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Welcome message from the server, if any. */ 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String welcomeMsg; 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Only passive mode used in JDK. See Bug 8010784. 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final boolean passiveMode = true; 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private TransferType type = TransferType.BINARY; 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private long restartOffset = 0; 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private long lastTransSize = -1; // -1 means 'unknown size' 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String lastFileName; 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Static members used by the parser 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static String[] patStrings = { 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d\\d:\\d\\d)\\s*(\\p{Print}*)", 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d{4})\\s*(\\p{Print}*)", 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 04/28/2006 09:12a 3,563 genBuffer.sh 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "(\\d{2}/\\d{2}/\\d{4})\\s*(\\d{2}:\\d{2}[ap])\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)", 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 01-29-97 11:32PM <DIR> prog 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "(\\d{2}-\\d{2}-\\d{2})\\s*(\\d{2}:\\d{2}[AP]M)\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)" 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static int[][] patternGroups = { 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year, 5 - permissions, 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 6 - user, 7 - group 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski {7, 4, 5, 6, 0, 1, 2, 3}, 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski {7, 4, 5, 0, 6, 1, 2, 3}, 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski {4, 3, 1, 2, 0, 0, 0, 0}, 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski {4, 3, 1, 2, 0, 0, 0, 0}}; 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Pattern[] patterns; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Pattern linkp = Pattern.compile("(\\p{Print}+) \\-\\> (\\p{Print}+)$"); 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.US); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static { 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski final int vals[] = {0, 0}; 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski final String encs[] = {null}; 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski AccessController.doPrivileged( 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<Object>() { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Object run() { 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue(); 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue(); 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encs[0] = System.getProperty("file.encoding", "ISO8859_1"); 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (vals[0] == 0) { 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultSoTimeout = -1; 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultSoTimeout = vals[0]; 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (vals[1] == 0) { 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultConnectTimeout = -1; 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski defaultConnectTimeout = vals[1]; 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encoding = encs[0]; 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isASCIISuperset(encoding)) { 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encoding = "ISO8859_1"; 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski encoding = "ISO8859_1"; 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patterns = new Pattern[patStrings.length]; 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < patStrings.length; i++) { 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski patterns[i] = Pattern.compile(patStrings[i]); 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Test the named character encoding to verify that it converts ASCII 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * characters correctly. We have to use an ASCII based encoding, or else 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the NetworkClients will not work correctly in EBCDIC based systems. 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * However, we cannot just use ASCII or ISO8859_1 universally, because in 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Asian locales, non-ASCII characters may be embedded in otherwise 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ASCII based protocols (eg. HTTP). The specifications (RFC2616, 2398) 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are a little ambiguous in this matter. For instance, RFC2398 [part 2.1] 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * says that the HTTP request URI should be escaped using a defined 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * mechanism, but there is no way to specify in the escaped string what 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the original character set is. It is not correct to assume that 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTF-8 is always used (as in URLs in HTML 4.0). For this reason, 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * until the specifications are updated to deal with this issue more 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * comprehensively, and more importantly, HTTP servers are known to 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * support these mechanisms, we will maintain the current behavior 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * where it is possible to send non-ASCII characters in their original 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unescaped form. 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static boolean isASCIISuperset(String encoding) throws Exception { 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String chkS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "abcdefghijklmnopqrstuvwxyz-_.!~*'();/?:@&=+$,"; 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Expected byte sequence for string above 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] chkB = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 115, 116, 117, 118, 119, 120, 121, 122, 45, 95, 46, 33, 126, 42, 39, 40, 41, 59, 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47, 63, 58, 64, 38, 61, 43, 36, 44}; 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] b = chkS.getBytes(encoding); 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return java.util.Arrays.equals(b, chkB); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class DefaultParser implements FtpDirParser { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Possible patterns: 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * drwxr-xr-x 1 username ftp 512 Jan 29 23:32 prog 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * -rw-r--r-- 1 jcc staff 105009 Feb 3 15:05 test.1 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 01-29-97 11:32PM <DIR> prog 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 04/28/2006 09:12a 3,563 genBuffer.sh 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * drwxr-xr-x folder 0 Jan 29 23:32 prog 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0 DIR 01-29-97 23:32 PROG 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private DefaultParser() { 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public FtpDirEntry parseLine(String line) { 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String fdate = null; 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String fsize = null; 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String time = null; 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String filename = null; 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String permstring = null; 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String username = null; 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String groupname = null; 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean dir = false; 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Calendar now = Calendar.getInstance(); 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int year = now.get(Calendar.YEAR); 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Matcher m = null; 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int j = 0; j < patterns.length; j++) { 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski m = patterns[j].matcher(line); 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (m.find()) { 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year, 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 5 - permissions, 6 - user, 7 - group 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski filename = m.group(patternGroups[j][0]); 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fsize = m.group(patternGroups[j][1]); 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fdate = m.group(patternGroups[j][2]); 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternGroups[j][4] > 0) { 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fdate += (", " + m.group(patternGroups[j][4])); 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (patternGroups[j][3] > 0) { 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fdate += (", " + String.valueOf(year)); 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternGroups[j][3] > 0) { 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski time = m.group(patternGroups[j][3]); 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternGroups[j][5] > 0) { 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski permstring = m.group(patternGroups[j][5]); 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir = permstring.startsWith("d"); 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternGroups[j][6] > 0) { 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski username = m.group(patternGroups[j][6]); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (patternGroups[j][7] > 0) { 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski groupname = m.group(patternGroups[j][7]); 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Old DOS format 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ("<DIR>".equals(fsize)) { 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dir = true; 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski fsize = null; 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (filename != null) { 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Date d; 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = df.parse(fdate); 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = null; 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (d != null && time != null) { 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int c = time.indexOf(":"); 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski now.setTime(d); 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski now.set(Calendar.HOUR, Integer.parseInt(time.substring(0, c))); 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski now.set(Calendar.MINUTE, Integer.parseInt(time.substring(c + 1))); 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = now.getTime(); 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // see if it's a symbolic link, i.e. the name if followed 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // by a -> and a path 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Matcher m2 = linkp.matcher(filename); 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (m2.find()) { 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Keep only the name then 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski filename = m2.group(1); 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean[][] perms = new boolean[3][3]; 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < 3; i++) { 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int j = 0; j < 3; j++) { 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski perms[i][j] = (permstring.charAt((i * 3) + j) != '-'); 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FtpDirEntry file = new FtpDirEntry(filename); 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setUser(username).setGroup(groupname); 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setSize(Long.parseLong(fsize)).setLastModified(d); 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setPermissions(perms); 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setType(dir ? FtpDirEntry.Type.DIR : (line.charAt(0) == 'l' ? FtpDirEntry.Type.LINK : FtpDirEntry.Type.FILE)); 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return file; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class MLSxParser implements FtpDirParser { 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss"); 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public FtpDirEntry parseLine(String line) { 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String name = null; 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i = line.lastIndexOf(";"); 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski name = line.substring(i + 1).trim(); 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski line = line.substring(0, i); 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski name = line.trim(); 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski line = ""; 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FtpDirEntry file = new FtpDirEntry(name); 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (!line.isEmpty()) { 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s; 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i = line.indexOf(";"); 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = line.substring(0, i); 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski line = line.substring(i + 1); 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = line; 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski line = ""; 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i = s.indexOf("="); 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i > 0) { 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String fact = s.substring(0, i); 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String value = s.substring(i + 1); 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.addFact(fact, value); 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = file.getFact("Size"); 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setSize(Long.parseLong(s)); 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = file.getFact("Modify"); 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Date d = null; 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = df.parse(s); 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (ParseException ex) { 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (d != null) { 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setLastModified(d); 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = file.getFact("Create"); 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Date d = null; 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = df.parse(s); 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (ParseException ex) { 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (d != null) { 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setCreated(d); 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = file.getFact("Type"); 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s.equalsIgnoreCase("file")) { 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setType(FtpDirEntry.Type.FILE); 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s.equalsIgnoreCase("dir")) { 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setType(FtpDirEntry.Type.DIR); 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s.equalsIgnoreCase("cdir")) { 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setType(FtpDirEntry.Type.CDIR); 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s.equalsIgnoreCase("pdir")) { 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski file.setType(FtpDirEntry.Type.PDIR); 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return file; 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FtpDirParser parser = new DefaultParser(); 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FtpDirParser mlsxParser = new MLSxParser(); 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Pattern transPat = null; 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void getTransferSize() { 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTransSize = -1; 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If it's a start of data transfer response, let's try to extract 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the size from the response string. Usually it looks like that: 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 150 Opening BINARY mode data connection for foo (6701 bytes). 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String response = getLastResponseString(); 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (transPat == null) { 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski transPat = Pattern.compile("150 Opening .*\\((\\d+) bytes\\)."); 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Matcher m = transPat.matcher(response); 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (m.find()) { 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = m.group(1); 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTransSize = Long.parseLong(s); 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * extract the created file name from the response string: 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 226 Transfer complete (unique file name:toto.txt.1). 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Usually happens when a STOU (store unique) command had been issued. 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void getTransferName() { 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastFileName = null; 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String response = getLastResponseString(); 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i = response.indexOf("unique file name:"); 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int e = response.lastIndexOf(')'); 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (i >= 0) { 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski i += 17; // Length of "unique file name:" 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastFileName = response.substring(i, e); 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pulls the response from the server and returns the code as a 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * number. Returns -1 on failure. 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int readServerResponse() throws IOException { 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer replyBuf = new StringBuffer(32); 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int c; 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int continuingCode = -1; 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int code; 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String response; 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverResponse.setSize(0); 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (true) { 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((c = in.read()) != -1) { 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '\r') { 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((c = in.read()) != '\n') { 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski replyBuf.append('\r'); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski replyBuf.append((char) c); 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (c == '\n') { 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski response = replyBuf.toString(); 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski replyBuf.setLength(0); 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (logger.isLoggable(PlatformLogger.FINEST)) { 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski logger.finest("Server [" + serverAddr + "] --> " + response); 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (response.length() == 0) { 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski code = -1; 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski code = Integer.parseInt(response.substring(0, 3)); 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (NumberFormatException e) { 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski code = -1; 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (StringIndexOutOfBoundsException e) { 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* this line doesn't contain a response code, so 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski we just completely ignore it */ 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverResponse.addElement(response); 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (continuingCode != -1) { 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* we've seen a ###- sequence */ 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (code != continuingCode || 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (response.length() >= 4 && response.charAt(3) == '-')) { 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* seen the end of code sequence */ 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continuingCode = -1; 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (response.length() >= 4 && response.charAt(3) == '-') { 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continuingCode = code; 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski continue; 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return code; 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Sends command <i>cmd</i> to the server. */ 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void sendServer(String cmd) { 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out.print(cmd); 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (logger.isLoggable(PlatformLogger.FINEST)) { 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski logger.finest("Server [" + serverAddr + "] <-- " + cmd); 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** converts the server response into a string. */ 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String getResponseString() { 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return serverResponse.elementAt(0); 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** Returns all server response strings. */ 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Vector<String> getResponseStrings() { 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return serverResponse; 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read the reply from the FTP server. 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean readReply() throws IOException { 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastReplyCode = FtpReplyCode.find(readServerResponse()); 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode.isPositivePreliminary()) { 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski replyPending = true; 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode.isPositiveCompletion() || lastReplyCode.isPositiveIntermediate()) { 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode == FtpReplyCode.CLOSING_DATA_CONNECTION) { 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getTransferName(); 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return true; 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return false; 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends a command to the FTP server and returns the error code 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (which can be a "success") sent by the server. 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cmd 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 521382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak private boolean issueCommand(String cmd) throws IOException, 522382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak sun.net.ftp.FtpProtocolException { 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isConnected()) { 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalStateException("Not connected"); 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (replyPending) { 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski completePending(); 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (sun.net.ftp.FtpProtocolException e) { 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // ignore... 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 533382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak if (cmd.indexOf('\n') != -1) { 534382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak sun.net.ftp.FtpProtocolException ex 535382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak = new sun.net.ftp.FtpProtocolException("Illegal FTP command"); 536382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak ex.initCause(new IllegalArgumentException("Illegal carriage return")); 537382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak throw ex; 538382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak } 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sendServer(cmd + "\r\n"); 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readReply(); 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Send a command to the FTP server and check for success. 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cmd String containing the command 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws FtpProtocolException if an error occured 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void issueCommandCheck(String cmd) throws sun.net.ftp.FtpProtocolException, IOException { 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!issueCommand(cmd)) { 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode()); 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Pattern epsvPat = null; 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static Pattern pasvPat = null; 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Opens a "PASSIVE" connection with the server and returns the connected 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>Socket</code>. 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the connected <code>Socket</code> 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the connection was unsuccessful. 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Socket openPassiveDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException { 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String serverAnswer; 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int port; 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InetSocketAddress dest = null; 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Here is the idea: 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * - First we want to try the new (and IPv6 compatible) EPSV command 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * But since we want to be nice with NAT software, we'll issue the 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EPSV ALL command first. 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EPSV is documented in RFC2428 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * - If EPSV fails, then we fall back to the older, yet ok, PASV 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * - If PASV fails as well, then we throw an exception and the calling 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method will have to try the EPRT or PORT command 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (issueCommand("EPSV ALL")) { 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // We can safely use EPSV commands 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("EPSV"); 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverAnswer = getResponseString(); 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The response string from a EPSV command will contain the port number 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the format will be : 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 229 Entering Extended PASSIVE Mode (|||58210|) 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // So we'll use the regular expresions package to parse the output. 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (epsvPat == null) { 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski epsvPat = Pattern.compile("^229 .* \\(\\|\\|\\|(\\d+)\\|\\)"); 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Matcher m = epsvPat.matcher(serverAnswer); 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!m.find()) { 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("EPSV failed : " + serverAnswer); 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Yay! Let's extract the port number 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = m.group(1); 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski port = Integer.parseInt(s); 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InetAddress add = server.getInetAddress(); 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (add != null) { 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dest = new InetSocketAddress(add, port); 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This means we used an Unresolved address to connect in 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the first place. Most likely because the proxy is doing 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the name resolution for us, so let's keep using unresolved 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // address. 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dest = InetSocketAddress.createUnresolved(serverAddr.getHostName(), port); 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // EPSV ALL failed, so Let's try the regular PASV cmd 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PASV"); 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverAnswer = getResponseString(); 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Let's parse the response String to get the IP & port to connect 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // to. The String should be in the following format : 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 227 Entering PASSIVE Mode (A1,A2,A3,A4,p1,p2) 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that the two parenthesis are optional 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The IP address is A1.A2.A3.A4 and the port is p1 * 256 + p2 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The regular expression is a bit more complex this time, because 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // the parenthesis are optionals and we have to use 3 groups. 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (pasvPat == null) { 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pasvPat = Pattern.compile("227 .* \\(?(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)?"); 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Matcher m = pasvPat.matcher(serverAnswer); 63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!m.find()) { 63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("PASV failed : " + serverAnswer); 63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Get port number out of group 2 & 3 63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski port = Integer.parseInt(m.group(3)) + (Integer.parseInt(m.group(2)) << 8); 63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // IP address is simple 63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = m.group(1).replace(',', '.'); 64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dest = new InetSocketAddress(s, port); 64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Got everything, let's open the socket! 64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (proxy != null) { 64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (proxy.type() == Proxy.Type.SOCKS) { 64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = AccessController.doPrivileged( 64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<Socket>() { 64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Socket run() { 65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Socket(proxy); 65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = new Socket(Proxy.NO_PROXY); 65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = new Socket(); 65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InetAddress serverAddress = AccessController.doPrivileged( 66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<InetAddress>() { 66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Override 66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public InetAddress run() { 66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return server.getLocalAddress(); 66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Bind the socket to the same address as the control channel. This 66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // is needed in case of multi-homed systems. 67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.bind(new InetSocketAddress(serverAddress, 0)); 67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (connectTimeout >= 0) { 67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest, connectTimeout); 67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (defaultConnectTimeout > 0) { 67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest, defaultConnectTimeout); 67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest); 67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (readTimeout >= 0) { 68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.setSoTimeout(readTimeout); 68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (defaultSoTimeout > 0) { 68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.setSoTimeout(defaultSoTimeout); 68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCrypto) { 68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = sslFact.createSocket(s, dest.getHostName(), dest.getPort(), true); 68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Can't open secure data channel: " + e); 69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!issueCommand(cmd)) { 69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.close(); 69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (getLastReplyCode() == FtpReplyCode.FILE_UNAVAILABLE) { 69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Ensure backward compatibility 69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new FileNotFoundException(cmd); 69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode()); 70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Opens a data connection with the server according to the set mode 70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (ACTIVE or PASSIVE) then send the command passed as an argument. 70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cmd the <code>String</code> containing the command to execute 70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the connected <code>Socket</code> 71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the connection or command failed 71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Socket openDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException { 71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket clientSocket; 71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (passiveMode) { 71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return openPassiveDataConnection(cmd); 71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (sun.net.ftp.FtpProtocolException e) { 71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // If Passive mode failed, fall back on PORT 72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Otherwise throw exception 72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String errmsg = e.getMessage(); 72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!errmsg.startsWith("PASV") && !errmsg.startsWith("EPSV")) { 72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw e; 72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ServerSocket portSocket; 72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InetAddress myAddress; 72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String portCmd; 73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (proxy != null && proxy.type() == Proxy.Type.SOCKS) { 73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // We're behind a firewall and the passive mode fail, 73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // since we can't accept a connection through SOCKS (yet) 73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // throw an exception 73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Passive mode failed"); 73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Bind the ServerSocket to the same address as the control channel 73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This is needed for multi-homed systems 73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portSocket = new ServerSocket(0, 1, server.getLocalAddress()); 74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski myAddress = portSocket.getInetAddress(); 74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (myAddress.isAnyLocalAddress()) { 74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski myAddress = server.getLocalAddress(); 74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Let's try the new, IPv6 compatible EPRT command 74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // See RFC2428 for specifics 74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Some FTP servers (like the one on Solaris) are bugged, they 74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // will accept the EPRT command but then, the subsequent command 74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (e.g. RETR) will fail, so we have to check BOTH results (the 75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // EPRT cmd then the actual command) to decide wether we should 75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // fall back on the older PORT command. 75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portCmd = "EPRT |" + ((myAddress instanceof Inet6Address) ? "2" : "1") + "|" + 75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski myAddress.getHostAddress() + "|" + portSocket.getLocalPort() + "|"; 75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!issueCommand(portCmd) || !issueCommand(cmd)) { 75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The EPRT command failed, let's fall back to good old PORT 75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portCmd = "PORT "; 75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] addr = myAddress.getAddress(); 75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* append host addr */ 76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < addr.length; i++) { 76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portCmd = portCmd + (addr[i] & 0xFF) + ","; 76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* append port number */ 76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portCmd = portCmd + ((portSocket.getLocalPort() >>> 8) & 0xff) + "," + (portSocket.getLocalPort() & 0xff); 76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck(portCmd); 76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck(cmd); 76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Either the EPRT or the PORT command was successful 77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Let's create the client socket 77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (connectTimeout >= 0) { 77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portSocket.setSoTimeout(connectTimeout); 77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (defaultConnectTimeout > 0) { 77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portSocket.setSoTimeout(defaultConnectTimeout); 77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clientSocket = portSocket.accept(); 77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (readTimeout >= 0) { 78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clientSocket.setSoTimeout(readTimeout); 78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (defaultSoTimeout > 0) { 78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clientSocket.setSoTimeout(defaultSoTimeout); 78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski portSocket.close(); 78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCrypto) { 79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski clientSocket = sslFact.createSocket(clientSocket, serverAddr.getHostName(), serverAddr.getPort(), true); 79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception ex) { 79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException(ex.getLocalizedMessage()); 79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return clientSocket; 79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private InputStream createInputStream(InputStream in) { 80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.ASCII) { 80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new sun.net.TelnetInputStream(in, false); 80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return in; 80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private OutputStream createOutputStream(OutputStream out) { 80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.ASCII) { 80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new sun.net.TelnetOutputStream(out, false); 80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return out; 81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates an instance of FtpClient. The client is not connected to any 81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server yet. 81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected FtpClient() { 81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates an instance of FtpClient. The client is not connected to any 82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server yet. 82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static sun.net.ftp.FtpClient create() { 82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new FtpClient(); 82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Set the transfer mode to <I>passive</I>. In that mode, data connections 83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are established by having the client connect to the server. 83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is the recommended default mode as it will work best through 83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * firewalls and NATs. 83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return This FtpClient 83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setActiveMode() 83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) { 84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Only passive mode used in JDK. See Bug 8010784. 84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // passiveMode = passive; 84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Gets the current transfer mode. 84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the current <code>FtpTransferMode</code> 84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isPassiveModeEnabled() { 85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return passiveMode; 85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the timeout value to use when connecting to the server, 85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param timeout the timeout value, in milliseconds, to use for the connect 85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * operation. A value of zero or less, means use the default timeout. 85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return This FtpClient 86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setConnectTimeout(int timeout) { 86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski connectTimeout = timeout; 86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the current connection timeout value. 86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the value, in milliseconds, of the current connect timeout. 87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setConnectTimeout(int) 87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getConnectTimeout() { 87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return connectTimeout; 87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the timeout value to use when reading from the server, 87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param timeout the timeout value, in milliseconds, to use for the read 88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * operation. A value of zero or less, means use the default timeout. 88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return This FtpClient 88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setReadTimeout(int timeout) { 88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski readTimeout = timeout; 88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the current read timeout value. 89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the value, in milliseconds, of the current read timeout. 89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setReadTimeout(int) 89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getReadTimeout() { 89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readTimeout; 89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setProxy(Proxy p) { 90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski proxy = p; 90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get the proxy of this FtpClient 90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the <code>Proxy</code>, this client is using, or <code>null</code> 90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if none is used. 90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setProxy(Proxy) 91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Proxy getProxy() { 91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return proxy; 91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Connects to the specified destination. 91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param dest the <code>InetSocketAddress</code> to connect to. 91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the connection fails. 92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void tryConnect(InetSocketAddress dest, int timeout) throws IOException { 92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isConnected()) { 92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski disconnect(); 92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server = doConnect(dest, timeout); 92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), 92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, encoding); 92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (UnsupportedEncodingException e) { 93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError(encoding + "encoding not found"); 93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = new BufferedInputStream(server.getInputStream()); 93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Socket doConnect(InetSocketAddress dest, int timeout) throws IOException { 93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (proxy != null) { 93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (proxy.type() == Proxy.Type.SOCKS) { 93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = AccessController.doPrivileged( 94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<Socket>() { 94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Socket run() { 94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Socket(proxy); 94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = new Socket(Proxy.NO_PROXY); 94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = new Socket(); 95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Instance specific timeouts do have priority, that means 95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // connectTimeout & readTimeout (-1 means not set) 95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Then global default timeouts 95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Then no timeout. 95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (timeout >= 0) { 95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest, timeout); 95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (connectTimeout >= 0) { 96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest, connectTimeout); 96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (defaultConnectTimeout > 0) { 96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest, defaultConnectTimeout); 96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.connect(dest); 96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (readTimeout >= 0) { 97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.setSoTimeout(readTimeout); 97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if (defaultSoTimeout > 0) { 97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s.setSoTimeout(defaultSoTimeout); 97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void disconnect() throws IOException { 97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isConnected()) { 97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server.close(); 98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server = null; 98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = null; 98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out = null; 98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastTransSize = -1; 98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastFileName = null; 98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski restartOffset = 0; 98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski welcomeMsg = null; 98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski lastReplyCode = null; 98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverResponse.setSize(0); 99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Tests whether this client is connected or not to a server. 99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the client is connected. 99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isConnected() { 99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return server != null; 99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public SocketAddress getServerAddress() { 100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return server == null ? null : server.getRemoteSocketAddress(); 100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient connect(SocketAddress dest) throws sun.net.ftp.FtpProtocolException, IOException { 100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return connect(dest, -1); 100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Connects the FtpClient to the specified destination. 101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param dest the address of the destination server 101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if connection failed. 101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient connect(SocketAddress dest, int timeout) throws sun.net.ftp.FtpProtocolException, IOException { 101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!(dest instanceof InetSocketAddress)) { 101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("Wrong address type"); 101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverAddr = (InetSocketAddress) dest; 102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tryConnect(serverAddr, timeout); 102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!readReply()) { 102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Welcome message: " + 102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getResponseString(), lastReplyCode); 102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski welcomeMsg = getResponseString().substring(4); 102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void tryLogin(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException { 103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("USER " + user); 103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Checks for "331 User name okay, need password." answer 103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode == FtpReplyCode.NEED_PASSWORD) { 103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((password != null) && (password.length > 0)) { 103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PASS " + String.valueOf(password)); 103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Attempts to log on the server with the specified user name and password. 104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param user The user name 104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param password The password for that user 104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the login was successful. 104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission 104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient login(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException { 105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isConnected()) { 105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE); 105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (user == null || user.length() == 0) { 105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("User name can't be null or empty"); 105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tryLogin(user, password); 105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // keep the welcome message around so we can 106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // put it in the resulting HTML page. 106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String l; 106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < serverResponse.size(); i++) { 106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski l = serverResponse.elementAt(i); 106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l != null) { 106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l.length() >= 4 && l.startsWith("230")) { 106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // get rid of the "230-" prefix 106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski l = l.substring(4); 106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(l); 107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski welcomeMsg = sb.toString(); 107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski loggedIn = true; 107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Attempts to log on the server with the specified user name, password and 108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * account name. 108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param user The user name 108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param password The password for that user. 108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param account The account name for that user. 108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the login was successful. 108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient login(String user, char[] password, String account) throws sun.net.ftp.FtpProtocolException, IOException { 108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isConnected()) { 109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE); 109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (user == null || user.length() == 0) { 109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("User name can't be null or empty"); 109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tryLogin(user, password); 109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Checks for "332 Need account for login." answer 110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode == FtpReplyCode.NEED_ACCOUNT) { 110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("ACCT " + account); 110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // keep the welcome message around so we can 110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // put it in the resulting HTML page. 110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (serverResponse != null) { 110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String l : serverResponse) { 111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l != null) { 111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l.length() >= 4 && l.startsWith("230")) { 111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // get rid of the "230-" prefix 111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski l = l.substring(4); 111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(l); 111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski welcomeMsg = sb.toString(); 112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski loggedIn = true; 112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Logs out the current user. This is in effect terminates the current 112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * session and the connection to the server will be closed. 112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws IOException { 113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (isConnected()) { 1131382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak try { 1132382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak issueCommand("QUIT"); 1133382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak } catch (FtpProtocolException e) { 1134382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak } 113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski loggedIn = false; 113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski disconnect(); 113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Checks whether the client is logged in to the server or not. 114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the client has already completed a login. 114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isLoggedIn() { 114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return loggedIn; 114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Changes to a specific directory on a remote FTP server 115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param remoteDirectory path of the directory to CD to. 115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception <code>FtpProtocolException</code> 115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient changeDirectory(String remoteDirectory) throws sun.net.ftp.FtpProtocolException, IOException { 115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (remoteDirectory == null || "".equals(remoteDirectory)) { 115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("directory can't be null or empty"); 115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("CWD " + remoteDirectory); 116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Changes to the parent directory, sending the CDUP command to the server. 116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful. 116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException 117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient changeToParentDirectory() throws sun.net.ftp.FtpProtocolException, IOException { 117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("CDUP"); 117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the server current working directory, or <code>null</code> if 117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the PWD command failed. 117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>String</code> containing the current working directory, 118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or <code>null</code> 118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException 118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getWorkingDirectory() throws sun.net.ftp.FtpProtocolException, IOException { 118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PWD"); 118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * answer will be of the following format : 118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 257 "/" is current directory. 119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String answ = getResponseString(); 119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!answ.startsWith("257")) { 119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return answ.substring(5, answ.lastIndexOf('"')); 119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the restart offset to the specified value. That value will be 120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sent through a <code>REST</code> command to server before a file 120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transfer and has the effect of resuming a file transfer from the 120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specified point. After a transfer the restart offset is set back to 120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * zero. 120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param offset the offset in the remote file at which to start the next 120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transfer. This must be a value greater than or equal to zero. 120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IllegalArgumentException if the offset is negative. 120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setRestartOffset(long offset) { 121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (offset < 0) { 121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("offset can't be negative"); 121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski restartOffset = offset; 121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Retrieves a file from the ftp server and writes it to the specified 121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>OutputStream</code>. 122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If the restart offset was set, then a <code>REST</code> command will be 122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sent before the RETR in order to restart the tranfer from the specified 122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * offset. 122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The <code>OutputStream</code> is not closed by this method at the end 122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the transfer. 122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name a <code>String<code> containing the name of the file to 122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * retreive from the server. 122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param local the <code>OutputStream</code> the file should be written to. 122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the transfer fails. 123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient getFile(String name, OutputStream local) throws sun.net.ftp.FtpProtocolException, IOException { 123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int mtu = 1500; 123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (restartOffset > 0) { 123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection("REST " + restartOffset); 123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski restartOffset = 0; 123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("RETR " + name); 124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getTransferSize(); 124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InputStream remote = createInputStream(s.getInputStream()); 124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buf = new byte[mtu * 10]; 124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l; 124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((l = remote.read(buf)) >= 0) { 124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l > 0) { 124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski local.write(buf, 0, l); 124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.close(); 125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = openDataConnection("RETR " + name); 125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getTransferSize(); 125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski InputStream remote = createInputStream(s.getInputStream()); 125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buf = new byte[mtu * 10]; 125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l; 125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((l = remote.read(buf)) >= 0) { 125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l > 0) { 125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski local.write(buf, 0, l); 126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.close(); 126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return completePending(); 126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Retrieves a file from the ftp server, using the RETR command, and 126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * returns the InputStream from* the established data connection. 127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #completePending()} <b>has</b> to be called once the application 127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is done reading from the returned stream. 127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the remote file 127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the {@link java.io.InputStream} from the data connection, or 127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> if the command was unsuccessful. 127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public InputStream getFileStream(String name) throws sun.net.ftp.FtpProtocolException, IOException { 127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (restartOffset > 0) { 128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection("REST " + restartOffset); 128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } finally { 128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski restartOffset = 0; 128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null) { 128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("RETR " + name); 129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getTransferSize(); 129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return createInputStream(s.getInputStream()); 129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection("RETR " + name); 129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null) { 129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski getTransferSize(); 129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return createInputStream(s.getInputStream()); 130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Transfers a file from the client to the server (aka a <I>put</I>) 130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by sending the STOR or STOU command, depending on the 130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>unique</code> argument, and returns the <code>OutputStream</code> 130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * from the established data connection. 130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #completePending()} <b>has</b> to be called once the application 130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is finished writing to the stream. 130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A new file is created at the server site if the file specified does 131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not already exist. 131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If <code>unique</code> is set to <code>true</code>, the resultant file 131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is to be created under a name unique to that directory, meaning 131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it will not overwrite an existing file, instead the server will 131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * generate a new, unique, file name. 131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The name of the remote file can be retrieved, after completion of the 131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transfer, by calling {@link #getLastFileName()}. 131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the remote file to write. 132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param unique <code>true</code> if the remote files should be unique, 132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in which case the STOU command will be used. 132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the {@link java.io.OutputStream} from the data connection or 132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> if the command was unsuccessful. 132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public OutputStream putFileStream(String name, boolean unique) 132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws sun.net.ftp.FtpProtocolException, IOException 132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski { 133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String cmd = unique ? "STOU " : "STOR "; 133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = openDataConnection(cmd + name); 133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null) { 133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski boolean bm = (type == TransferType.BINARY); 133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new sun.net.TelnetOutputStream(s.getOutputStream(), bm); 133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Transfers a file from the client to the server (aka a <I>put</I>) 134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by sending the STOR command. The content of the <code>InputStream</code> 134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * passed in argument is written into the remote file, overwriting any 134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * existing data. 134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A new file is created at the server site if the file specified does 134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not already exist. 134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name the name of the remote file to write. 134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param local the <code>InputStream</code> that points to the data to 135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transfer. 135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param unique <code>true</code> if the remote file should be unique 135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (i.e. not already existing), <code>false</code> otherwise. 135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the transfer was successful. 135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #getLastFileName() 135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient putFile(String name, InputStream local, boolean unique) throws sun.net.ftp.FtpProtocolException, IOException { 135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String cmd = unique ? "STOU " : "STOR "; 135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int mtu = 1500; 136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.BINARY) { 136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = openDataConnection(cmd + name); 136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski OutputStream remote = createOutputStream(s.getOutputStream()); 136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buf = new byte[mtu * 10]; 136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l; 136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((l = local.read(buf)) >= 0) { 136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l > 0) { 136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.write(buf, 0, l); 136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.close(); 137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return completePending(); 137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the APPE command to the server in order to transfer a data stream 137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * passed in argument and append it to the content of the specified remote 137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * file. 137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name A <code>String</code> containing the name of the remote file 138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to append to. 138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param local The <code>InputStream</code> providing access to the data 138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to be appended. 138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the transfer was successful. 138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient appendFile(String name, InputStream local) throws sun.net.ftp.FtpProtocolException, IOException { 138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int mtu = 1500; 138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = openDataConnection("APPE " + name); 139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski OutputStream remote = createOutputStream(s.getOutputStream()); 139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] buf = new byte[mtu * 10]; 139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int l; 139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while ((l = local.read(buf)) >= 0) { 139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l > 0) { 139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.write(buf, 0, l); 139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski remote.close(); 139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return completePending(); 140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Renames a file on the server. 140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param from the name of the file being renamed 140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param to the new name for the file 140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if the command fails 140851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 140951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient rename(String from, String to) throws sun.net.ftp.FtpProtocolException, IOException { 141051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("RNFR " + from); 141151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("RNTO " + to); 141251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 141351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 141451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 141551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 141651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Deletes a file on the server. 141751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 141851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name a <code>String</code> containing the name of the file 141951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to delete. 142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful 142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the exchange 142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient deleteFile(String name) throws sun.net.ftp.FtpProtocolException, IOException { 142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("DELE " + name); 142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a new directory on the server. 143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name a <code>String</code> containing the name of the directory 143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to create. 143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the exchange 143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient makeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException { 143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("MKD " + name); 143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Removes a directory on the server. 144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name a <code>String</code> containing the name of the directory 144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to remove. 144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the exchange. 144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient removeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException { 145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("RMD " + name); 145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends a No-operation command. It's useful for testing the connection 145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * status or as a <I>keep alive</I> mechanism. 145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws FtpProtocolException if the command fails 146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient noop() throws sun.net.ftp.FtpProtocolException, IOException { 146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("NOOP"); 146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the STAT command to the server. 146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This can be used while a data connection is open to get a status 146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * on the current transfer, in that case the parameter should be 147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code>. 147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If used between file transfers, it may have a pathname as argument 147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in which case it will work as the LIST command except no data 147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * connection will be created. 147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param name an optional <code>String</code> containing the pathname 147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the STAT command should apply to. 147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the response from the server or <code>null</code> if the 147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command failed. 147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getStatus(String name) throws sun.net.ftp.FtpProtocolException, IOException { 148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck((name == null ? "STAT" : "STAT " + name)); 148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A typical response will be: 148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 213-status of t32.gif: 148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * -rw-r--r-- 1 jcc staff 247445 Feb 17 1998 t32.gif 148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 213 End of Status 148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or 149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 211-jsn FTP server status: 149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Version wu-2.6.2+Sun 149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Connected to localhost (::1) 149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Logged in as jccollet 149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * TYPE: ASCII, FORM: Nonprint; STRUcture: File; transfer MODE: Stream 149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * No data connection 149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0 data bytes received in 0 files 149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0 data bytes transmitted in 0 files 149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 0 data bytes total in 0 files 150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 53 traffic bytes received in 0 transfers 150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 485 traffic bytes transmitted in 0 transfers 150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 587 traffic bytes total in 0 transfers 150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 211 End of status 150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * So we need to remove the 1st and last line 150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<String> resp = getResponseStrings(); 150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 1; i < resp.size() - 1; i++) { 151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(resp.get(i)); 151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the FEAT command to the server and returns the list of supported 151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * features in the form of strings. 151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The features are the supported commands, like AUTH TLS, PROT or PASV. 152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See the RFCs for a complete list. 152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that not all FTP servers support that command, in which case 152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the method will return <code>null</code> 152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>List</code> of <code>Strings</code> describing the 152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * supported additional features, or <code>null</code> 152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if the command is not supported. 152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<String> getFeatures() throws sun.net.ftp.FtpProtocolException, IOException { 153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The FEAT command, when implemented will return something like: 153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 211-Features: 153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * AUTH TLS 153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PBSZ 153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PROT 153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EPSV 153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EPRT 154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PASV 154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * REST STREAM 154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 211 END 154351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 154451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ArrayList<String> features = new ArrayList<String>(); 154551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("FEAT"); 154651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<String> resp = getResponseStrings(); 154751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Note that we start at index 1 to skip the 1st line (211-...) 154851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and we stop before the last line. 154951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 1; i < resp.size() - 1; i++) { 155051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = resp.get(i); 155151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Get rid of leading space and trailing newline 155251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski features.add(s.substring(1, s.length() - 1)); 155351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 155451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return features; 155551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 155651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 155851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sends the ABOR command to the server. 155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It tells the server to stop the previous command or transfer. 156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful. 156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient abort() throws sun.net.ftp.FtpProtocolException, IOException { 156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("ABOR"); 156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // TODO: Must check the ReplyCode: 156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * From the RFC: 156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * There are two cases for the server upon receipt of this 157051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command: (1) the FTP service command was already completed, 157151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or (2) the FTP service command is still in progress. 157251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In the first case, the server closes the data connection 157351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (if it is open) and responds with a 226 reply, indicating 157451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that the abort command was successfully processed. 157551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * In the second case, the server aborts the FTP service in 157651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * progress and closes the data connection, returning a 426 157751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * reply to indicate that the service request terminated 157851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * abnormally. The server then sends a 226 reply, 157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * indicating that the abort command was successfully 158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * processed. 158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Some methods do not wait until completion before returning, so this 158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method can be called to wait until completion. This is typically the case 159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with commands that trigger a transfer like {@link #getFileStream(String)}. 159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * So this method should be called before accessing information related to 159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * such a command. 159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>This method will actually block reading on the command channel for a 159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * notification from the server that the command is finished. Such a 159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * notification often carries extra information concerning the completion 159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the pending action (e.g. number of bytes transfered).</p> 159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Note that this will return true immediately if no command or action 159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is pending</p> 159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>It should be also noted that most methods issuing commands to the ftp 160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server will call this method if a previous command is pending. 160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Example of use: 160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * InputStream in = cl.getFileStream("file"); 160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ... 160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cl.completePending(); 160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * long size = cl.getLastTransferSize(); 160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * On the other hand, it's not necessary in a case like: 160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <pre> 161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * InputStream in = cl.getFileStream("file"); 161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * // read content 161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ... 161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cl.logout(); 161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </pre> 161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>Since {@link #logout()} will call completePending() if necessary.</p> 161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the completion was successful or if no 161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * action was pending. 161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException 161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient completePending() throws sun.net.ftp.FtpProtocolException, IOException { 162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (replyPending) { 162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski replyPending = false; 162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!readReply()) { 162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException(getLastResponseString(), lastReplyCode); 162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reinitializes the USER parameters on the FTP server 163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws FtpProtocolException if the command fails 163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient reInit() throws sun.net.ftp.FtpProtocolException, IOException { 163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("REIN"); 163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski loggedIn = false; 163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (useCrypto) { 163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (server instanceof SSLSocket) { 164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski javax.net.ssl.SSLSession session = ((SSLSocket) server).getSession(); 164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski session.invalidate(); 164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Restore previous socket and streams 164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server = oldSocket; 164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski oldSocket = null; 164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), 164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, encoding); 164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (UnsupportedEncodingException e) { 164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError(encoding + "encoding not found"); 165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = new BufferedInputStream(server.getInputStream()); 165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useCrypto = false; 165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Changes the transfer type (binary, ascii, ebcdic) and issue the 166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * proper command (e.g. TYPE A) to the server. 166151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param type the <code>FtpTransferType</code> to use. 166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return This FtpClient 166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during transmission. 166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setType(TransferType type) throws sun.net.ftp.FtpProtocolException, IOException { 166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String cmd = "NOOP"; 166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.type = type; 167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.ASCII) { 167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cmd = "TYPE A"; 167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.BINARY) { 167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cmd = "TYPE I"; 167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type == TransferType.EBCDIC) { 167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski cmd = "TYPE E"; 167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck(cmd); 168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Issues a LIST command to the server to get the current directory 168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * listing, and returns the InputStream from the data connection. 168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #completePending()} <b>has</b> to be called once the application 168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is finished writing to the stream. 168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param path the pathname of the directory to list, or <code>null</code> 169051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for the current working directory. 169151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the <code>InputStream</code> from the resulting data connection 169251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 169351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #changeDirectory(String) 169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #listFiles(String) 169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public InputStream list(String path) throws sun.net.ftp.FtpProtocolException, IOException { 169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection(path == null ? "LIST" : "LIST " + path); 169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return createInputStream(s.getInputStream()); 170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Issues a NLST path command to server to get the specified directory 170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * content. It differs from {@link #list(String)} method by the fact that 170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it will only list the file names which would make the parsing of the 170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * somewhat easier. 171051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 171151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #completePending()} <b>has</b> to be called once the application 171251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is finished writing to the stream. 171351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 171451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param path a <code>String</code> containing the pathname of the 171551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directory to list or <code>null</code> for the current working 171651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directory. 171751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the <code>InputStream</code> from the resulting data connection 171851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 171951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 172051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public InputStream nameList(String path) throws sun.net.ftp.FtpProtocolException, IOException { 172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s; 172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection("NLST " + path); 172351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 172451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return createInputStream(s.getInputStream()); 172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Issues the SIZE [path] command to the server to get the size of a 173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specific file on the server. 173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that this command may not be supported by the server. In which 173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * case -1 will be returned. 173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param path a <code>String</code> containing the pathname of the 173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * file. 173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>long</code> containing the size of the file or -1 if 173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the server returned an error, which can be checked with 173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #getLastReplyCode()}. 174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOException { 174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (path == null || path.length() == 0) { 174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException("path can't be null or empty"); 174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("SIZE " + path); 174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode == FtpReplyCode.FILE_STATUS) { 174851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = getResponseString(); 174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = s.substring(4, s.length() - 1); 175051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Long.parseLong(s); 175151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static String[] MDTMformats = { 175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "yyyyMMddHHmmss.SSS", 175651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "yyyyMMddHHmmss" 175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static SimpleDateFormat[] dateFormats = new SimpleDateFormat[MDTMformats.length]; 175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static { 176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < MDTMformats.length; i++) { 176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dateFormats[i] = new SimpleDateFormat(MDTMformats[i]); 176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT")); 176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Issues the MDTM [path] command to the server to get the modification 176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * time of a specific file on the server. 177051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that this command may not be supported by the server, in which 177151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * case <code>null</code> will be returned. 177251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 177351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param path a <code>String</code> containing the pathname of the file. 177451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>Date</code> representing the last modification time 177551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or <code>null</code> if the server returned an error, which 177651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * can be checked with {@link #getLastReplyCode()}. 177751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 177851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 177951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getLastModified(String path) throws sun.net.ftp.FtpProtocolException, IOException { 178051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("MDTM " + path); 178151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode == FtpReplyCode.FILE_STATUS) { 178251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = getResponseString().substring(4); 178351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Date d = null; 178451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (SimpleDateFormat dateFormat : dateFormats) { 178551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 178651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski d = dateFormat.parse(s); 178751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (ParseException ex) { 178851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 178951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (d != null) { 179051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return d; 179151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 179251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 179351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 179451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 179551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 179651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 179751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 179851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sets the parser used to handle the directory output to the specified 179951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * one. By default the parser is set to one that can handle most FTP 180051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * servers output (Unix base mostly). However it may be necessary for 180151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and application to provide its own parser due to some uncommon 180251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * output format. 180351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 180451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param p The <code>FtpDirParser</code> to use. 180551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #listFiles(String) 180651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 180751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient setDirParser(FtpDirParser p) { 180851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski parser = p; 180951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 181051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 181151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 181251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private class FtpFileIterator implements Iterator<FtpDirEntry>, Closeable { 181351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 181451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private BufferedReader in = null; 181551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FtpDirEntry nextFile = null; 181651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private FtpDirParser fparser = null; 181751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private boolean eof = false; 181851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 181951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public FtpFileIterator(FtpDirParser p, BufferedReader in) { 182051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.in = in; 182151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.fparser = p; 182251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski readNext(); 182351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 182451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 182551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void readNext() { 182651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nextFile = null; 182751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (eof) { 182851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 182951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 183051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String line = null; 183151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 183251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski do { 183351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski line = in.readLine(); 183451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (line != null) { 183551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nextFile = fparser.parseLine(line); 183651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (nextFile != null) { 183751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 183851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 183951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 184051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } while (line != null); 184151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in.close(); 184251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException iOException) { 184351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 184451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski eof = true; 184551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 184651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 184751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean hasNext() { 184851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return nextFile != null; 184951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 185051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 185151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public FtpDirEntry next() { 185251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski FtpDirEntry ret = nextFile; 185351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski readNext(); 185451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return ret; 185551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 185651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 185751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void remove() { 185851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new UnsupportedOperationException("Not supported yet."); 185951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 186051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 186151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws IOException { 186251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (in != null && !eof) { 186351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in.close(); 186451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 186551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski eof = true; 186651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski nextFile = null; 186751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 186851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 186951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 187051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 187151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Issues a MLSD command to the server to get the specified directory 187251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * listing and applies the current parser to create an Iterator of 187351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link java.net.ftp.FtpDirEntry}. Note that the Iterator returned is also a 187451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link java.io.Closeable}. 187551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If the server doesn't support the MLSD command, the LIST command is used 187651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instead. 187751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 187851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #completePending()} <b>has</b> to be called once the application 187951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is finished iterating through the files. 188051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 188151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param path the pathname of the directory to list or <code>null</code> 188251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for the current working directoty. 188351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>Iterator</code> of files or <code>null</code> if the 188451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command failed. 188551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission 188651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #setDirParser(FtpDirParser) 188751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #changeDirectory(String) 188851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 188951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Iterator<FtpDirEntry> listFiles(String path) throws sun.net.ftp.FtpProtocolException, IOException { 189051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = null; 189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BufferedReader sin = null; 189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection(path == null ? "MLSD" : "MLSD " + path); 189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (sun.net.ftp.FtpProtocolException FtpException) { 189551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // The server doesn't understand new MLSD command, ignore and fall 189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // back to LIST 189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sin = new BufferedReader(new InputStreamReader(s.getInputStream())); 190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new FtpFileIterator(mlsxParser, sin); 190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = openDataConnection(path == null ? "LIST" : "LIST " + path); 190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sin = new BufferedReader(new InputStreamReader(s.getInputStream())); 190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new FtpFileIterator(parser, sin); 190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 191051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1912382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak private boolean sendSecurityData(byte[] buf) throws IOException, 1913382a4d3fa486b844f4fd42c16ee41d9a38ba52f0Przemyslaw Szczepaniak sun.net.ftp.FtpProtocolException { 191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BASE64Encoder encoder = new BASE64Encoder(); 191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = encoder.encode(buf); 191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return issueCommand("ADAT " + s); 191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private byte[] getSecurityData() { 192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String s = getLastResponseString(); 192151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s.substring(4, 9).equalsIgnoreCase("ADAT=")) { 192251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski BASE64Decoder decoder = new BASE64Decoder(); 192351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 192451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Need to get rid of the leading '315 ADAT=' 192551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // and the trailing newline 192651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return decoder.decodeBuffer(s.substring(9, s.length() - 1)); 192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (IOException e) { 192851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // 192951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 193251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 193351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 193451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 193551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Attempts to use Kerberos GSSAPI as an authentication mechanism with the 193651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ftp server. This will issue an <code>AUTH GSSAPI</code> command, and if 193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it is accepted by the server, will followup with <code>ADAT</code> 193851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command to exchange the various tokens until authentification is 193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * successful. This conforms to Appendix I of RFC 2228. 194051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if authentication was successful. 194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occurs during the transmission. 194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient useKerberos() throws sun.net.ftp.FtpProtocolException, IOException { 194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Comment out for the moment since it's not in use and would create 194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * needless cross-package links. 194851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("AUTH GSSAPI"); 195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (lastReplyCode != FtpReplyCode.NEED_ADAT) 195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Unexpected reply from server"); 195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GSSManager manager = GSSManager.getInstance(); 195451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GSSName name = manager.createName("SERVICE:ftp@"+ 195551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski serverAddr.getHostName(), null); 195651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GSSContext context = manager.createContext(name, null, null, 195751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski GSSContext.DEFAULT_LIFETIME); 195851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski context.requestMutualAuth(true); 195951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski context.requestReplayDet(true); 196051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski context.requestSequenceDet(true); 196151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski context.requestCredDeleg(true); 196251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte []inToken = new byte[0]; 196351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (!context.isEstablished()) { 196451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] outToken 196551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski = context.initSecContext(inToken, 0, inToken.length); 196651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // send the output token if generated 196751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (outToken != null) { 196851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sendSecurityData(outToken)) { 196951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski inToken = getSecurityData(); 197051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 197151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 197251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 197351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski loggedIn = true; 197451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (GSSException e) { 197551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 197651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 197751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 197851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 197951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 198051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 198151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 198251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the Welcome string the server sent during initial connection. 198351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 198451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>String</code> containing the message the server 198551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * returned during connection or <code>null</code>. 198651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 198751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getWelcomeMsg() { 198851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return welcomeMsg; 198951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 199151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 199251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the last reply code sent by the server. 199351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 199451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the lastReplyCode 199551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 199651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public FtpReplyCode getLastReplyCode() { 199751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return lastReplyCode; 199851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 199951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 200051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 200151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the last response string sent by the server. 200251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 200351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the message string, which can be quite long, last returned 200451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by the server. 200551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 200651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getLastResponseString() { 200751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 200851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (serverResponse != null) { 200951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String l : serverResponse) { 201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (l != null) { 201151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(l); 201251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 201651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 201751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 201851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 201951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns, when available, the size of the latest started transfer. 202051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is retreived by parsing the response string received as an initial 202151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * response to a RETR or similar request. 202251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 202351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the size of the latest transfer or -1 if either there was no 202451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * transfer or the information was unavailable. 202551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 202651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public long getLastTransferSize() { 202751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return lastTransSize; 202851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 202951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 203051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 203151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns, when available, the remote name of the last transfered file. 203251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is mainly useful for "put" operation when the unique flag was 203351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * set since it allows to recover the unique file name created on the 203451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server which may be different from the one submitted with the command. 203551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 203651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the name the latest transfered file remote name, or 203751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> if that information is unavailable. 203851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 203951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getLastFileName() { 204051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return lastFileName; 204151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 204251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 204351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 204451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Attempts to switch to a secure, encrypted connection. This is done by 204551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sending the "AUTH TLS" command. 204651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>See <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a></p> 204751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If successful this will establish a secure command channel with the 204851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server, it will also make it so that all other transfers (e.g. a RETR 204951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command) will be done over an encrypted channel as well unless a 205051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #reInit()} command or a {@link #endSecureSession()} command is issued. 205151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 205251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 205351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 205451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #endSecureSession() 205551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 205651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient startSecureSession() throws sun.net.ftp.FtpProtocolException, IOException { 205751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isConnected()) { 205851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE); 205951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (sslFact == null) { 206151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 206251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault(); 206351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 206451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException(e.getLocalizedMessage()); 206551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 206751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("AUTH TLS"); 206851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Socket s = null; 206951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 207051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski s = sslFact.createSocket(server, serverAddr.getHostName(), serverAddr.getPort(), true); 207151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (javax.net.ssl.SSLException ssle) { 207251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 207351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski disconnect(); 207451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception e) { 207551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 207651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw ssle; 207751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 207851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Remember underlying socket so we can restore it later 207951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski oldSocket = server; 208051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server = s; 208151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 208251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), 208351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, encoding); 208451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (UnsupportedEncodingException e) { 208551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError(encoding + "encoding not found"); 208651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 208751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = new BufferedInputStream(server.getInputStream()); 208851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 208951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PBSZ 0"); 209051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PROT P"); 209151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useCrypto = true; 209251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 209351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 209451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 209551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 209651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends a <code>CCC</code> command followed by a <code>PROT C</code> 209751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * command to the server terminating an encrypted session and reverting 209851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * back to a non crypted transmission. 209951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 210051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 210151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during transmission. 210251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see #startSecureSession() 210351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 210451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient endSecureSession() throws sun.net.ftp.FtpProtocolException, IOException { 210551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!useCrypto) { 210651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 210751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 210851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 210951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("CCC"); 211051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("PROT C"); 211151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski useCrypto = false; 211251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Restore previous socket and streams 211351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski server = oldSocket; 211451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski oldSocket = null; 211551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 211651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), 211751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski true, encoding); 211851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (UnsupportedEncodingException e) { 211951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new InternalError(encoding + "encoding not found"); 212051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 212151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski in = new BufferedInputStream(server.getInputStream()); 212251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 212351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 212451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 212551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 212651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 212751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the "Allocate" (ALLO) command to the server telling it to 212851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pre-allocate the specified number of bytes for the next transfer. 212951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 213051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param size The number of bytes to allocate. 213151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 213251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 213351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 213451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient allocate(long size) throws sun.net.ftp.FtpProtocolException, IOException { 213551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("ALLO " + size); 213651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 213751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 213851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 213951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 214051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the "Structure Mount" (SMNT) command to the server. This let the 214151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * user mount a different file system data structure without altering his 214251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * login or accounting information. 214351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 214451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param struct a <code>String</code> containing the name of the 214551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * structure to mount. 214651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the operation was successful. 214751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 214851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 214951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient structureMount(String struct) throws sun.net.ftp.FtpProtocolException, IOException { 215051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("SMNT " + struct); 215151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 215251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 215351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 215451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 215551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends a SYST (System) command to the server and returns the String 215651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sent back by the server describing the operating system at the 215751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server. 215851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 215951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>String</code> describing the OS, or <code>null</code> 216051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if the operation was not successful. 216151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during the transmission. 216251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 216351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getSystem() throws sun.net.ftp.FtpProtocolException, IOException { 216451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("SYST"); 216551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 216651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 215 UNIX Type: L8 Version: SUNOS 216751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 216851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String resp = getResponseString(); 216951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Get rid of the leading code and blank 217051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return resp.substring(4); 217151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 217251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 217351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 217451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the HELP command to the server, with an optional command, like 217551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * SITE, and returns the text sent back by the server. 217651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 217751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cmd the command for which the help is requested or 217851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>null</code> for the general help 217951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return a <code>String</code> containing the text sent back by the 218051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * server, or <code>null</code> if the command failed. 218151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during transmission 218251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 218351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getHelp(String cmd) throws sun.net.ftp.FtpProtocolException, IOException { 218451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("HELP " + cmd); 218551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 218651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 218751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * HELP 218851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 214-The following commands are implemented. 218951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * USER EPRT STRU ALLO DELE SYST RMD MDTM ADAT 219051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PASS EPSV MODE REST CWD STAT PWD PROT 219151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * QUIT LPRT RETR RNFR LIST HELP CDUP PBSZ 219251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PORT LPSV STOR RNTO NLST NOOP STOU AUTH 219351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PASV TYPE APPE ABOR SITE MKD SIZE CCC 219451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 214 Direct comments to ftp-bugs@jsn. 219551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 219651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * HELP SITE 219751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 214-The following SITE commands are implemented. 219851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UMASK HELP GROUPS 219951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IDLE ALIAS CHECKMETHOD 220051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * CHMOD CDPATH CHECKSUM 220151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 214 Direct comments to ftp-bugs@jsn. 220251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 220351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<String> resp = getResponseStrings(); 220451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (resp.size() == 1) { 220551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Single line response 220651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return resp.get(0).substring(4); 220751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 220851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // on multiple lines answers, like the ones above, remove 1st and last 220951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // line, concat the the others. 221051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski StringBuffer sb = new StringBuffer(); 221151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 1; i < resp.size() - 1; i++) { 221251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sb.append(resp.get(i).substring(3)); 221351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 221451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return sb.toString(); 221551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 221651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 221751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 221851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Sends the SITE command to the server. This is used by the server 221951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to provide services specific to his system that are essential 222051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to file transfer. 222151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 222251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param cmd the command to be sent. 222351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return <code>true</code> if the command was successful. 222451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @throws IOException if an error occured during transmission 222551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 222651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public sun.net.ftp.FtpClient siteCmd(String cmd) throws sun.net.ftp.FtpProtocolException, IOException { 222751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski issueCommandCheck("SITE " + cmd); 222851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 222951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 223051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 2231