/* * ftp4j - A pure Java FTP client library * * Copyright (C) 2008-2010 Carlo Pelliccia (www.sauronsoftware.it) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version * 2.1, as published by the Free Software Foundation. * * This program 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 Lesser General Public License 2.1 for more details. * * You should have received a copy of the GNU Lesser General Public * License version 2.1 along with this program. * If not, see . */ package it.sauronsoftware.ftp4j.connectors; import it.sauronsoftware.ftp4j.FTPConnector; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; /** * This one connects a remote ftp host via a HTTP 1.1 proxy which allows * tunneling through the HTTP CONNECT method. * * The connector's default value for the * useSuggestedAddressForDataConnections flag is false. * * @author Carlo Pelliccia */ public class HTTPTunnelConnector extends FTPConnector { /** * The proxy host name. */ private String proxyHost; /** * The proxy port. */ private int proxyPort; /** * The proxyUser for proxy authentication. */ private String proxyUser; /** * The proxyPass for proxy authentication. */ private String proxyPass; /** * Builds the connector. * * @param proxyHost * The proxy host name. * @param proxyPort * The proxy port. * @param proxyUser * The username for proxy authentication. * @param proxyPass * The password for proxy authentication. */ public HTTPTunnelConnector(String proxyHost, int proxyPort, String proxyUser, String proxyPass) { this.proxyHost = proxyHost; this.proxyPort = proxyPort; this.proxyUser = proxyUser; this.proxyPass = proxyPass; } /** * Builds the connector. * * @param proxyHost * The proxy host name. * @param proxyPort * The proxy port. */ public HTTPTunnelConnector(String proxyHost, int proxyPort) { this(proxyHost, proxyPort, null, null); } private Socket httpConnect(String host, int port, boolean forDataTransfer) throws IOException { // The CRLF sequence. byte[] CRLF = "\r\n".getBytes("UTF-8"); // The connect command line. String connect = "CONNECT " + host + ":" + port + " HTTP/1.1"; String hostHeader = "Host: " + host + ":" + port; // A connection status flag. boolean connected = false; // The socket for the connection with the proxy. Socket socket = null; InputStream in = null; OutputStream out = null; // FTPConnection routine. try { if (forDataTransfer) { socket = tcpConnectForDataTransferChannel(proxyHost, proxyPort); } else { socket = tcpConnectForCommunicationChannel(proxyHost, proxyPort); } in = socket.getInputStream(); out = socket.getOutputStream(); // Send the CONNECT request. out.write(connect.getBytes("UTF-8")); out.write(CRLF); out.write(hostHeader.getBytes("UTF-8")); out.write(CRLF); // Auth headers if (proxyUser != null && proxyPass != null) { String header = "Proxy-Authorization: Basic " + Base64.encode(proxyUser + ":" + proxyPass); out.write(header.getBytes("UTF-8")); out.write(CRLF); } out.write(CRLF); out.flush(); // Get the proxy response. ArrayList responseLines = new ArrayList(); BufferedReader reader = new BufferedReader( new InputStreamReader(in)); for (String line = reader.readLine(); line != null && line.length() > 0; line = reader.readLine()) { responseLines.add(line); } // Parse the response. int size = responseLines.size(); if (size < 1) { throw new IOException( "HTTPTunnelConnector: invalid proxy response"); } String code = null; String response = (String) responseLines.get(0); if (response.startsWith("HTTP/") && response.length() >= 12) { code = response.substring(9, 12); } else { throw new IOException( "HTTPTunnelConnector: invalid proxy response"); } if (!"200".equals(code)) { StringBuffer msg = new StringBuffer(); msg.append("HTTPTunnelConnector: connection failed\r\n"); msg.append("Response received from the proxy:\r\n"); for (int i = 0; i < size; i++) { String line = (String) responseLines.get(i); msg.append(line); msg.append("\r\n"); } throw new IOException(msg.toString()); } connected = true; } catch (IOException e) { throw e; } finally { if (!connected) { if (out != null) { try { out.close(); } catch (Throwable t) { ; } } if (in != null) { try { in.close(); } catch (Throwable t) { ; } } if (socket != null) { try { socket.close(); } catch (Throwable t) { ; } } } } return socket; } public Socket connectForCommunicationChannel(String host, int port) throws IOException { return httpConnect(host, port, false); } public Socket connectForDataTransferChannel(String host, int port) throws IOException { return httpConnect(host, port, true); } }