ftpconnection.java
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· Java 代码 · 共 1,082 行 · 第 1/2 页
JAVA
1,082 行
/* * $Id: FTPConnection.java,v 1.1 2004/01/10 23:34:31 dalibor Exp $ * Copyright (C) 2003 The Free Software Foundation * * This file is part of GNU inetlib, a library. * * GNU inetlib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU inetlib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License. */package gnu.inet.ftp;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.InputStream;import java.io.IOException;import java.io.OutputStream;import java.net.BindException;import java.net.InetAddress;import java.net.ProtocolException;import java.net.Socket;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.List;import gnu.inet.util.CRLFInputStream;import gnu.inet.util.LineInputStream;/** * An FTP client connection, or PI. * This implements RFC 959, with the following exceptions: * <ul> * <li>STAT, HELP, SITE, SMNT, and ACCT commands are not supported.</li> * <li>the TYPE command does not allow alternatives to the default bytesize * (Non-print), and local bytesize is not supported.</li> * </ul> * * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> * @version $Revision: 1.1 $ $Date: 2004/01/10 23:34:31 $ */public class FTPConnection{ /** * The default FTP transmission control port. */ public static final int FTP_PORT = 21; /** * The FTP data port. */ public static final int FTP_DATA_PORT = 20; // -- FTP vocabulary -- protected static final String USER = "USER"; protected static final String PASS = "PASS"; protected static final String ACCT = "ACCT"; protected static final String CWD = "CWD"; protected static final String CDUP = "CDUP"; protected static final String SMNT = "SMNT"; protected static final String REIN = "REIN"; protected static final String QUIT = "QUIT"; protected static final String PORT = "PORT"; protected static final String PASV = "PASV"; protected static final String TYPE = "TYPE"; protected static final String STRU = "STRU"; protected static final String MODE = "MODE"; protected static final String RETR = "RETR"; protected static final String STOR = "STOR"; protected static final String STOU = "STOU"; protected static final String APPE = "APPE"; protected static final String ALLO = "ALLO"; protected static final String REST = "REST"; protected static final String RNFR = "RNFR"; protected static final String RNTO = "RNTO"; protected static final String ABOR = "ABOR"; protected static final String DELE = "DELE"; protected static final String RMD = "RMD"; protected static final String MKD = "MKD"; protected static final String PWD = "PWD"; protected static final String LIST = "LIST"; protected static final String NLST = "NLST"; protected static final String SITE = "SITE"; protected static final String SYST = "SYST"; protected static final String STAT = "STAT"; protected static final String HELP = "HELP"; protected static final String NOOP = "NOOP"; public static final int TYPE_ASCII = 1; public static final int TYPE_EBCDIC = 2; public static final int TYPE_BINARY = 3; public static final int STRUCTURE_FILE = 1; public static final int STRUCTURE_RECORD = 2; public static final int STRUCTURE_PAGE = 3; public static final int MODE_STREAM = 1; public static final int MODE_BLOCK = 2; public static final int MODE_COMPRESSED = 3; // -- Telnet constants -- private static final String US_ASCII = "US-ASCII"; private static final byte[] CRLF = { 0x0d, 0x0a }; /** * The socket used to communicate with the server. */ protected Socket socket; /** * The socket input stream. */ protected LineInputStream in; /** * The socket output stream. */ protected OutputStream out; /** * If true, print debugging information. */ protected boolean debug; /** * The current data transfer process in use by this connection. */ protected DTP dtp; /** * The current representation type. */ protected int representationType = TYPE_ASCII; /** * The current file structure type. */ protected int fileStructure = STRUCTURE_FILE; /** * The current transfer mode. */ protected int transferMode = MODE_STREAM; /** * If true, use passive mode. */ protected boolean passive = false; /** * Creates a new connection to the server using the default port. * @param hostname the hostname of the server to connect to */ public FTPConnection(String hostname) throws UnknownHostException, IOException { this(hostname, -1, -1, -1, false); } /** * Creates a new connection to the server. * @param hostname the hostname of the server to connect to * @param port the port to connect to (if <=0, use default port) */ public FTPConnection(String hostname, int port) throws UnknownHostException, IOException { this(hostname, port, -1, -1, false); } /** * Creates a new connection to the server. * @param hostname the hostname of the server to connect to * @param port the port to connect to (if <=0, use default port) * @param connectionTimeout the connection timeout, in milliseconds * @param timeout the I/O timeout, in milliseconds * @param debug print debugging information */ public FTPConnection(String hostname, int port, int connectionTimeout, int timeout, boolean debug) throws UnknownHostException, IOException { this.debug = debug; if (port <= 0) port = FTP_PORT; // Set up socket // TODO connection timeout socket = new Socket(hostname, port); if (timeout > 0) socket.setSoTimeout(timeout); InputStream in = socket.getInputStream(); in = new BufferedInputStream(in); in = new CRLFInputStream(in); this.in = new LineInputStream(in); OutputStream out = socket.getOutputStream(); this.out = new BufferedOutputStream(out); // Read greeting FTPResponse response = getResponse(); switch (response.getCode()) { case 220: // hello break; default:throw new FTPException(response); } } /** * Authenticate using the specified username and password. * If the username suffices for the server, the password will not be used * and may be null. * @param username the username * @param password the optional password * @return true on success, false otherwise */ public boolean authenticate(String username, String password) throws IOException { String cmd = new StringBuffer(USER).append(' ').append(username).toString(); send(cmd); FTPResponse response = getResponse(); switch (response.getCode()) { case 230: // User logged in return true; case 331: // User name okay, need password break; case 332: // Need account for login case 530: // No such user return false; default:throw new FTPException(response); } cmd = new StringBuffer(PASS).append(' ').append(password).toString(); send(cmd); response = getResponse(); switch (response.getCode()) { case 230: // User logged in case 202: // Superfluous return true; case 332: // Need account for login case 530: // Bad password return false; default: throw new FTPException(response); } } /** * Changes directory to the specified path. * @param path an absolute or relative pathname * @return true on success, false if the specified path does not exist */ public boolean changeWorkingDirectory(String path) throws IOException { String cmd = new StringBuffer(CWD).append(' ').append(path).toString(); send(cmd); FTPResponse response = getResponse(); switch (response.getCode()) { case 250: return true; case 550:return false; default:throw new FTPException(response); } } /** * Changes directory to the parent of the current working directory. * @return true on success, false otherwise */ public boolean changeToParentDirectory() throws IOException { send(CDUP); FTPResponse response = getResponse(); switch (response.getCode()) { case 250: return true; case 550:return false; default:throw new FTPException(response); } } /** * Terminates an authenticated login. * If file transfer is in progress, it remains active for result response * only. */ public void reinitialize() throws IOException { send(REIN); FTPResponse response = getResponse(); switch (response.getCode()) { case 220: if (dtp != null) { dtp.complete(); dtp = null; } break; default: throw new FTPException(response); } } /** * Terminates the control connection. * The file transfer connection remains open for result response only. * This connection is invalid and no further commands may be issued. */ public void logout() throws IOException { send(QUIT); try { getResponse(); // not required } catch(IOException e) { } if (dtp != null) { dtp.complete(); dtp = null; } try { socket.close(); } catch(IOException e) { } } /** * Initialise the data transfer process. */ protected void initialiseDTP() throws IOException { if (dtp != null) { dtp.complete(); dtp = null; } InetAddress localhost = socket.getLocalAddress(); if (passive) { send(PASV); FTPResponse response = getResponse(); switch (response.getCode()) { case 227: String message = response.getMessage(); try { int start = message.indexOf(','); char c = message.charAt(start - 1); while (c > 0x30 && c < 0x39) c = message.charAt((--start) - 1); int mid1 = start; for (int i = 0; i < 4; i++) mid1 = message.indexOf(',', mid1 + 1); int mid2 = message.indexOf(',', mid1 + 1); int end = mid2; c = message.charAt(end + 1); while (c > 0x30 && c < 0x39) c = message.charAt((++end) + 1); String address = message.substring(start, mid1).replace(',', '.'); int port_hi = Integer.parseInt(message.substring(mid1 + 1, mid2)); int port_lo = Integer.parseInt(message.substring(mid2 + 1, end + 1)); int port = (port_hi << 8) | port_lo; System.out.println("Entering passive mode: " + address + ":" + port); dtp = new PassiveModeDTP(address, port, localhost); break; } catch(ArrayIndexOutOfBoundsException e) { throw new ProtocolException(e.getMessage() + ": " + message); } catch(NumberFormatException e) { throw new ProtocolException(e.getMessage() + ": " + message); } default: throw new FTPException(response); } } else { // Get the local port int port = socket.getLocalPort() + 1; int tries = 0; // Bind the active mode DTP while (dtp == null) { try { dtp = new ActiveModeDTP(localhost, port); System.out.println("Listening on: " + port); } catch(BindException e) { port++; tries++; if (tries > 9) throw e; } } // Send PORT command StringBuffer buf = new StringBuffer(PORT); buf.append(' '); // Construct the address/port string form byte[]address = localhost.getAddress(); for (int i = 0; i < address.length; i++) { int a = (int) address[i]; if (a < 0) a += 0x100; buf.append(a); buf.append(','); } int port_hi = (port & 0xff00) >> 8; int port_lo = (port & 0x00ff); buf.append(port_hi); buf.append(','); buf.append(port_lo); send(buf.toString()); // Get response FTPResponse response = getResponse(); switch (response.getCode()) { case 200: // OK break; default: dtp.abort(); dtp = null; throw new FTPException(response); } } dtp.setTransferMode(transferMode); } /** * Set passive mode. * @param flag true if we should use passive mode, false otherwise */ public void setPassive(boolean flag) throws IOException { if (passive != flag) { passive = flag; initialiseDTP(); } } /** * Returns the current representation type of the transfer data. * @return TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY */ public int getRepresentationType() { return representationType; } /** * Sets the desired representation type of the transfer data. * @param type TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY */ public void setRepresentationType(int type) throws IOException { StringBuffer buf = new StringBuffer(TYPE); buf.append(' '); switch (type) { case TYPE_ASCII: buf.append('A'); break; case TYPE_EBCDIC:buf.append('E'); break; case TYPE_BINARY:buf.append('I'); break; default:throw new IllegalArgumentException(Integer.toString(type)); } //buf.append(' '); //buf.append('N'); send(buf.toString()); FTPResponse response = getResponse(); switch (response.getCode()) { case 200: representationType = type; break; default: throw new FTPException(response); } } /** * Returns the current file structure type. * @return STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE */ public int getFileStructure() { return fileStructure; } /** * Sets the desired file structure type. * @param structure STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE */ public void setFileStructure(int structure) throws IOException
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?