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]>

Reply via email to