X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2FHTTP.java;h=84e5abb7c01f6472818ba185450cac423505385b;hb=9d07963a45f2147a62d8897e9c4245c224d98ccb;hp=fed6e6e852931746412e214e66e1719884663d6c;hpb=6b010667b40641fdb82925e56466f847f721ef1f;p=org.ibex.core.git diff --git a/src/org/xwt/HTTP.java b/src/org/xwt/HTTP.java index fed6e6e..84e5abb 100644 --- a/src/org/xwt/HTTP.java +++ b/src/org/xwt/HTTP.java @@ -51,12 +51,12 @@ public class HTTP { */ Semaphore okToRecieve = null; + /** true iff this is the first request to be made on this socket */ + boolean firstRequest = true; + /** cache for resolveAndCheckIfFirewalled() */ static Hashtable resolvedHosts = new Hashtable(); - /** if any request encounters an IOException, the entire HTTP connection is invalidated */ - boolean invalid = false; - /** true iff we are allowed to skip the resolve check (only allowed when we're downloading the PAC script) */ boolean skipResolveCheck = false; @@ -88,12 +88,11 @@ public class HTTP { Semaphore blockOn = null; Semaphore releaseMe = null; synchronized(this) { - if (invalid) throw new HTTPException("connection failed on a previous pipelined call"); try { connect(); sendRequest(contentType, content); } catch (IOException e) { - invalid = true; + reset(); throw e; } blockOn = okToRecieve; @@ -104,12 +103,18 @@ public class HTTP { boolean doRelease = true; try { if (blockOn != null) blockOn.block(); - if (invalid) throw new HTTPException("connection failed on a previous pipelined call"); + + // previous call wrecked the socket connection, but we already sent our request, so we can't just retry -- + // this could cause the server to receive the request twice, which could be bad (think of the case where the + // server call causes Amazon.com to ship you an item with one-click purchasing). + if (sock == null) + throw new HTTPException("a previous pipelined call messed up the socket"); Hashtable h = in == null ? null : parseHeaders(in); if (h == null) { + if (firstRequest) throw new HTTPException("server closed the socket with no response"); // sometimes the server chooses to close the stream between requests - in = null; sock = null; + reset(); releaseMe.release(); return makeRequest(contentType, content); } @@ -123,7 +128,7 @@ public class HTTP { if (h.get("HTTP").equals("1.0") && h.get("content-length") == null) { if (Log.on) Log.log(this, "proxy returned an HTTP/1.0 reply with no content-length..."); - in = null; sock = null; + reset(); } else { int cl = h.get("content-length") == null ? -1 : Integer.parseInt(h.get("content-length").toString()); new HTTPInputStream(in, cl, releaseMe).close(); @@ -145,7 +150,7 @@ public class HTTP { } - } catch (IOException e) { invalid = true; throw e; + } catch (IOException e) { reset(); throw e; } finally { if (doRelease) releaseMe.release(); } } @@ -176,18 +181,8 @@ public class HTTP { return; } catch (UnknownHostException uhe) { } - if (Platform.detectProxy() == null) throw new HTTPException("could not resolve hostname \"" + host + "\" and no proxy configured"); - if (Log.on) Log.log(this, " could not resolve host " + host + "; using xmlrpc.xwt.org to ensure security"); - try { - JS.Array args = new JS.Array(); - args.addElement(host); - Object ret = new XMLRPC("http://xmlrpc.xwt.org/RPC2/", "dns.resolve").call(args); - if (ret == null || !(ret instanceof String)) throw new Exception(" xmlrpc.xwt.org returned non-String: " + ret); - resolvedHosts.put(host, ret); - return; - } catch (Throwable e) { - throw new HTTPException("exception while attempting to use xmlrpc.xwt.org to resolve " + host + ": " + e); - } + if (Platform.detectProxy() == null) + throw new HTTPException("could not resolve hostname \"" + host + "\" and no proxy configured"); } @@ -281,11 +276,11 @@ public class HTTP { } /** executes the PAC script and dispatches a call to one of the other attempt methods based on the result */ - public Socket attemptPAC(org.xwt.js.JS.Callable pacFunc) { + public Socket attemptPAC(org.xwt.js.JSCallable pacFunc) { if (Log.verbose) Log.log(this, "evaluating PAC script"); String pac = null; try { - org.xwt.js.JS.Array args = new org.xwt.js.JS.Array(); + org.xwt.js.JSArray args = new org.xwt.js.JSArray(); args.addElement(url.toString()); args.addElement(url.getHost()); Object obj = pacFunc.call(args); @@ -323,6 +318,10 @@ public class HTTP { // Everything Else //////////////////////////////////////////////////////////////////////////// private synchronized void connect() throws IOException { + if (originalUrl.equals("stdio:")) { + in = new BufferedInputStream(System.in); + return; + } if (sock != null) { if (in == null) in = new BufferedInputStream(sock.getInputStream()); return; @@ -354,10 +353,15 @@ public class HTTP { if (Log.verbose) Log.log(this, "creating HTTP object for connection to " + host + ":" + port); Proxy pi = Platform.detectProxy(); - if (sock == null && pi != null && pi.proxyAutoConfigFunction != null) sock = attemptPAC(pi.proxyAutoConfigFunction); - if (sock == null && pi != null && ssl && pi.httpsProxyHost != null) sock = attemptHttpProxy(pi.httpsProxyHost, pi.httpsProxyPort); - if (sock == null && pi != null && pi.httpProxyHost != null) sock = attemptHttpProxy(pi.httpProxyHost, pi.httpProxyPort); - if (sock == null && pi != null && pi.socksProxyHost != null) sock = attemptSocksProxy(pi.socksProxyHost, pi.socksProxyPort); + OUTER: do { + if (pi != null) { + for(int i=0; i epoch. + time *= 10000; // tenths of a microsecond. + // convert to little-endian byte array. + byte[] timestamp = new byte[8]; + for (int i = 0; i < 8; i++) { + timestamp[i] = (byte) time; + time >>>= 8; + } + byte[] blob = new byte[blobSignature.length + reserved.length + + timestamp.length + clientChallenge.length + + unknown1.length + targetInformation.length + + unknown2.length]; + int offset = 0; + System.arraycopy(blobSignature, 0, blob, offset, blobSignature.length); + offset += blobSignature.length; + System.arraycopy(reserved, 0, blob, offset, reserved.length); + offset += reserved.length; + System.arraycopy(timestamp, 0, blob, offset, timestamp.length); + offset += timestamp.length; + System.arraycopy(clientChallenge, 0, blob, offset, + clientChallenge.length); + offset += clientChallenge.length; + System.arraycopy(unknown1, 0, blob, offset, unknown1.length); + offset += unknown1.length; + System.arraycopy(targetInformation, 0, blob, offset, + targetInformation.length); + offset += targetInformation.length; + System.arraycopy(unknown2, 0, blob, offset, unknown2.length); + return blob; + } + + /** + * Calculates the HMAC-MD5 hash of the given data using the specified + * hashing key. + * + * @param data The data for which the hash will be calculated. + * @param key The hashing key. + * + * @return The HMAC-MD5 hash of the given data. + */ + private static byte[] hmacMD5(byte[] data, byte[] key) throws Exception { + byte[] ipad = new byte[64]; + byte[] opad = new byte[64]; + for (int i = 0; i < 64; i++) { + ipad[i] = (byte) 0x36; + opad[i] = (byte) 0x5c; + } + for (int i = key.length - 1; i >= 0; i--) { + ipad[i] ^= key[i]; + opad[i] ^= key[i]; + } + byte[] content = new byte[data.length + 64]; + System.arraycopy(ipad, 0, content, 0, 64); + System.arraycopy(data, 0, content, 64, data.length); + MD5Digest md5 = new MD5Digest(); + md5.update(content, 0, content.length); + data = new byte[md5.getDigestSize()]; + md5.doFinal(data, 0); + content = new byte[data.length + 64]; + System.arraycopy(opad, 0, content, 0, 64); + System.arraycopy(data, 0, content, 64, data.length); + md5 = new MD5Digest(); + md5.update(content, 0, content.length); + byte[] ret = new byte[md5.getDigestSize()]; + md5.doFinal(ret, 0); + return ret; + } + + /** + * Creates a DES encryption key from the given key material. + * + * @param bytes A byte array containing the DES key material. + * @param offset The offset in the given byte array at which + * the 7-byte key material starts. + * + * @return A DES encryption key created from the key material + * starting at the specified offset in the given byte array. + */ + /* + private static Key createDESKey(byte[] bytes, int offset) { + byte[] keyBytes = new byte[7]; + System.arraycopy(bytes, offset, keyBytes, 0, 7); + byte[] material = new byte[8]; + material[0] = keyBytes[0]; + material[1] = (byte) (keyBytes[0] << 7 | (keyBytes[1] & 0xff) >>> 1); + material[2] = (byte) (keyBytes[1] << 6 | (keyBytes[2] & 0xff) >>> 2); + material[3] = (byte) (keyBytes[2] << 5 | (keyBytes[3] & 0xff) >>> 3); + material[4] = (byte) (keyBytes[3] << 4 | (keyBytes[4] & 0xff) >>> 4); + material[5] = (byte) (keyBytes[4] << 3 | (keyBytes[5] & 0xff) >>> 5); + material[6] = (byte) (keyBytes[5] << 2 | (keyBytes[6] & 0xff) >>> 6); + material[7] = (byte) (keyBytes[6] << 1); + oddParity(material); + return new SecretKeySpec(material, "DES"); + } + */ + + /** + * Applies odd parity to the given byte array. + * + * @param bytes The data whose parity bits are to be adjusted for + * odd parity. + */ + private static void oddParity(byte[] bytes) { + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + boolean needsParity = (((b >>> 7) ^ (b >>> 6) ^ (b >>> 5) ^ + (b >>> 4) ^ (b >>> 3) ^ (b >>> 2) ^ + (b >>> 1)) & 0x01) == 0; + if (needsParity) { + bytes[i] |= (byte) 0x01; + } else { + bytes[i] &= (byte) 0xfe; + } + } + } + + } + } }