2002/05/05 08:37:32
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:46:55 +0000 (06:46 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:46:55 +0000 (06:46 +0000)
darcs-hash:20040130064655-2ba56-13ddd566eda986040af2b4d6fb8e7c88bcd88213.gz

CHANGES
src/org/xwt/HTTP.java
src/org/xwt/Main.java
src/org/xwt/Platform.java
src/org/xwt/SOAP.java
src/org/xwt/TinySSL.java
src/org/xwt/XMLRPC.java
src/org/xwt/plat/Java12.java
src/org/xwt/plat/Win32.java

diff --git a/CHANGES b/CHANGES
index 063e6b7..ac028f8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
               XMLRPC.java, Java12.java, Win32.cc, Win32.java: new HTTP
               architecture, first implementation of proxy support.
 
+05-Apr megacz HTTP.java, Main.java, Platform.java, SOAP.java,
+              TinySSL.java, XMLRPC.java, Java12.java, Win32.java:
+              improved proxy support.
+
 
 
 
index 075a641..6b054c5 100644 (file)
@@ -1,5 +1,4 @@
-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
-package org.xwt;
+// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]package org.xwt;
 
 import java.net.*;
 import java.io.*;
@@ -30,7 +29,7 @@ public class HTTP {
     /** the path (URI) to retrieve on the server */
     String path = null;
 
-    /** the socket; created lazily */
+    /** the socket */
     Socket sock = null;
 
     /** the socket's inputstream */
@@ -45,81 +44,180 @@ public class HTTP {
     /** the content-length of the data being recieved */
     int contentLength = 0;
 
-    /** true iff a proxy should be used */
-    boolean proxy = false;
-
     /** additional headers to be transmitted */
     String headers = "";
 
-    public HTTP(String url) throws MalformedURLException, IOException {
-        if (url.startsWith("https:")) {
-            url = "http" + url.substring(5);
-            ssl = true;
-        }
-        if (!url.startsWith("http:")) throw new IOException("HTTP only supports http/https urls");
+    /** cache for resolveAndCheckIfFirewalled() */
+    static Hashtable resolvedHosts = new Hashtable();
+
+
+    // Constructor ////////////////////////////////////////////////////////////////////////////////////////
+
+    public HTTP(String url) throws MalformedURLException, IOException { this(url, false); }
+    public HTTP(String url, boolean skipResolveCheck) throws MalformedURLException, IOException {
+        if (url.startsWith("https:")) { url = "http" + url.substring(5); ssl = true; }
+        if (!url.startsWith("http:")) throw new HTTPException("HTTP only supports http/https urls");
         this.url = new URL(url);
-        host = this.url.getHost();
         port = this.url.getPort();
         path = this.url.getFile();
         if (port == -1) port = ssl ? 443 : 80;
+        host = this.url.getHost();
+        if (Log.on) Log.log(this, "creating HTTP object for connection to " + host + ":" + port);
+        addHeader("Host", host);                  // host header is always sent verbatim
+        if (!skipResolveCheck) host = resolveAndCheckIfFirewalled(host);   // might have to use the strict IP if behind a proxy
+
+        ProxyInfo 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);
+        if (sock == null) sock = attemptDirect();
+        if (sock == null) throw new HTTPException("all socket creation attempts have failed");
+        sock.setTcpNoDelay(true);
+    }
+
+
+    // Safeguarded DNS Resolver ///////////////////////////////////////////////////////////////////////////
+
+    /**
+     *  resolves the hostname and returns it as a string in the form "x.y.z.w", except for the special case "xmlrpc.xwt.org".
+     *  @throws HTTPException if the host falls within a firewalled netblock
+     */
+    private String resolveAndCheckIfFirewalled(String host) throws HTTPException {
+
+        // special case
+        if (host.equals("xmlrpc.xwt.org")) return host;
+
+        // cached
+        if (resolvedHosts.get(host) != null) return (String)resolvedHosts.get(host);
+
+        if (Log.on) Log.log(this, "  resolveAndCheckIfFirewalled: resolving " + host);
+
+        // resolve using DNS
         try {
             InetAddress addr = InetAddress.getByName(host);
             byte[] quadbyte = addr.getAddress();
-            if (quadbyte[0] == 10 || (quadbyte[0] == 192 && quadbyte[1] == 168) ||
-                (quadbyte[0] == 172 && (quadbyte[1] & 0xF0) == 16) && !addr.equals(Main.originAddr))
-                throw new IOException("security violation: " + host + " [" + addr.getHostAddress() + "] is in a firewalled netblock");
-        } catch (UnknownHostException uhe) {
-            if (Platform.detectProxy() == null) throw new IOException("could not resolve hostname \"" + host + "\" and no proxy configured");
-            else if (Log.on) Log.log("could not resolve host " + host + "; assuming that the proxy can resolve it for us");
+            if ((quadbyte[0] == 10 ||
+                 (quadbyte[0] == 192 && quadbyte[1] == 168) ||
+                 (quadbyte[0] == 172 && (quadbyte[1] & 0xF0) == 16)) && !addr.equals(Main.originAddr))
+                throw new HTTPException("security violation: " + host + " [" + addr.getHostAddress() + "] is in a firewalled netblock");
+            return addr.getHostAddress();
+        } catch (UnknownHostException uhe) { }
+
+        // resolve using xmlrpc.xwt.org
+        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 {
+            Object ret = new XMLRPC("http://xmlrpc.xwt.org/RPC2/", "dns.resolve").call(new Object[] { host });
+            if (ret == null || !(ret instanceof String)) throw new Exception("    xmlrpc.xwt.org returned non-String: " + ret);
+            resolvedHosts.put(host, ret);
+            return (String)ret;
+        } catch (Throwable e) {
+            throw new HTTPException("exception while attempting to use xmlrpc.xwt.org to resolve " + host + ": " + e);
         }
     }
 
-    public String getContentType() throws IOException {
-        getInputStream();
-        return contentType;
-    }
 
-    public int getContentLength() throws IOException {
-        getInputStream();
-        return contentLength;
-    }
+    // Methods to attempt socket creation /////////////////////////////////////////////////////////////////
 
-    public void addHeader(String header, String value) throws IOException {
-        if (in != null) throw new IOException("attempt to add header after connection has been made");
-        headers += header + ": " + value + "\r\n";
+    /** Attempts a direct connection */
+    public Socket attemptDirect() {
+        try {
+            if (Log.on) Log.log(this, "attempting to create unproxied socket to " + host + ":" + port + (ssl ? " [ssl]" : ""));
+            return Platform.getSocket(host, port, ssl, true);
+        } catch (IOException e) {
+            if (Log.on) Log.log(this, "exception in attemptDirect(): " + e);
+            return null;
+        }
     }
 
-    private void getSock() throws IOException {
-        ProxyInfo pi = Platform.detectProxy();
+    /** Attempts to use an HTTP proxy, employing the CONNECT method if HTTPS is requested */
+    public Socket attemptHttpProxy(String proxyHost, int proxyPort) {
+        try {
+            if (Log.on) Log.log(this, "attempting to create HTTP proxied socket using proxy " + proxyHost + ":" + proxyPort);
+
+            Socket sock = Platform.getSocket(proxyHost, proxyPort, ssl, false);
+            if (!ssl) {
+                path = "http://" + host + ":" + port + path;
+            } else {
+                if (Log.on) Log.log(this, "attempting to create HTTP proxied socket using proxy " + proxyHost + ":" + proxyPort);
+                PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
+                BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
+                pw.print("CONNECT " + host + ":" + port + " HTTP/1.0\r\n\r\n");
+                String s = br.readLine();
+                if (s.charAt(9) != '2') throw new HTTPException("proxy refused CONNECT method: \"" + s + "\"");
+                while (br.readLine().length() > 0) { };
+                ((TinySSL)sock).negotiate();
+            }
+            return sock;
 
-        // unproxied
-        if (pi == null || (pi.proxyAutoConfigFunction == null && pi.socksProxyHost == null && pi.httpProxyHost == null)) {
-            if (Log.on) Log.log(this, "creating unproxied socket to " + host + ":" + port + (ssl ? " [ssl]" : ""));
-            sock = Platform.getSocket(host, port, ssl);
-            return;
+        } catch (IOException e) {
+            if (Log.on) Log.log(this, "exception in attemptHttpProxy(): " + e);
+            return null;
         }
+    }
+
+    /**
+     *  Implements SOCKSv4 with v4a DNS extension
+     *  @see http://www.socks.nec.com/protocol/socks4.protocol
+     *  @see http://www.socks.nec.com/protocol/socks4a.protocol
+     */
+    public Socket attemptSocksProxy(String proxyHost, int proxyPort) {
+
+        // even if host is already a "x.y.z.w" string, we use this to parse it into bytes
+        InetAddress addr = null;
+        try { addr = InetAddress.getByName(host); } catch (Exception e) { }
 
-        // no PAC; simple config
-        if (pi.proxyAutoConfigFunction == null) {
-            String proxyHost = ssl && pi.httpsProxyHost != null ? pi.httpsProxyHost : pi.httpProxyHost;
-            int proxyPort = ssl && pi.httpsProxyHost != null ? pi.httpsProxyPort : pi.httpProxyPort;
-            if (Log.on) Log.log(this, "no proxyAutoConfigFunction; using proxy " + proxyHost + ":" + proxyPort);
-            sock = Platform.getSocket(proxyHost, proxyPort, ssl);
-            proxy = true;
-            return;
+        if (Log.on) Log.log(this, "attempting to create SOCKSv4" + (addr == null ? "" : "a") +
+                            " proxied socket using proxy " + proxyHost + ":" + proxyPort);
+
+        try {
+            Socket sock = Platform.getSocket(proxyHost, proxyPort, ssl, false);
+            
+            DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
+            dos.writeByte(0x04);                         // SOCKSv4(a)
+            dos.writeByte(0x01);                         // CONNECT
+            dos.writeShort(port & 0xffff);               // port
+            if (addr == null) dos.writeInt(0x00000001);  // bogus IP
+            else dos.write(addr.getAddress());           // actual IP
+            dos.writeByte(0x00);                         // no userid
+            if (addr == null) {
+                PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos));
+                pw.print(host);
+                pw.flush();
+                dos.writeByte(0x00);                     // hostname null terminator
+            }
+            dos.flush();
+
+            DataInputStream dis = new DataInputStream(sock.getInputStream());
+            dis.readByte();                              // reply version
+            byte success = dis.readByte();               // success/fail
+            dis.skip(6);                                 // ip/port
+            
+            if ((int)(success & 0xff) == 90) {
+                if (ssl) ((TinySSL)sock).negotiate();
+                return sock;
+            }
+            if (Log.on) Log.log(this, "SOCKS server denied access, code " + (success & 0xff));
+            return null;
+
+        } catch (IOException e) {
+            if (Log.on) Log.log(this, "exception in attemptSocksProxy(): " + e);
+            return null;
         }
-        
-        // PAC
+    }
+
+    /** executes the PAC script and dispatches a call to one of the other attempt methods based on the result */
+    public Socket attemptPAC(Function pacFunc) {
+        if (Log.on) Log.log(this, "evaluating PAC script");
         String pac = null;
         try {
-            Context cx = Context.enter();
-            Object obj = pi.proxyAutoConfigFunction.call(cx, ProxyInfo.base, null, new Object[] { url.toString(), host });
-            if (Log.on) Log.log(this, "PAC script returned \"" + obj + "\"");
+            Object obj = pacFunc.call(Context.enter(), ProxyInfo.proxyAutoConfigRootScope, null, new Object[] { url.toString(), url.getHost() });
+            if (Log.on) Log.log(this, "  PAC script returned \"" + obj + "\"");
             pac = obj.toString();
         } catch (Throwable e) {
-            if (Log.on) Log.log(this, "PAC script threw an exception:");
-            if (Log.on) Log.log(this, e);
-            throw new IOException("PAC script threw exception " + e);
+            if (Log.on) Log.log(this, "PAC script threw exception " + e);
+            return null;
         }
 
         StringTokenizer st = new StringTokenizer(pac, ";", false);
@@ -127,33 +225,51 @@ public class HTTP {
             String token = st.nextToken().trim();
             if (Log.on) Log.log(this, "  trying \"" + token + "\"...");
             try {
-                if (token.startsWith("DIRECT")) {
-                    proxy = false;
-                    sock = Platform.getSocket(host, port, ssl);
-                    return;
-                } else if (token.startsWith("PROXY")) { 
-                    proxy = true;
-                    sock = Platform.getSocket(token.substring(token.indexOf(' ') + 1, token.indexOf(':')),
-                                              Integer.parseInt(token.substring(token.indexOf(':') + 1)), ssl);
-                    return;
-                } else if (token.startsWith("SOCKS")) {
-                    // FIXME
-                }
+                Socket ret = null;
+                if (token.startsWith("DIRECT"))
+                    ret = attemptDirect();
+                else if (token.startsWith("PROXY"))
+                    ret = attemptHttpProxy(token.substring(token.indexOf(' ') + 1, token.indexOf(':')),
+                                           Integer.parseInt(token.substring(token.indexOf(':') + 1)));
+                else if (token.startsWith("SOCKS"))
+                    ret = attemptSocksProxy(token.substring(token.indexOf(' ') + 1, token.indexOf(':')),
+                                            Integer.parseInt(token.substring(token.indexOf(':') + 1)));
+                if (ret != null) return ret;
             } catch (Throwable e) {
-                if (Log.on) Log.log(this, "attempt at \"" + proxy + "\" failed due to " + e + "; trying next one");
+                if (Log.on) Log.log(this, "attempt at \"" + token + "\" failed due to " + e + "; trying next token");
             }
         }
-        throw new IOException("all proxy options exhausted");
+        if (Log.on) Log.log(this, "all PAC results exhausted");
+        return null;
+    }
+
+
+    // Everything Else ////////////////////////////////////////////////////////////////////////////
+
+    /** returns the content-type of the reply */
+    public String getContentType() throws IOException {
+        getInputStream();
+        return contentType;
+    }
+
+    /** returns the content-length of the reply */
+    public int getContentLength() throws IOException {
+        getInputStream();
+        return contentLength;
+    }
+
+    /** adds a header to the outbound transmission */
+    public void addHeader(String header, String value) throws HTTPException {
+        if (in != null) throw new HTTPException("attempt to add header after connection has been made");
+        headers += header + ": " + value + "\r\n";
     }
 
     public OutputStream getOutputStream(int contentLength, String contentType) throws IOException {
         if (out != null) return out;
-        if (in != null) throw new IOException("attempt to getOutputStream() after getInputStream()");
-        getSock();
-        sock.setTcpNoDelay(true);
+        if (in != null) throw new HTTPException("attempt to getOutputStream() after getInputStream()");
         out = sock.getOutputStream();
         PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
-        pw.print("POST " + (proxy ? url.toString() : path) + " HTTP/1.0\r\n");
+        pw.print("POST " + path + " HTTP/1.0\r\n");
         pw.print("Host: " + host + "\r\n");
         pw.print("User-Agent: XWT\r\n");
         pw.print("Content-length: " + contentLength + "\r\n");
@@ -169,10 +285,8 @@ public class HTTP {
         if (out != null) {
             out.flush();
         } else {
-            getSock();
-            sock.setTcpNoDelay(true);
             PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
-            pw.print("GET " + (proxy ? url.toString() : path) + " HTTP/1.0\r\n");
+            pw.print("GET " + path + " HTTP/1.0\r\n");
             pw.print("Host: " + host + "\r\n");
             pw.print("User-Agent: XWT\r\n");
             pw.print(headers);
@@ -188,7 +302,7 @@ public class HTTP {
         int buflen = 0;
         while(true) {
             int read = in.read();
-            if (read == -1) throw new IOException("stream closed while reading headers");
+            if (read == -1) throw new HTTPException("stream closed while reading headers");
             buf[buflen++] = (byte)read;
             if (buflen >= 4 && buf[buflen - 4] == '\r' && buf[buflen - 3] == '\n' && buf[buflen - 2] == '\r' && buf[buflen - 1] == '\n') break;
             if (buflen == buf.length) {
@@ -200,9 +314,9 @@ public class HTTP {
         
         BufferedReader headerReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, buflen)));
         String s = headerReader.readLine();
-        if (!s.startsWith("HTTP/")) throw new IOException("Expected reply to start with \"HTTP/\"");
+        if (!s.startsWith("HTTP/")) throw new HTTPException("Expected reply to start with \"HTTP/\"");
         String reply = s.substring(s.indexOf(' ') + 1);
-        if (!reply.startsWith("2")) throw new IOException("HTTP Error: " + reply);
+        if (!reply.startsWith("2")) throw new HTTPException("HTTP Error: " + reply);
         while((s = headerReader.readLine()) != null) {
             if (s.length() > 15 && s.substring(0, 15).equalsIgnoreCase("content-length: "))
                 contentLength = Integer.parseInt(s.substring(15));
@@ -211,6 +325,17 @@ public class HTTP {
         return in;
     }
 
+
+
+    // HTTPException ///////////////////////////////////////////////////////////////////////////////////
+
+    static class HTTPException extends IOException {
+        public HTTPException(String s) { super(s); }
+    }
+
+
+    // ProxyInfo ///////////////////////////////////////////////////////////////////////////////////
+
     public static class ProxyInfo {
 
         public ProxyInfo() { }
@@ -241,8 +366,9 @@ public class HTTP {
 
         public static ProxyInfo detectProxyViaManual() {
             try {
-                try { InetAddress.getByName("xwt-proxy-httpHost");
-                } catch (UnkownHostException unhe) { InetAddress.getByName("xwt-proxy-socksHost"); }
+                // continue iff one of the two resolves
+                try { InetAddress.getByName("xwt-proxy-httpHost"); }
+                catch (UnknownHostException e) { InetAddress.getByName("xwt-proxy-socksHost"); }
 
                 if (Log.on) Log.log(Platform.class, "using xwt-proxy-* configuration");
                 ProxyInfo ret = new ProxyInfo();
@@ -263,7 +389,7 @@ public class HTTP {
                 } catch (UnknownHostException e) { }
                 return ret;
             } catch (UnknownHostException e) {
-                if (Log.on) Log.log(Platform.class, "xwt-proxy-* detection failed due to:");
+                if (Log.on) Log.log(Platform.class, "xwt-proxy-* detection failed due to: " + e);
                 return null;
             }
         }
@@ -288,7 +414,7 @@ public class HTTP {
             try { 
                 Context cx = Context.enter();
                 cx.setOptimizationLevel(-1);
-                BufferedReader br = new BufferedReader(new InputStreamReader(new HTTP(url).getInputStream()));
+                BufferedReader br = new BufferedReader(new InputStreamReader(new HTTP(url, true).getInputStream()));
                 String s = null;
                 String script = "";
                 while((s = br.readLine()) != null) script += s + "\n";
index 2ac536d..0c0c7b9 100644 (file)
@@ -92,8 +92,9 @@ public class Main extends Applet {
                     URL u = new URL(args[startargs]);
                     try {
                         originAddr = InetAddress.getByName(u.getHost());
-                    } catch (UnknownHostException) {
-                        if (Log.on) Log.log("couldn't resolve " + u.getHost() + " -- hopefully there is a proxy that can");
+                        // FIXME: use XMLRPC resolver?
+                    } catch (UnknownHostException e) {
+                        if (Log.on) Log.log(Main.class, "couldn't resolve " + u.getHost() + " -- hopefully there is a proxy that can");
                     }
                     Resources.loadArchive(new HTTP(args[startargs]).getInputStream());
                     
index 39a480f..e3ee510 100644 (file)
@@ -103,8 +103,8 @@ public class Platform {
     protected Surface _createSurface(Box b, boolean framed) { return null; }
 
     /** creates a socket object */
-    protected Socket _getSocket(String host, int port, boolean ssl) throws IOException {
-        return ssl ? new TinySSL(host, port) : new Socket(java.net.InetAddress.getByName(host), port);
+    protected Socket _getSocket(String host, int port, boolean ssl, boolean negotiate) throws IOException {
+        return ssl ? new TinySSL(host, port, negotiate) : new Socket(java.net.InetAddress.getByName(host), port);
     }
 
     /** creates and returns a picture */
@@ -169,10 +169,7 @@ public class Platform {
         return;
     }
 
-    /** Returns true iff the platform detected that it should be using a proxy.
-     *  The platform implementation should cache the result.
-     *  This method will only be called if a connection attempt failed
-     */
+    /** Returns null if XWT should always use direct connection; otherwise returns a ProxyInfo object with proxy settings */
     protected synchronized HTTP.ProxyInfo _detectProxy() { return null; }
 
     // Static methods -- thunk to the instance /////////////////////////////////////////////////////////////////////////
@@ -214,7 +211,9 @@ public class Platform {
     public static void setClipBoard(String s) { platform._setClipBoard(s); }
 
     /** creates a socket object, with or without ssl encryption */
-    public static Socket getSocket(String host, int port, boolean ssl) throws IOException { return platform._getSocket(host, port, ssl); }
+    public static Socket getSocket(String host, int port, boolean ssl, boolean negotiate) throws IOException {
+        return platform._getSocket(host, port, ssl, negotiate);
+    }
 
     /** returns the width of the screen, in pixels */
     public static int getScreenWidth() { return platform._getScreenWidth(); }
index 35ecd50..ade85e5 100644 (file)
@@ -212,7 +212,7 @@ class SOAP extends XMLRPC {
         }
     }
 
-    protected String send(Object[] args, HTTP http) throws JavaScriptException {
+    protected String send(Object[] args, HTTP http) throws JavaScriptException, IOException {
         // build up the request
         StringBuffer content = new StringBuffer();
         content.append("<?xml version=\"1.0\"?>\n");
index 41e83a1..e3f90ab 100644 (file)
@@ -151,12 +151,17 @@ public class TinySSL extends Socket {
     public InputStream getInputStream() { return is; }
     public OutputStream getOutputStream() { return os; }
 
-    public TinySSL(String host, int port) throws IOException {
+    public TinySSL(String host, int port) throws IOException { this(host, port, true); }
+    public TinySSL(String host, int port, boolean negotiateImmediately) throws IOException {
         super(host, port);
         hostname = host;
+        if (negotiateImmediately) negotiate();
+    }
+
+    /** negotiates the SSL connection */
+    public void negotiate() throws IOException {
         os = new SSLOutputStream(super.getOutputStream());
         is = new SSLInputStream(super.getInputStream());
-            
         os.writeClientHello();
         is.readServerHandshakes();
         os.sendClientHandshakes();
index 3201ecd..274b5ef 100644 (file)
@@ -230,14 +230,21 @@ class XMLRPC extends XML implements Function {
         }
     }
 
-    private Object connect(Object[] args) throws JavaScriptException, IOException {
+    public Object call(Object[] args) throws JavaScriptException, IOException {
         if (Log.verbose) Log.log(this, "call to " + url + " : " + methodname);
+
+        if (tracker == null) tracker = new Hash();
+        else tracker.clear();
+
+        if (objects == null) objects = new Vec();
+        else objects.setSize(0);
+
         HTTP http = new HTTP(url);
         String content = send(args, http);
         OutputStream os = new BufferedOutputStream(http.getOutputStream(content.length(), "text/xml"), 4000);
         PrintWriter ps = !Log.verbose ?
             new PrintWriter(os) :
-            new PrintWriter(new FilterWriter(os)) {
+            new PrintWriter(new FilterWriter(new OutputStreamWriter(os)) {
                     public void write(int i) throws IOException {
                         super.write(i);
                         if (Log.on) Log.log(this, "send: " + ((char)i));
@@ -274,7 +281,7 @@ class XMLRPC extends XML implements Function {
         return recieve(br);
     }
 
-    protected String send(Object[] args, HTTP http) throws JavaScriptException {
+    protected String send(Object[] args, HTTP http) throws JavaScriptException, IOException {
         StringBuffer content = new StringBuffer();
         content.append("<?xml version=\"1.0\"?>\n");
         content.append("    <methodCall>\n");
@@ -310,12 +317,6 @@ class XMLRPC extends XML implements Function {
 
     public final Object call(Context cx, Scriptable scope, Scriptable thisObj, java.lang.Object[] args) throws JavaScriptException {
 
-        if (tracker == null) tracker = new Hash();
-        else tracker.clear();
-
-        if (objects == null) objects = new Vec();
-        else objects.setSize(0);
-
         // put ourselves in the background
         Thread thread = Thread.currentThread();
         if (!(thread instanceof ThreadMessage)) {
@@ -327,7 +328,7 @@ class XMLRPC extends XML implements Function {
         mythread.done.release();
 
         try {
-            return connect(args);
+            return call(args);
 
         } catch (IOException se) {
             if (Log.on) Log.log(this, se);
index 0036405..6d21ccc 100644 (file)
@@ -51,19 +51,21 @@ public class Java12 extends AWT {
                         else return null;
 
                     } catch (Throwable e) {
-                        if (Log.on) Log.log(this, "exception while querying sun.plugin.protocol.PluginProxyHandler:");
+                        if (Log.on) Log.log(this, "exception while querying sun.plugin.protocol.PluginProxyHandler: " + e);
                         if (Log.on) Log.log(this, e);
                         return null;
                     }
                 }});
     }
 
-    protected Socket __getSocket(String host, int port, boolean ssl) throws IOException { return super._getSocket(host, port, ssl); }
-    protected Socket _getSocket(final String host, final int port, final boolean ssl) throws IOException {
+    protected Socket __getSocket(String host, int port, boolean ssl, boolean negotiate) throws IOException {
+        return super._getSocket(host, port, ssl, negotiate);
+    }
+    protected Socket _getSocket(final String host, final int port, final boolean ssl, final boolean negotiate) throws IOException {
         return (Socket)java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
                 public Object run() {
                     try {
-                        return __getSocket(host, port, ssl);
+                        return __getSocket(host, port, ssl, negotiate);
                     } catch (Exception e) {
                         if (Log.on) Log.log(Java12.class, "Error attempting to create socket");
                         if (Log.on) Log.log(Java12.class, e);
index f9172d0..a32d29b 100644 (file)
@@ -139,7 +139,7 @@ public class Win32 extends GCJ {
             if (ret.proxyAutoConfigFunction != null) return ret;
         }
 
-        if (container[0] = null) return null;
+        if (container[0] == null) return null;
         StringTokenizer st = new StringTokenizer(container[0], ";", false);
         while(st.hasMoreTokens()) try {
             String s = st.nextToken().trim();