Hi,
since HttpClient.java from the slide client library is missing proxy
support for ssl connections, I had to add it myself. Here is the
patch, perhaps someone else is interested. It is almost a one to one
copy of an example from the JSSE reference guide. A slight
modification can also be found at
http://www.javaworld.com/javaworld/javatips/jw-javatip111.html?)
Regards,
Ingo
Index: src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java
===================================================================
RCS file:
/home/cvspublic/jakarta-slide/src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java,v
retrieving revision 1.15
diff -u -r1.15 HttpClient.java
--- src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java 24 Sep 2002
12:41:50 -0000 1.15
+++ src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java 9 Oct 2002
+14:35:17 -0000
@@ -1,5 +1,5 @@
/*
- * $Header:
/home/cvspublic/jakarta-slide/src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java,v
1.15 2002/09/24 12:41:50 juergen Exp $
+ * $Header:
+/home/cvs/jakarta-slide/src/webdav/client/src/org/apache/commons/httpclient/HttpClient.java,v
+ 1.15 2002/09/24 12:41:50 juergen Exp $
* $Revision: 1.15 $
* $Date: 2002/09/24 12:41:50 $
*
@@ -63,6 +63,7 @@
package org.apache.commons.httpclient;
+import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -818,14 +819,46 @@
Class sslFactoryClass =
Class.forName("javax.net.ssl.SSLSocketFactory");
Method getDefaultMethod =
sslFactoryClass.getMethod("getDefault", new Class[0]) ;
Object sslSocketFactory = getDefaultMethod.invoke(null,null);
- Class[] paramClass = new Class[2];
- paramClass[0] = String.class;
- paramClass[1] = int.class;
- Method createSocketMethod =
sslSocketFactory.getClass().getMethod("createSocket",paramClass);
- Object[] param = new Object[2];
- param[0] = this.sessionHost;
- param[1] = new Integer(this.sessionPort);
- socket = (Socket)
createSocketMethod.invoke(sslSocketFactory,param);
+
+ // Add proxy support for https
+ String tunnelHost = System.getProperty(
+ "https.proxyHost");
+ if (tunnelHost != null) {
+ /*
+ * Set up a socket to do tunneling through the proxy.
+ * Start it off as a regular socket, then layer SSL
+ * over the top of it.
+ */
+ int tunnelPort = Integer.parseInt(
+ System.getProperty("https.proxyPort", "443"));
+ Socket tunnel = new Socket(tunnelHost, tunnelPort);
+ doTunnelHandshake(tunnel,
+ sessionHost, sessionPort);
+ Class[] paramClass = new Class[4];
+ paramClass[0] = Socket.class;
+ paramClass[1] = String.class;
+ paramClass[2] = int.class;
+ paramClass[3] = boolean.class;
+ Method createSocketMethod =
+sslSocketFactory.getClass().getMethod("createSocket", paramClass);
+ Object[] param = new Object[4];
+ param[0] = tunnel;
+ param[1] = sessionHost;
+ param[2] = new Integer(sessionPort);
+ param[3] = Boolean.TRUE;
+ socket = (Socket)
+createSocketMethod.invoke(sslSocketFactory, param);
+ Method startHandshakeMethod =
+socket.getClass().getMethod("startHandshake", null);
+ startHandshakeMethod.setAccessible(true);
+ startHandshakeMethod.invoke(socket, null);
+ } else {
+ Class[] paramClass = new Class[2];
+ paramClass[0] = String.class;
+ paramClass[1] = int.class;
+ Method createSocketMethod =
+sslSocketFactory.getClass().getMethod("createSocket",paramClass);
+ Object[] param = new Object[2];
+ param[0] = this.sessionHost;
+ param[1] = new Integer(this.sessionPort);
+ socket = (Socket)
+createSocketMethod.invoke(sslSocketFactory,param);
+ }
} else {
socket = new Socket
@@ -1261,6 +1294,85 @@
}
}
+ /*
+ * Tell our tunnel where we want to CONNECT, and look for the
+ * right reply. Throw IOException if anything goes wrong.
+ */
+ private void doTunnelHandshake(Socket tunnel, String host, int port)
+ throws IOException {
+ OutputStream out = tunnel.getOutputStream();
+ String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"
+ + "User-Agent: "
+ + sun.net.www.protocol.http.HttpURLConnection.userAgent
+ + "\r\n\r\n";
+ byte b[];
+ try {
+ /*
+ * We really do want ASCII7 -- the http protocol doesn't change
+ * with locale.
+ */
+ b = msg.getBytes("ASCII7");
+ } catch (UnsupportedEncodingException ignored) {
+ /*
+ * If ASCII7 isn't there, something serious is wrong, but
+ * Paranoia Is Good (tm)
+ */
+ b = msg.getBytes();
+ }
+ out.write(b);
+ out.flush();
+
+ /*
+ * We need to store the reply so we can create a detailed
+ * error message to the user.
+ */
+ byte reply[] = new byte[200];
+ int replyLen = 0;
+ int newlinesSeen = 0;
+ boolean headerDone = false; /* Done on first newline */
+
+ InputStream in = tunnel.getInputStream();
+ boolean error = false;
+
+ while (newlinesSeen < 2) {
+ int i = in.read();
+ if (i < 0) {
+ throw new IOException("Unexpected EOF from proxy");
+ }
+ if (i == '\n') {
+ headerDone = true;
+ ++newlinesSeen;
+ } else if (i != '\r') {
+ newlinesSeen = 0;
+ if (!headerDone && replyLen < reply.length) {
+ reply[replyLen++] = (byte) i;
+ }
+ }
+ }
+
+ /*
+ * Converting the byte array to a string is slightly wasteful
+ * in the case where the connection was successful, but it's
+ * insignificant compared to the network overhead.
+ */
+ String replyStr;
+ try {
+ replyStr = new String(reply, 0, replyLen, "ASCII7");
+ } catch (UnsupportedEncodingException ignored) {
+ replyStr = new String(reply, 0, replyLen);
+ }
+
+ /* We check for Connection Established (works with HTTP/1.0 and 1.1) */
+ //if (!replyStr.startsWith("HTTP/1.0 200")) {
+ if(replyStr.toLowerCase().indexOf("200 connection established") == -1) {
+ throw new IOException("Unable to tunnel through "
+ + tunnel.getInetAddress().getHostName()
+ + ":" + tunnel.getPort()
+ + ". Proxy returns \"" + replyStr + "\"");
+ }
+
+ /* tunneling Handshake was successful! */
+ }
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>