improvements to Doc.java, corresponding fixes to the reference
[org.ibex.core.git] / src / org / ibex / HTTP.java
index 856eabe..10da62b 100644 (file)
@@ -31,6 +31,7 @@ public class HTTP {
 
     public static HTTP stdio = new HTTP("stdio:");
 
+
     // Statics ///////////////////////////////////////////////////////////////////////////////////////////////
 
     static Hash resolvedHosts = new Hash();            ///< cache for resolveAndCheckIfFirewalled()
@@ -40,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
@@ -87,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);
@@ -269,7 +270,7 @@ public class HTTP {
         if (Log.verbose) Log.info(this, "evaluating PAC script");
         String pac = null;
         try {
-            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()];
@@ -779,7 +786,9 @@ public class HTTP {
                 Scheduler.add(new Scheduler.Task() {
                         public void perform() throws IOException, JSExn {
                             Box b = new Box();
-                            Template t = Template.buildTemplate("org/ibex/builtin/proxy_authorization.ibex", 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);
@@ -1032,13 +1041,13 @@ public class HTTP {
              */
             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);