001 /* 002 * ftp4j - A pure Java FTP client library 003 * 004 * Copyright (C) 2008-2009 Carlo Pelliccia (www.sauronsoftware.it) 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Lesser General Public License version 008 * 2.1, as published by the Free Software Foundation. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License version 2.1 along with this program. 017 * If not, see <http://www.gnu.org/licenses/>. 018 */ 019 package it.sauronsoftware.ftp4j.connectors; 020 021 import it.sauronsoftware.ftp4j.FTPCommunicationChannel; 022 import it.sauronsoftware.ftp4j.FTPConnection; 023 import it.sauronsoftware.ftp4j.FTPConnector; 024 import it.sauronsoftware.ftp4j.FTPIllegalReplyException; 025 import it.sauronsoftware.ftp4j.FTPReply; 026 027 import java.io.IOException; 028 import java.net.Socket; 029 030 /** 031 * This one connects a remote host via a FTP proxy which supports the SITE or 032 * the OPEN proxy method. 033 * 034 * @author Carlo Pelliccia 035 */ 036 public class FTPProxyConnector implements FTPConnector { 037 038 /** 039 * Requires the connection to the remote host through a SITE command after 040 * proxy authentication. Default one. 041 */ 042 public static int STYLE_SITE_COMMAND = 0; 043 044 /** 045 * Requires the connection to the remote host through a OPEN command without 046 * proxy authentication. 047 */ 048 public static int STYLE_OPEN_COMMAND = 1; 049 050 /** 051 * The proxy host name. 052 */ 053 private String proxyHost; 054 055 /** 056 * The proxy port. 057 */ 058 private int proxyPort; 059 060 /** 061 * The proxyUser for proxy authentication. 062 */ 063 private String proxyUser; 064 065 /** 066 * The proxyPass for proxy authentication. 067 */ 068 private String proxyPass; 069 070 /** 071 * The style used by the proxy. 072 */ 073 public int style = STYLE_SITE_COMMAND; 074 075 /** 076 * Builds the connector. 077 * 078 * Default value for the style is STYLE_SITE_COMMAND. 079 * 080 * @param proxyHost 081 * The proxy host name. 082 * @param proxyPort 083 * The proxy port. 084 * @param proxyUser 085 * The username for proxy authentication. 086 * @param proxyPass 087 * The password for proxy authentication. 088 */ 089 public FTPProxyConnector(String proxyHost, int proxyPort, String proxyUser, 090 String proxyPass) { 091 this.proxyHost = proxyHost; 092 this.proxyPort = proxyPort; 093 this.proxyUser = proxyUser; 094 this.proxyPass = proxyPass; 095 } 096 097 /** 098 * Builds the connector. 099 * 100 * Default value for the style is STYLE_SITE_COMMAND. 101 * 102 * @param proxyHost 103 * The proxy host name. 104 * @param proxyPort 105 * The proxy port. 106 */ 107 public FTPProxyConnector(String proxyHost, int proxyPort) { 108 this(proxyHost, proxyPort, "anonymous", "ftp4j"); 109 } 110 111 /** 112 * Sets the style used by the proxy. 113 * 114 * {@link FTPProxyConnector#STYLE_SITE_COMMAND} - Requires the connection to 115 * the remote host through a SITE command after proxy authentication. 116 * 117 * {@link FTPProxyConnector#STYLE_OPEN_COMMAND} - Requires the connection to 118 * the remote host through a OPEN command without proxy authentication. 119 * 120 * Default value for the style is STYLE_SITE_COMMAND. 121 * 122 * @param style 123 * The style. 124 * @see FTPProxyConnector#STYLE_SITE_COMMAND 125 * @see FTPProxyConnector#STYLE_OPEN_COMMAND 126 */ 127 public void setStyle(int style) { 128 if (style != STYLE_OPEN_COMMAND && style != STYLE_SITE_COMMAND) { 129 throw new IllegalArgumentException("Invalid style"); 130 } 131 this.style = style; 132 } 133 134 public FTPConnection connectForCommunicationChannel(String host, int port) 135 throws IOException { 136 Socket socket = new Socket(proxyHost, proxyPort); 137 SocketConnection socketConnection = new SocketConnection(socket); 138 FTPCommunicationChannel communication = new FTPCommunicationChannel( 139 socketConnection, "ASCII"); 140 // Welcome message. 141 FTPReply r; 142 try { 143 r = communication.readFTPReply(); 144 } catch (FTPIllegalReplyException e) { 145 throw new IOException("Invalid proxy response"); 146 } 147 // Does this reply mean "ok"? 148 if (r.getCode() != 220) { 149 // Mmmmm... it seems no! 150 throw new IOException("Invalid proxy response"); 151 } 152 if (style == STYLE_SITE_COMMAND) { 153 // Usefull flags. 154 boolean passwordRequired; 155 // Send the user and read the reply. 156 communication.sendFTPCommand("USER " + proxyUser); 157 try { 158 r = communication.readFTPReply(); 159 } catch (FTPIllegalReplyException e) { 160 throw new IOException("Invalid proxy response"); 161 } 162 switch (r.getCode()) { 163 case 230: 164 // Password isn't required. 165 passwordRequired = false; 166 break; 167 case 331: 168 // Password is required. 169 passwordRequired = true; 170 break; 171 default: 172 // User validation failed. 173 throw new IOException("Proxy authentication failed"); 174 } 175 // Password. 176 if (passwordRequired) { 177 // Send the password. 178 communication.sendFTPCommand("PASS " + proxyPass); 179 try { 180 r = communication.readFTPReply(); 181 } catch (FTPIllegalReplyException e) { 182 throw new IOException("Invalid proxy response"); 183 } 184 if (r.getCode() != 230) { 185 // Authentication failed. 186 throw new IOException("Proxy authentication failed"); 187 } 188 } 189 communication.sendFTPCommand("SITE " + host + ":" + port); 190 } else if (style == STYLE_OPEN_COMMAND) { 191 communication.sendFTPCommand("OPEN " + host + ":" + port); 192 } 193 return socketConnection; 194 } 195 196 public FTPConnection connectForDataTransferChannel(String host, int port) 197 throws IOException { 198 Socket socket = new Socket(host, port); 199 return new SocketConnection(socket); 200 } 201 202 }