Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 43756 invoked from network); 20 Jun 2006 15:14:52 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 20 Jun 2006 15:14:52 -0000 Received: (qmail 19910 invoked by uid 500); 20 Jun 2006 15:14:52 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 19817 invoked by uid 500); 20 Jun 2006 15:14:51 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 19803 invoked by uid 99); 20 Jun 2006 15:14:51 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 20 Jun 2006 08:14:51 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 20 Jun 2006 08:14:50 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 6C8311A9844; Tue, 20 Jun 2006 08:14:30 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r415701 - in /incubator/harmony/enhanced/classlib/trunk/modules/luni/src: main/java/org/apache/harmony/luni/internal/net/www/protocol/http/ test/java/org/apache/harmony/tests/internal/net/www/protocol/http/ Date: Tue, 20 Jun 2006 15:14:29 -0000 To: harmony-commits@incubator.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060620151430.6C8311A9844@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: tellison Date: Tue Jun 20 08:14:29 2006 New Revision: 415701 URL: http://svn.apache.org/viewvc?rev=415701&view=rev Log: Apply patch HARMONY-624 ([classlib][luni] HttpURLConnection does not send proxy authorization credentials) Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java?rev=415701&r1=415700&r2=415701&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java Tue Jun 20 08:14:29 2006 @@ -74,6 +74,8 @@ private InputStream uis; + protected Socket socket; + OutputStream socketOut; OutputStream cacheOut; @@ -582,23 +584,11 @@ } if (socket == null) { // make direct connection - socket = getHTTPConnection( - new InetSocketAddress(getHostName(), getHostPort())); + socket = getHTTPConnection(null); } socket.setSoTimeout(getReadTimeout()); + setUpTransportIO(socket); connected = true; - socketOut = socket.getOutputStream(); - is = new BufferedInputStream(socket.getInputStream()); - } - - /** - * Returns connected socket to be used for this HTTP connection. - * TODO: implement persistent connections. - */ - protected Socket getHTTPConnection(SocketAddress address) throws IOException { - Socket socket = new Socket(); - socket.connect(address, getConnectTimeout()); - return socket; } /** @@ -607,18 +597,35 @@ */ protected Socket getHTTPConnection(Proxy proxy) throws IOException { Socket socket; - if (proxy.type() == Proxy.Type.HTTP) { - socket = getHTTPConnection(proxy.address()); + if (proxy == null || proxy.type() == Proxy.Type.DIRECT) { + this.proxy = null; // not using proxy + socket = new Socket(); + socket.connect( + new InetSocketAddress(getHostName(), getHostPort()), + getConnectTimeout()); + } else if (proxy.type() == Proxy.Type.HTTP) { + socket = new Socket(); + socket.connect(proxy.address(), getConnectTimeout()); } else { - // using DIRECT or SOCKS proxy + // using SOCKS proxy socket = new Socket(proxy); socket.connect( - new InetSocketAddress(url.getHost(), url.getPort()), + new InetSocketAddress(getHostName(), getHostPort()), getConnectTimeout()); } return socket; } + /** + * Sets up the data streams used to send request[s] and read response[s]. + * @param socket socket to be used for connection + */ + protected void setUpTransportIO(Socket socket) throws IOException { + this.socket = socket; + socketOut = socket.getOutputStream(); + is = new BufferedInputStream(socket.getInputStream()); + } + // Tries to get head and body from cache, return true if has got this time or // already got before private boolean getFromCache() throws IOException { @@ -675,7 +682,7 @@ } } - void endRequest() throws IOException { + protected void endRequest() throws IOException { if (os != null) { os.close(); } @@ -990,7 +997,7 @@ return result.toString(); } - private String requestString() { + protected String requestString() { if (usingProxy() || proxyName != null) { return url.toString(); } @@ -1351,7 +1358,7 @@ /** * Answer whether the connection should use a proxy server. - * + * * Need to check both proxy* and http.proxy* because of change between JDK * 1.0 and JDK 1.1 */ @@ -1362,7 +1369,7 @@ /** * Handles an HTTP request along with its redirects and authentication */ - void doRequest() throws IOException { + protected void doRequest() throws IOException { // do nothing if we've already sent the request if (sentRequest) { // If necessary, finish the request by @@ -1384,48 +1391,58 @@ if (!sendRequest()) { return; } - - // authorization failed ? - if (responseCode == HTTP_UNAUTHORIZED) { // keep asking for + // proxy authorization failed ? + if (responseCode == HTTP_PROXY_AUTH) { + if (!usingProxy()) { + throw new IOException("Received HTTP_PROXY_AUTH (407) " + +"code while not using proxy"); + } // username/password // until authorized - String challenge = resHeader.get("WWW-Authenticate"); + String challenge = resHeader.get("Proxy-Authenticate"); if (challenge == null) { - break; - } - int idx = challenge.indexOf(" "); - String scheme = challenge.substring(0, idx); - int realm = challenge.indexOf("realm=\"") + 7; - String prompt = null; - if (realm != -1) { - int end = challenge.indexOf('"', realm); - if (end != -1) { - prompt = challenge.substring(realm, end); - } + throw new IOException( + "Received authentication challenge is null."); } - - // the following will use the user-defined authenticator to get - // the password - PasswordAuthentication pa = Authenticator - .requestPasswordAuthentication(getHostAddress(), - getHostPort(), url.getProtocol(), prompt, - scheme); - if (pa == null) { + // drop everything and reconnect, might not be required for + // HTTP/1.1 + endRequest(); + closeSocket(); + connected = false; + String credentials = getAuthorizationCredentials(challenge); + if (credentials == null) { + // could not find credentials, end request cicle break; } + // set up the authorization credentials + setRequestProperty("Proxy-Authorization", credentials); + // continue to send request + continue; + } + // www authorization failed ? + if (responseCode == HTTP_UNAUTHORIZED) { // keep asking for + // username/password + // until authorized + String challenge = resHeader.get("WWW-Authenticate"); + if (challenge == null) { + throw new IOException( + "Received authentication challenge is null."); + } // drop everything and reconnect, might not be required for // HTTP/1.1 endRequest(); closeSocket(); connected = false; - // base64 encode the username and password - byte[] bytes = (pa.getUserName() + ":" + new String(pa - .getPassword())).getBytes("ISO8859_1"); - String encoded = Base64.encode(bytes, "ISO8859_1"); - setRequestProperty("Authorization", scheme + " " + encoded); + String credentials = getAuthorizationCredentials(challenge); + if (credentials == null) { + // could not find credentials, end request cicle + break; + } + // set up the authorization credentials + setRequestProperty("Authorization", credentials); + // continue to send request continue; } - // See if there is a server redirect to the URL, but only handle 1 // level of // URL redirection from the server to avoid being caught in an @@ -1434,7 +1451,8 @@ if ((responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM || responseCode == HTTP_MOVED_TEMP - || responseCode == HTTP_SEE_OTHER || responseCode == HTTP_USE_PROXY) + || responseCode == HTTP_SEE_OTHER + || responseCode == HTTP_USE_PROXY) && os == null) { if (++redirect > 4) { @@ -1466,13 +1484,43 @@ } } } - break; } - // Cache the content stream and read the first chunked header getContentStream(); } + + // Returns the authorization credentials on the base of + // provided authorization challenge + private String getAuthorizationCredentials(String challenge) + throws IOException { + + int idx = challenge.indexOf(" "); + String scheme = challenge.substring(0, idx); + int realm = challenge.indexOf("realm=\"") + 7; + String prompt = null; + if (realm != -1) { + int end = challenge.indexOf('"', realm); + if (end != -1) + prompt = challenge.substring(realm, end); + } + // The following will use the user-defined authenticator to get + // the password + PasswordAuthentication pa = Authenticator + .requestPasswordAuthentication(getHostAddress(), + getHostPort(), url.getProtocol(), prompt, + scheme); + if (pa == null) { + // could not retrieve the credentials + return null; + } + // base64 encode the username and password + byte[] bytes = (pa.getUserName() + ":" + + new String(pa.getPassword())).getBytes("ISO8859_1"); + String encoded = Base64.encode(bytes, "ISO8859_1"); + return scheme + " " + encoded; + } + private void setProxy(String proxy) { int index = proxy.indexOf(':'); Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java?rev=415701&r1=415700&r2=415701&view=diff ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java (original) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/tests/internal/net/www/protocol/http/HttpURLConnectionTest.java Tue Jun 20 08:14:29 2006 @@ -17,11 +17,14 @@ package org.apache.harmony.tests.internal.net.www.protocol.http; import java.io.IOException; +import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.ProxySelector; import java.net.ServerSocket; +import java.net.Socket; import java.net.SocketAddress; import java.net.SocketTimeoutException; import java.net.URI; @@ -70,6 +73,43 @@ } } + static class MockProxyServer extends MockServer { + + boolean acceptedAuthorizedRequest; + + public MockProxyServer(String name) throws Exception { + super(name); + } + + public void run() { + try { + Socket socket = serverSocket.accept(); + socket.setSoTimeout(1000); + byte[] buff = new byte[1024]; + int num = socket.getInputStream().read(buff); + socket.getOutputStream().write(( + "HTTP/1.0 407 Proxy authentication required\n" + + "Proxy-authenticate: Basic realm=\"remotehost\"\n\n") + .getBytes()); + num = socket.getInputStream().read(buff); + if (num == -1) { + // this connection was closed, create new one: + socket = serverSocket.accept(); + socket.setSoTimeout(1000); + num = socket.getInputStream().read(buff); + } + String request = new String(buff, 0, num); + acceptedAuthorizedRequest = + request.toLowerCase().indexOf("proxy-authorization:") > 0; + if (acceptedAuthorizedRequest) { + socket.getOutputStream().write(( + "HTTP/1.1 200 OK\n\n").getBytes()); + } + } catch (IOException e) { + } + } + } + /** * ProxySelector implementation used in the test. */ @@ -212,4 +252,39 @@ ProxySelector.setDefault(defPS); } } + + public void testProxyAuthorization() throws Exception { + // Set up test Authenticator + Authenticator.setDefault(new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication( + "user", "password".toCharArray()); + } + }); + + try { + MockProxyServer proxy = new MockProxyServer("ProxyServer"); + + URL url = new URL("http://remotehost:55555/requested.data"); + HttpURLConnection connection = + (HttpURLConnection) url.openConnection( + new Proxy(Proxy.Type.HTTP, + new InetSocketAddress("localhost", proxy.port()))); + connection.setConnectTimeout(1000); + connection.setReadTimeout(1000); + + proxy.start(); + + connection.connect(); + assertEquals("unexpected response code", + 200, connection.getResponseCode()); + proxy.join(); + assertTrue("Connection did not send proxy authorization request", + proxy.acceptedAuthorizedRequest); + } finally { + // remove previously set authenticator + Authenticator.setDefault(null); + } + } + }