/* * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.net.www.protocol.http; import java.net.URL;import java.net.URLConnection;import java.net.ProtocolException;import java.net.HttpRetryException;import java.net.PasswordAuthentication;import java.net.Authenticator;import java.net.InetAddress;import java.net.UnknownHostException;import java.net.SocketTimeoutException;import java.net.Proxy;import java.net.ProxySelector;import java.net.URI;import java.net.InetSocketAddress;import java.net.CookieHandler;import java.net.ResponseCache;import java.net.CacheResponse;import java.net.SecureCacheResponse;import java.net.CacheRequest;import java.net.Authenticator.RequestorType;import java.io.*;import java.util.Date;import java.util.Map;import java.util.List;import java.util.Locale;import java.util.StringTokenizer;import java.util.Iterator;import java.util.HashSet;import java.util.HashMap;import java.util.Set;import sun.net.*;import sun.net.www.*;import sun.net.www.http.HttpClient;import sun.net.www.http.PosterOutputStream;import sun.net.www.http.ChunkedInputStream;import sun.net.www.http.ChunkedOutputStream;import sun.util.logging.PlatformLogger;import java.text.SimpleDateFormat;import java.util.TimeZone;import java.net.MalformedURLException;import java.nio.ByteBuffer;import static sun.net.www.protocol.http.AuthScheme.BASIC;import static sun.net.www.protocol.http.AuthScheme.DIGEST;import static sun.net.www.protocol.http.AuthScheme.NTLM;import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;import static sun.net.www.protocol.http.AuthScheme.KERBEROS;import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; /** * A class to represent an HTTP connection to a remote object. */ public class HttpURLConnection extends java.net.HttpURLConnection { static String HTTP_CONNECT = "CONNECT"; static final String version; public static final String userAgent; /* max # of allowed re-directs */ static final int defaultmaxRedirects = 20; static final int maxRedirects; /* Not all servers support the (Proxy)-Authentication-Info headers. * By default, we don't require them to be sent */ static final boolean validateProxy; static final boolean validateServer; private StreamingOutputStream strOutputStream; private final static String RETRY_MSG1 = "cannot retry due to proxy authentication, in streaming mode"; private final static String RETRY_MSG2 = "cannot retry due to server authentication, in streaming mode"; private final static String RETRY_MSG3 = "cannot retry due to redirection, in streaming mode"; /* * System properties related to error stream handling: * * sun.net.http.errorstream.enableBuffering = <boolean> * * With the above system property set to true (default is false), * when the response code is >=400, the HTTP handler will try to * buffer the response body (up to a certain amount and within a * time limit). Thus freeing up the underlying socket connection * for reuse. The rationale behind this is that usually when the * server responds with a >=400 error (client error or server * error, such as 404 file not found), the server will send a * small response body to explain who to contact and what to do to * recover. With this property set to true, even if the * application doesn't call getErrorStream(), read the response * body, and then call close(), the underlying socket connection * can still be kept-alive and reused. The following two system * properties provide further control to the error stream * buffering behaviour. * * sun.net.http.errorstream.timeout = <int> * the timeout (in millisec) waiting the error stream * to be buffered; default is 300 ms * * sun.net.http.errorstream.bufferSize = <int> * the size (in bytes) to use for the buffering the error stream; * default is 4k */ /* Should we enable buffering of error streams? */ private static boolean enableESBuffer = false; /* timeout waiting for read for buffered error stream; */ private static int timeout4ESBuffer = 0; /* buffer size for buffered error stream; */ private static int bufSize4ES = 0; /* * Restrict setting of request headers through the public api * consistent with JavaScript XMLHttpRequest2 with a few * exceptions. Disallowed headers are silently ignored for * backwards compatibility reasons rather than throwing a * SecurityException. For example, some applets set the * Host header since old JREs did not implement HTTP 1.1. * Additionally, any header starting with Sec- is * disallowed. * * The following headers are allowed for historical reasons: * * Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date, * Referer, TE, User-Agent, headers beginning with Proxy-. * * The following headers are allowed in a limited form: * * Connection: close * * See http://www.w3.org/TR/XMLHttpRequest2. */ private static final boolean allowRestrictedHeaders; private static final Set<String> restrictedHeaderSet; private static final String[] restrictedHeaders = { /* Restricted by XMLHttpRequest2 */ //"Accept-Charset", //"Accept-Encoding", "Access-Control-Request-Headers", "Access-Control-Request-Method", "Connection", /* close is allowed */ "Content-Length", //"Cookie", //"Cookie2", "Content-Transfer-Encoding", //"Date", //"Expect", "Host", "Keep-Alive", "Origin", // "Referer", // "TE", "Trailer", "Transfer-Encoding", "Upgrade", //"User-Agent", "Via" }; static { maxRedirects = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "http.maxRedirects", defaultmaxRedirects)).intValue(); version = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.version")); String agent = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("http.agent")); if (agent == null) { agent = "Java/"+version; } else { agent = agent + " Java/"+version; } userAgent = agent; validateProxy = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "http.auth.digest.validateProxy")).booleanValue(); validateServer = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "http.auth.digest.validateServer")).booleanValue(); enableESBuffer = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.http.errorstream.enableBuffering")).booleanValue(); timeout4ESBuffer = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.http.errorstream.timeout", 300)).intValue(); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } bufSize4ES = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.http.errorstream.bufferSize", 4096)).intValue(); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default } allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.http.allowRestrictedHeaders"))).booleanValue(); if (!allowRestrictedHeaders) { restrictedHeaderSet = new HashSet<String>(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { restrictedHeaderSet.add(restrictedHeaders[i].toLowerCase()); } } else { restrictedHeaderSet = null; } } static final String httpVersion = "HTTP/1.1"; static final String acceptString = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"; // the following http request headers should NOT have their values // returned for security reasons. private static final String[] EXCLUDE_HEADERS = { "Proxy-Authorization", "Authorization" }; // also exclude system cookies when any might be set private static final String[] EXCLUDE_HEADERS2= { "Proxy-Authorization", "Authorization", "Cookie", "Cookie2" }; protected HttpClient http; protected Handler handler; protected Proxy instProxy; private CookieHandler cookieHandler; private ResponseCache cacheHandler; // the cached response, and cached response headers and body protected CacheResponse cachedResponse; private MessageHeader cachedHeaders; private InputStream cachedInputStream; /* output stream to server */ protected PrintStream ps = null; /* buffered error stream */ private InputStream errorStream = null; /* User set Cookies */ private boolean setUserCookies = true; private String userCookies = null; private String userCookies2 = null; /* We only have a single static authenticator for now. * REMIND: backwards compatibility with JDK 1.1. Should be * eliminated for JDK 2.0. */ private static HttpAuthenticator defaultAuth; /* all the headers we send * NOTE: do *NOT* dump out the content of 'requests' in the * output or stacktrace since it may contain security-sensitive * headers such as those defined in EXCLUDE_HEADERS. */ private MessageHeader requests; /* The following two fields are only used with Digest Authentication */ String domain; /* The list of authentication domains */ DigestAuthentication.Parameters digestparams; /* Current credentials in use */ AuthenticationInfo currentProxyCredentials = null; AuthenticationInfo currentServerCredentials = null; boolean needToCheck = true; private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */ private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */ /* try auth without calling Authenticator. Used for transparent NTLM authentication */ private boolean tryTransparentNTLMServer = true; private boolean tryTransparentNTLMProxy = true; /* Used by Windows specific code */ private Object authObj; /* Set if the user is manually setting the Authorization or Proxy-Authorization headers */ boolean isUserServerAuth; boolean isUserProxyAuth; String serverAuthKey, proxyAuthKey; /* Progress source */ protected ProgressSource pi; /* all the response headers we get back */ private MessageHeader responses; /* the stream _from_ the server */ private InputStream inputStream = null; /* post stream _to_ the server, if any */ private PosterOutputStream poster = null; /* Indicates if the std. request headers have been set in requests. */ private boolean setRequests=false; /* Indicates whether a request has already failed or not */ private boolean failedOnce=false; /* Remembered Exception, we will throw it again if somebody calls getInputStream after disconnect */ private Exception rememberedException = null; /* If we decide we want to reuse a client, we put it here */ private HttpClient reuseClient = null; /* Tunnel states */ enum TunnelState { /* No tunnel */ NONE, /* Setting up a tunnel */ SETUP, /* Tunnel has been successfully setup */ TUNNELING } private TunnelState tunnelState = TunnelState.NONE; /* Redefine timeouts from java.net.URLConnection as we need -1 to mean * not set. This is to ensure backward compatibility. */ private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT; private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT; /* Logging support */ private static final PlatformLogger logger = PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); /* * privileged request password authentication * */ private static PasswordAuthentication privilegedRequestPasswordAuthentication( final String host, final InetAddress addr, final int port, final String protocol, final String prompt, final String scheme, final URL url, final RequestorType authType) { return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<PasswordAuthentication>() { public PasswordAuthentication run() { if (logger.isLoggable(PlatformLogger.FINEST)) { logger.finest("Requesting Authentication: host =" + host + " url = " + url); } PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( host, addr, port, protocol, prompt, scheme, url, authType); if (logger.isLoggable(PlatformLogger.FINEST)) { logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); } return pass; } }); } private boolean isRestrictedHeader(String key, String value) { if (allowRestrictedHeaders) { return false; } key = key.toLowerCase(); if (restrictedHeaderSet.contains(key)) { /* * Exceptions to restricted headers: * * Allow "Connection: close". */ if (key.equals("connection") && value.equalsIgnoreCase("close")) { return false; } return true; } else if (key.startsWith("sec-")) { return true; } return false; } /* * Checks the validity of http message header and whether the header * is restricted and throws IllegalArgumentException if invalid or * restricted. */ private boolean isExternalMessageHeaderAllowed(String key, String value) { checkMessageHeader(key, value); if (!isRestrictedHeader(key, value)) { return true; } return false; } /* Logging support */ public static PlatformLogger getHttpLogger() { return logger; } /* Used for Windows NTLM implementation */ public Object authObj() { return authObj; } public void authObj(Object authObj) { this.authObj = authObj; } /* * checks the validity of http message header and throws * IllegalArgumentException if invalid. */ private void checkMessageHeader(String key, String value) { char LF = '\n'; int index = key.indexOf(LF); if (index != -1) { throw new IllegalArgumentException( "Illegal character(s) in message header field: " + key); } else { if (value == null) { return; } index = value.indexOf(LF); while (index != -1) { index++; if (index < value.length()) { char c = value.charAt(index); if ((c==' ') || (c=='\t')) { // ok, check the next occurrence index = value.indexOf(LF, index); continue; } } throw new IllegalArgumentException( "Illegal character(s) in message header value: " + value); } } } /* adds the standard key/val pairs to reqests if necessary & write to * given PrintStream */ private void writeRequests() throws IOException { /* print all message headers in the MessageHeader * onto the wire - all the ones we've set and any * others that have been set */ // send any pre-emptive authentication if (http.usingProxy && tunnelState() != TunnelState.TUNNELING) { setPreemptiveProxyAuthentication(requests); } if (!setRequests) { /* We're very particular about the order in which we * set the request headers here. The order should notLines 1–500 of 3300. Load more
/* * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.net.www.protocol.http; import java.net.URL; import java.net.URLConnection; import java.net.ProtocolException; import java.net.HttpRetryException; import java.net.PasswordAuthentication; import java.net.Authenticator; import java.net.InetAddress; import java.net.UnknownHostException; import java.net.SocketTimeoutException; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; import java.net.InetSocketAddress; import java.net.CookieHandler; import java.net.ResponseCache; import java.net.CacheResponse; import java.net.SecureCacheResponse; import java.net.CacheRequest; import java.net.Authenticator.RequestorType; import java.io.*; import java.util.Date; import java.util.Map; import java.util.List; import java.util.Locale; import java.util.StringTokenizer; import java.util.Iterator; import java.util.HashSet; import java.util.HashMap; import java.util.Set; import sun.net.*; import sun.net.www.*; import sun.net.www.http.HttpClient; import sun.net.www.http.PosterOutputStream; import sun.net.www.http.ChunkedInputStream; import sun.net.www.http.ChunkedOutputStream; import sun.util.logging.PlatformLogger; import java.text.SimpleDateFormat; import java.util.TimeZone; import java.net.MalformedURLException; import java.nio.ByteBuffer; import static sun.net.www.protocol.http.AuthScheme.BASIC; import static sun.net.www.protocol.http.AuthScheme.DIGEST; import static sun.net.www.protocol.http.AuthScheme.NTLM; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; /** * A class to represent an HTTP connection to a remote object. */ public class HttpURLConnection extends java.net.HttpURLConnection { static String HTTP_CONNECT = "CONNECT"; static final String version; public static final String userAgent; /* max # of allowed re-directs */ static final int defaultmaxRedirects = 20; static final int maxRedirects; /* Not all servers support the (Proxy)-Authentication-Info headers. * By default, we don't require them to be sent */ static final boolean validateProxy; static final boolean validateServer; private StreamingOutputStream strOutputStream; private final static String RETRY_MSG1 = "cannot retry due to proxy authentication, in streaming mode"; private final static String RETRY_MSG2 = "cannot retry due to server authentication, in streaming mode"; private final static String RETRY_MSG3 = "cannot retry due to redirection, in streaming mode"; /* * System properties related to error stream handling: * * sun.net.http.errorstream.enableBuffering = <boolean> * * With the above system property set to true (default is false), * when the response code is >=400, the HTTP handler will try to * buffer the response body (up to a certain amount and within a * time limit). Thus freeing up the underlying socket connection * for reuse. The rationale behind this is that usually when the * server responds with a >=400 error (client error or server * error, such as 404 file not found), the server will send a * small response body to explain who to contact and what to do to * recover. With this property set to true, even if the * application doesn't call getErrorStream(), read the response * body, and then call close(), the underlying socket connection * can still be kept-alive and reused. The following two system * properties provide further control to the error stream * buffering behaviour. * * sun.net.http.errorstream.timeout = <int> * the timeout (in millisec) waiting the error stream * to be buffered; default is 300 ms * * sun.net.http.errorstream.bufferSize = <int> * the size (in bytes) to use for the buffering the error stream; * default is 4k */ /* Should we enable buffering of error streams? */ private static boolean enableESBuffer = false; /* timeout waiting for read for buffered error stream; */ private static int timeout4ESBuffer = 0; /* buffer size for buffered error stream; */ private static int bufSize4ES = 0; /* * Restrict setting of request headers through the public api * consistent with JavaScript XMLHttpRequest2 with a few * exceptions. Disallowed headers are silently ignored for * backwards compatibility reasons rather than throwing a * SecurityException. For example, some applets set the * Host header since old JREs did not implement HTTP 1.1. * Additionally, any header starting with Sec- is * disallowed. * * The following headers are allowed for historical reasons: * * Accept-Charset, Accept-Encoding, Cookie, Cookie2, Date, * Referer, TE, User-Agent, headers beginning with Proxy-. * * The following headers are allowed in a limited form: * * Connection: close * * See http://www.w3.org/TR/XMLHttpRequest2. */ private static final boolean allowRestrictedHeaders; private static final Set<String> restrictedHeaderSet; private static final String[] restrictedHeaders = { /* Restricted by XMLHttpRequest2 */ //"Accept-Charset", //"Accept-Encoding", "Access-Control-Request-Headers", "Access-Control-Request-Method", "Connection", /* close is allowed */ "Content-Length", //"Cookie", //"Cookie2", "Content-Transfer-Encoding", //"Date", //"Expect", "Host", "Keep-Alive", "Origin", // "Referer", // "TE", "Trailer", "Transfer-Encoding", "Upgrade", //"User-Agent", "Via" }; static { maxRedirects = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "http.maxRedirects", defaultmaxRedirects)).intValue(); version = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.version")); String agent = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("http.agent")); if (agent == null) { agent = "Java/"+version; } else { agent = agent + " Java/"+version; } userAgent = agent; validateProxy = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "http.auth.digest.validateProxy")).booleanValue(); validateServer = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "http.auth.digest.validateServer")).booleanValue(); enableESBuffer = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.http.errorstream.enableBuffering")).booleanValue(); timeout4ESBuffer = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.http.errorstream.timeout", 300)).intValue(); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } bufSize4ES = java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.http.errorstream.bufferSize", 4096)).intValue(); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default } allowRestrictedHeaders = ((Boolean)java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.http.allowRestrictedHeaders"))).booleanValue(); if (!allowRestrictedHeaders) { restrictedHeaderSet = new HashSet<String>(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { restrictedHeaderSet.add(restrictedHeaders[i].toLowerCase()); } } else { restrictedHeaderSet = null; } } static final String httpVersion = "HTTP/1.1"; static final String acceptString = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"; // the following http request headers should NOT have their values // returned for security reasons. private static final String[] EXCLUDE_HEADERS = { "Proxy-Authorization", "Authorization" }; // also exclude system cookies when any might be set private static final String[] EXCLUDE_HEADERS2= { "Proxy-Authorization", "Authorization", "Cookie", "Cookie2" }; protected HttpClient http; protected Handler handler; protected Proxy instProxy; private CookieHandler cookieHandler; private ResponseCache cacheHandler; // the cached response, and cached response headers and body protected CacheResponse cachedResponse; private MessageHeader cachedHeaders; private InputStream cachedInputStream; /* output stream to server */ protected PrintStream ps = null; /* buffered error stream */ private InputStream errorStream = null; /* User set Cookies */ private boolean setUserCookies = true; private String userCookies = null; private String userCookies2 = null; /* We only have a single static authenticator for now. * REMIND: backwards compatibility with JDK 1.1. Should be * eliminated for JDK 2.0. */ private static HttpAuthenticator defaultAuth; /* all the headers we send * NOTE: do *NOT* dump out the content of 'requests' in the * output or stacktrace since it may contain security-sensitive * headers such as those defined in EXCLUDE_HEADERS. */ private MessageHeader requests; /* The following two fields are only used with Digest Authentication */ String domain; /* The list of authentication domains */ DigestAuthentication.Parameters digestparams; /* Current credentials in use */ AuthenticationInfo currentProxyCredentials = null; AuthenticationInfo currentServerCredentials = null; boolean needToCheck = true; private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */ private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */ /* try auth without calling Authenticator. Used for transparent NTLM authentication */ private boolean tryTransparentNTLMServer = true; private boolean tryTransparentNTLMProxy = true; /* Used by Windows specific code */ private Object authObj; /* Set if the user is manually setting the Authorization or Proxy-Authorization headers */ boolean isUserServerAuth; boolean isUserProxyAuth; String serverAuthKey, proxyAuthKey; /* Progress source */ protected ProgressSource pi; /* all the response headers we get back */ private MessageHeader responses; /* the stream _from_ the server */ private InputStream inputStream = null; /* post stream _to_ the server, if any */ private PosterOutputStream poster = null; /* Indicates if the std. request headers have been set in requests. */ private boolean setRequests=false; /* Indicates whether a request has already failed or not */ private boolean failedOnce=false; /* Remembered Exception, we will throw it again if somebody calls getInputStream after disconnect */ private Exception rememberedException = null; /* If we decide we want to reuse a client, we put it here */ private HttpClient reuseClient = null; /* Tunnel states */ enum TunnelState { /* No tunnel */ NONE, /* Setting up a tunnel */ SETUP, /* Tunnel has been successfully setup */ TUNNELING } private TunnelState tunnelState = TunnelState.NONE; /* Redefine timeouts from java.net.URLConnection as we need -1 to mean * not set. This is to ensure backward compatibility. */ private int connectTimeout = NetworkClient.DEFAULT_CONNECT_TIMEOUT; private int readTimeout = NetworkClient.DEFAULT_READ_TIMEOUT; /* Logging support */ private static final PlatformLogger logger = PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); /* * privileged request password authentication * */ private static PasswordAuthentication privilegedRequestPasswordAuthentication( final String host, final InetAddress addr, final int port, final String protocol, final String prompt, final String scheme, final URL url, final RequestorType authType) { return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<PasswordAuthentication>() { public PasswordAuthentication run() { if (logger.isLoggable(PlatformLogger.FINEST)) { logger.finest("Requesting Authentication: host =" + host + " url = " + url); } PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( host, addr, port, protocol, prompt, scheme, url, authType); if (logger.isLoggable(PlatformLogger.FINEST)) { logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); } return pass; } }); } private boolean isRestrictedHeader(String key, String value) { if (allowRestrictedHeaders) { return false; } key = key.toLowerCase(); if (restrictedHeaderSet.contains(key)) { /* * Exceptions to restricted headers: * * Allow "Connection: close". */ if (key.equals("connection") && value.equalsIgnoreCase("close")) { return false; } return true; } else if (key.startsWith("sec-")) { return true; } return false; } /* * Checks the validity of http message header and whether the header * is restricted and throws IllegalArgumentException if invalid or * restricted. */ private boolean isExternalMessageHeaderAllowed(String key, String value) { checkMessageHeader(key, value); if (!isRestrictedHeader(key, value)) { return true; } return false; } /* Logging support */ public static PlatformLogger getHttpLogger() { return logger; } /* Used for Windows NTLM implementation */ public Object authObj() { return authObj; } public void authObj(Object authObj) { this.authObj = authObj; } /* * checks the validity of http message header and throws * IllegalArgumentException if invalid. */ private void checkMessageHeader(String key, String value) { char LF = '\n'; int index = key.indexOf(LF); if (index != -1) { throw new IllegalArgumentException( "Illegal character(s) in message header field: " + key); } else { if (value == null) { return; } index = value.indexOf(LF); while (index != -1) { index++; if (index < value.length()) { char c = value.charAt(index); if ((c==' ') || (c=='\t')) { // ok, check the next occurrence index = value.indexOf(LF, index); continue; } } throw new IllegalArgumentException( "Illegal character(s) in message header value: " + value); } } } /* adds the standard key/val pairs to reqests if necessary & write to * given PrintStream */ private void writeRequests() throws IOException { /* print all message headers in the MessageHeader * onto the wire - all the ones we've set and any * others that have been set */ // send any pre-emptive authentication if (http.usingProxy && tunnelState() != TunnelState.TUNNELING) { setPreemptiveProxyAuthentication(requests); } if (!setRequests) { /* We're very particular about the order in which we * set the request headers here. The order should not