X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2FHTTP.java;h=10da62b2cb0a42f39eb813f2cef58105a5a149de;hb=a45a8fc2ca7e197f70a1e13ae22d2a49339722f8;hp=146389721469b0c61488fc866e0c91d667643317;hpb=3591b88b94a6bb378af3d4abe6eb5233ce583104;p=org.ibex.core.git diff --git a/src/org/ibex/HTTP.java b/src/org/ibex/HTTP.java index 1463897..10da62b 100644 --- a/src/org/ibex/HTTP.java +++ b/src/org/ibex/HTTP.java @@ -29,6 +29,8 @@ public class HTTP { public static class HTTPException extends IOException { public HTTPException(String s) { super(s); } } + public static HTTP stdio = new HTTP("stdio:"); + // Statics /////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,7 +41,7 @@ public class HTTP { // Instance Data /////////////////////////////////////////////////////////////////////////////////////////////// final String originalUrl; ///< the URL as passed to the original constructor; this is never changed - URL url = null; ///< the URL to connect to; this is munged when the url is parsed */ + String url = null; ///< the URL to connect to; this is munged when the url is parsed */ String host = null; ///< the host to connect to int port = -1; ///< the port to connect on boolean ssl = false; ///< true if SSL (HTTPS) should be used @@ -86,7 +88,7 @@ public class HTTP { // 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) + if (in == null) throw new HTTPException("a previous pipelined call messed up the socket"); Hashtable h = in == null ? null : parseHeaders(in); @@ -268,8 +270,7 @@ public class HTTP { if (Log.verbose) Log.info(this, "evaluating PAC script"); String pac = null; try { - org.ibex.js.JSArray args = new org.ibex.js.JSArray(); - Object obj = pacFunc.call(url.toString(), url.getHost(), null, null, 2); + Object obj = pacFunc.call(url, host, null, null, 2); if (Log.verbose) Log.info(this, " PAC script returned \"" + obj + "\""); pac = obj.toString(); } catch (Throwable e) { @@ -321,18 +322,22 @@ public class HTTP { } if (url.startsWith("https:")) { - this.url = new URL("http" + url.substring(5)); ssl = true; } else if (!url.startsWith("http:")) { - throw new MalformedURLException("HTTP only supports http/https urls"); + throw new IOException("HTTP only supports http/https urls"); + } + if (url.indexOf("://") == -1) throw new IOException("URLs must contain a ://"); + String temphost = url.substring(url.indexOf("://") + 1); + path = temphost.substring(temphost.indexOf('/')); + temphost = temphost.substring(0, temphost.indexOf('/')); + if (temphost.indexOf(':') != -1) { + port = Integer.parseInt(temphost.substring(temphost.indexOf(':')+1)); + temphost = temphost.substring(0, temphost.indexOf(':')); } else { - this.url = new URL(url); + port = ssl ? 443 : 80; } - if (!skipResolveCheck) resolveAndCheckIfFirewalled(this.url.getHost()); - port = this.url.getPort(); - path = this.url.getFile(); - if (port == -1) port = ssl ? 443 : 80; - host = this.url.getHost(); + if (!skipResolveCheck) resolveAndCheckIfFirewalled(temphost); + host = temphost; if (Log.verbose) Log.info(this, "creating HTTP object for connection to " + host + ":" + port); Proxy pi = Platform.detectProxy(); @@ -355,7 +360,7 @@ public class HTTP { PrintWriter pw = new PrintWriter(new OutputStreamWriter(originalUrl.equals("stdio:") ? System.out : sock.getOutputStream())); if (content != null) { - pw.print("POST " + path + " HTTP/1.1\r\n"); + pw.print("POST " + path + " HTTP/1.0\r\n"); // FIXME chunked encoding int contentLength = content.substring(0, 2).equals("\r\n") ? content.length() - 2 : (content.length() - content.indexOf("\r\n\r\n") - 4); @@ -384,7 +389,7 @@ public class HTTP { if (h.get("AUTHTYPE").equals("Basic")) { if (authCache.get(originalUrl) != null) throw new HTTPException("username/password rejected"); - authCache.put(originalUrl, "Basic " + new String(Base64.encode(userInfo.getBytes("US-ASCII")))); + authCache.put(originalUrl, "Basic " + new String(Base64.encode(userInfo.getBytes("UTF8")))); } else if (h.get("AUTHTYPE").equals("Digest")) { if (authCache.get(originalUrl) != null && !"true".equals(h.get("stale"))) @@ -431,7 +436,7 @@ public class HTTP { if (style.equals("Basic")) { Proxy.Authorization.authorization2 = - "Basic " + new String(Base64.encode(Proxy.Authorization.authorization.getBytes("US-ASCII"))); + "Basic " + new String(Base64.encode(Proxy.Authorization.authorization.getBytes("UTF8"))); } else if (style.equals("Digest")) { String A1 = Proxy.Authorization.authorization.substring(0, userInfo.indexOf(':')) + ":" + h.get("realm") + ":" + @@ -580,6 +585,8 @@ public class HTTP { if (buflen >= 4 && buf[buflen - 4] == '\r' && buf[buflen - 3] == '\n' && buf[buflen - 2] == '\r' && buf[buflen - 1] == '\n') break; + if (buflen >=2 && buf[buflen - 1] == '\n' && buf[buflen - 2] == '\n') + break; // nice for people using stdio if (buflen == buf.length) { byte[] newbuf = new byte[buf.length * 2]; System.arraycopy(buf, 0, newbuf, 0, buflen); @@ -630,7 +637,7 @@ public class HTTP { } private String H(String s) throws IOException { - byte[] b = s.getBytes("US-ASCII"); + byte[] b = s.getBytes("UTF8"); MD5Digest md5 = new MD5Digest(); md5.update(b, 0, b.length); byte[] out = new byte[md5.getDigestSize()]; @@ -649,8 +656,6 @@ public class HTTP { /** encapsulates most of the proxy logic; some is shared in HTTP.java */ public static class Proxy { - public Proxy() { } - public String httpProxyHost = null; ///< the HTTP Proxy host to use public int httpProxyPort = -1; ///< the HTTP Proxy port to use public String httpsProxyHost = null; ///< seperate proxy for HTTPS @@ -770,7 +775,7 @@ public class HTTP { static public Semaphore waitingForUser = new Semaphore(); public static synchronized void getPassword(final String realm, final String style, - final String proxyIP, String oldAuth) { + final String proxyIP, String oldAuth) throws IOException { // this handles cases where multiple threads hit the proxy auth at the same time -- all but one will block on the // synchronized keyword. If 'authorization' changed while the thread was blocked, it means that the user entered @@ -779,9 +784,11 @@ public class HTTP { if (authorization != oldAuth) return; if (Log.on) Log.info(Authorization.class, "displaying proxy authorization dialog"); Scheduler.add(new Scheduler.Task() { - public void perform() throws Exception { + public void perform() throws IOException, JSExn { Box b = new Box(); - Template t = Template.buildTemplate(Stream.getInputStream((JS)Main.builtin.get("org/ibex/builtin/proxy_authorization.ibex")), new Ibex(null)); + Template t = null; + // FIXME + //Template.buildTemplate("org/ibex/builtin/proxy_authorization.ibex", Stream.getInputStream((JS)Main.builtin.get("org/ibex/builtin/proxy_authorization.ibex")), new Ibex(null)); t.apply(b); b.put("realm", realm); b.put("proxyIP", proxyIP); @@ -936,7 +943,7 @@ public class HTTP { * @return The NTLM Response. */ public static byte[] getNTLMResponse(String password, byte[] challenge) - throws Exception { + throws UnsupportedEncodingException { byte[] ntlmHash = ntlmHash(password); return lmResponse(ntlmHash, challenge); } @@ -951,7 +958,7 @@ public class HTTP { * @return The LM Response. */ public static byte[] getLMResponse(String password, byte[] challenge) - throws Exception { + { byte[] lmHash = lmHash(password); return lmResponse(lmHash, challenge); } @@ -973,7 +980,7 @@ public class HTTP { */ public static byte[] getNTLMv2Response(String target, String user, String password, byte[] targetInformation, byte[] challenge, - byte[] clientChallenge) throws Exception { + byte[] clientChallenge) throws UnsupportedEncodingException { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); byte[] blob = createBlob(targetInformation, clientChallenge); return lmv2Response(ntlmv2Hash, blob, challenge); @@ -994,7 +1001,7 @@ public class HTTP { */ public static byte[] getLMv2Response(String target, String user, String password, byte[] challenge, byte[] clientChallenge) - throws Exception { + throws UnsupportedEncodingException { byte[] ntlmv2Hash = ntlmv2Hash(target, user, password); return lmv2Response(ntlmv2Hash, clientChallenge, challenge); } @@ -1012,7 +1019,7 @@ public class HTTP { * the client challenge, null-padded to 24 bytes. */ public static byte[] getNTLM2SessionResponse(String password, - byte[] challenge, byte[] clientChallenge) throws Exception { + byte[] challenge, byte[] clientChallenge) throws UnsupportedEncodingException { byte[] ntlmHash = ntlmHash(password); MD5Digest md5 = new MD5Digest(); md5.update(challenge, 0, challenge.length); @@ -1032,15 +1039,15 @@ public class HTTP { * @return The LM Hash of the given password, used in the calculation * of the LM Response. */ - private static byte[] lmHash(String password) throws Exception { + private static byte[] lmHash(String password) { /* - byte[] oemPassword = password.toUpperCase().getBytes("US-ASCII"); + byte[] oemPassword = password.toUpperCase().getBytes("UTF8"); int length = java.lang.Math.min(oemPassword.length, 14); byte[] keyBytes = new byte[14]; System.arraycopy(oemPassword, 0, keyBytes, 0, length); Key lowKey = createDESKey(keyBytes, 0); Key highKey = createDESKey(keyBytes, 7); - byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII"); + byte[] magicConstant = "KGS!@#$%".getBytes("UTF8"); Cipher des = Cipher.getInstance("DES/ECB/NoPadding"); des.init(Cipher.ENCRYPT_MODE, lowKey); byte[] lowHash = des.doFinal(magicConstant); @@ -1062,7 +1069,7 @@ public class HTTP { * @return The NTLM Hash of the given password, used in the calculation * of the NTLM Response and the NTLMv2 and LMv2 Hashes. */ - private static byte[] ntlmHash(String password) throws Exception { + private static byte[] ntlmHash(String password) throws UnsupportedEncodingException { byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked"); MD4Digest md4 = new MD4Digest(); md4.update(unicodePassword, 0, unicodePassword.length); @@ -1081,7 +1088,7 @@ public class HTTP { * and LMv2 Responses. */ private static byte[] ntlmv2Hash(String target, String user, - String password) throws Exception { + String password) throws UnsupportedEncodingException { byte[] ntlmHash = ntlmHash(password); String identity = user.toUpperCase() + target.toUpperCase(); return hmacMD5(identity.getBytes("UnicodeLittleUnmarked"), ntlmHash); @@ -1097,7 +1104,7 @@ public class HTTP { * hash). */ private static byte[] lmResponse(byte[] hash, byte[] challenge) - throws Exception { + { /* byte[] keyBytes = new byte[21]; System.arraycopy(hash, 0, keyBytes, 0, 16); @@ -1132,7 +1139,7 @@ public class HTTP { * client data). */ private static byte[] lmv2Response(byte[] hash, byte[] clientData, - byte[] challenge) throws Exception { + byte[] challenge) { byte[] data = new byte[challenge.length + clientData.length]; System.arraycopy(challenge, 0, data, 0, challenge.length); System.arraycopy(clientData, 0, data, challenge.length, @@ -1210,7 +1217,7 @@ public class HTTP { * * @return The HMAC-MD5 hash of the given data. */ - private static byte[] hmacMD5(byte[] data, byte[] key) throws Exception { + private static byte[] hmacMD5(byte[] data, byte[] key) { byte[] ipad = new byte[64]; byte[] opad = new byte[64]; for (int i = 0; i < 64; i++) {