? changes.diff
Index: Base64.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Base64.java
--- Base64.java	20 Jul 2001 19:38:16 -0000	1.1.1.1
+++ Base64.java	19 Feb 2002 01:20:19 -0000
@@ -1,326 +1,322 @@
 package org.apache.xmlrpc;
 
-// We can replace this with some apache code I'm sure. jvz.
-
-//////////////////////license & copyright header/////////////////////////
-//                                                                     //
-//    Base64 - encode/decode data using the Base64 encoding scheme     //
-//                                                                     //
-//                Copyright (c) 1998 by Kevin Kelley                   //
-//                                                                     //
-// This library is free software; you can redistribute it and/or       //
-// modify it under the terms of the GNU Lesser General Public          //
-// License as published by the Free Software Foundation; either        //
-// version 2.1 of the License, or (at your option) any later version.  //
-//                                                                     //
-// This library 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 Lesser General Public License for more details.                 //
-//                                                                     //
-// You should have received a copy of the GNU Lesser General Public    //
-// License along with this library; if not, write to the Free Software //
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA           //
-// 02111-1307, USA, or contact the author:                             //
-//                                                                     //
-// Kevin Kelley <kelley@ruralnet.net> - 30718 Rd. 28, La Junta, CO,    //
-// 81050  USA.                                                         //
-//                                                                     //
-////////////////////end license & copyright header///////////////////////
-
-import java.io.*; // needed only for main() method.
-
+/*
+ * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
+ * $Revision: 1.4 $
+ * $Date: 2001/09/04 21:49:55 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ */
 
 /**
-*   Provides encoding of raw bytes to base64-encoded characters, and
-*  decoding of base64 characters to raw bytes.
-*
-* @author Kevin Kelley (kelley@ruralnet.net)
-* @version 1.3
-* @date 06 August 1998
-* @modified 14 February 2000
-* @modified 22 September 2000
-*/
-public class Base64
+ * This class provides encode/decode for RFC 2045 Base64 as defined by
+ * RFC 2045, N. Freed and N. Borenstein.  <a
+ * href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>:
+ * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
+ * Internet Message Bodies. Reference 1996
+ *
+ * @author Jeffrey Rodriguez
+ * @version $Id: Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
+ */
+public final class  Base64
 {
+    static private final int  BASELENGTH         = 255;
+    static private final int  LOOKUPLENGTH       = 64;
+    static private final int  TWENTYFOURBITGROUP = 24;
+    static private final int  EIGHTBIT           = 8;
+    static private final int  SIXTEENBIT         = 16;
+    static private final int  SIXBIT             = 6;
+    static private final int  FOURBYTE           = 4;
+    static private final int  SIGN               = -128;
+    static private final byte PAD                = (byte) '=';
+    static private byte [] base64Alphabet       = new byte[BASELENGTH];
+    static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
+    //static private final Log log = LogSource.getInstance("org.apache.commons.util.Base64");
 
-    /**
-    * returns an array of base64-encoded characters to represent the
-    * passed data array.
-    *
-    * @param data the array of bytes to encode
-    * @return base64-coded character array.
-    */
-    static public char[] encode(byte[] data)
+    static
     {
-        char[] out = new char[((data.length + 2) / 3) * 4];
-
-        //
-        // 3 bytes encode to 4 chars.  Output is always an even
-        // multiple of 4 characters.
-        //
-        for (int i = 0, index = 0; i < data.length; i += 3, index += 4)
-        {
-            boolean quad = false;
-            boolean trip = false;
-
-            int val = (0xFF & (int) data[i]);
-            val <<= 8;
-            if ((i + 1) < data.length)
-            {
-                val |= (0xFF & (int) data[i + 1]);
-                trip = true;
-            }
-            val <<= 8;
-            if ((i + 2) < data.length)
-            {
-                val |= (0xFF & (int) data[i + 2]);
-                quad = true;
-            }
-            out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
-            val >>= 6;
-            out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
-            val >>= 6;
-            out[index + 1] = alphabet[val & 0x3F];
-            val >>= 6;
-            out[index + 0] = alphabet[val & 0x3F];
+        for (int i = 0; i < BASELENGTH; i++ )
+        {
+            base64Alphabet[i] = -1;
         }
-        return out;
-    }
-
-    /**
-      * Decodes a BASE-64 encoded stream to recover the original
-      * data. White space before and after will be trimmed away,
-      * but no other manipulation of the input will be performed.
-      *
-      * As of version 1.2 this method will properly handle input
-      * containing junk characters (newlines and the like) rather
-      * than throwing an error. It does this by pre-parsing the
-      * input and generating from that a count of VALID input
-      * characters.
-      **/
-    static public byte[] decode(char[] data)
-    {
-        // as our input could contain non-BASE64 data (newlines,
-        // whitespace of any sort, whatever) we must first adjust
-        // our count of USABLE data so that...
-        // (a) we don't misallocate the output array, and
-        // (b) think that we miscalculated our data length
-        //     just because of extraneous throw-away junk
-
-        int tempLen = data.length;
-        for (int ix = 0; ix < data.length; ix++)
+        for (int i = 'Z'; i >= 'A'; i--)
         {
-            if ((data[ix] > 255) || codes[data[ix]] < 0)
-                --tempLen; // ignore non-valid chars and padding
+            base64Alphabet[i] = (byte) (i - 'A');
         }
-        // calculate required length:
-        //  -- 3 bytes for every 4 valid base64 chars
-        //  -- plus 2 bytes if there are 3 extra base64 chars,
-        //     or plus 1 byte if there are 2 extra.
-
-        int len = (tempLen / 4) * 3;
-        if ((tempLen % 4) == 3)
-            len += 2;
-        if ((tempLen % 4) == 2)
-            len += 1;
-
-        byte[] out = new byte[len];
-
-
-
-        int shift = 0; // # of excess bits stored in accum
-        int accum = 0; // excess bits
-        int index = 0;
-
-        // we now go through the entire array (NOT using the 'tempLen' value)
-        for (int ix = 0; ix < data.length; ix++)
+        for (int i = 'z'; i>= 'a'; i--)
         {
-            int value = (data[ix] > 255) ? -1 : codes[data[ix]];
-
-            if (value >= 0)// skip over non-code
-
-            {
-                accum <<= 6; // bits shift up by 6 each time thru
-                shift += 6; // loop, with new bits being put in
-                accum |= value; // at the bottom.
-                if (shift >= 8)// whenever there are 8 or more shifted in,
-
-                {
-                    shift -= 8; // write them out (from the top, leaving any
-                    out[index++] = // excess at the bottom for next iteration.
-                            (byte)((accum >> shift) & 0xff);
-                }
-            }
-            // we will also have skipped processing a padding null byte ('=') here;
-            // these are used ONLY for padding to an even length and do not legally
-            // occur as encoded data. for this reason we can ignore the fact that
-            // no index++ operation occurs in that special case: the out[] array is
-            // initialized to all-zero bytes to start with and that works to our
-            // advantage in this combination.
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
         }
-
-        // if there is STILL something wrong we just have to throw up now!
-        if (index != out.length)
+        for (int i = '9'; i >= '0'; i--)
         {
-            throw new Error("Miscalculated data length (wrote " +
-                    index + " instead of " + out.length + ")");
+            base64Alphabet[i] = (byte) (i - '0' + 52);
         }
 
-        return out;
-    }
-
+        base64Alphabet['+']  = 62;
+        base64Alphabet['/']  = 63;
 
-    //
-    // code characters for values 0..63
-    //
-    static private char[] alphabet =
-            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray();
-
-    //
-    // lookup table for converting base64 characters to value in range 0..63
-    //
-    static private byte[] codes = new byte[256];
-    static
-    {
-        for (int i = 0; i < 256; i++)
-            codes[i] = -1;
-        for (int i = 'A'; i <= 'Z'; i++)
-            codes[i] = (byte)(i - 'A');
-        for (int i = 'a'; i <= 'z'; i++)
-            codes[i] = (byte)(26 + i - 'a');
-        for (int i = '0'; i <= '9'; i++)
-            codes[i] = (byte)(52 + i - '0');
-        codes['+'] = 62;
-        codes['/'] = 63;
-    }
+        for (int i = 0; i <= 25; i++ )
+            lookUpBase64Alphabet[i] = (byte) ('A' + i);
 
+        for (int i = 26,  j = 0; i <= 51; i++, j++ )
+            lookUpBase64Alphabet[i] = (byte) ('a'+ j);
 
+        for (int i = 52,  j = 0; i <= 61; i++, j++ )
+            lookUpBase64Alphabet[i] = (byte) ('0' + j);
 
+        lookUpBase64Alphabet[62] = (byte) '+';
+        lookUpBase64Alphabet[63] = (byte) '/';
+    }
 
-    ///////////////////////////////////////////////////
-    // remainder (main method and helper functions) is
-    // for testing purposes only, feel free to clip it.
-    ///////////////////////////////////////////////////
+    public static boolean isBase64( String isValidString )
+    {
+        return isArrayByteBase64(isValidString.getBytes());
+    }
 
-    public static void main(String[] args)
+    public static boolean isBase64( byte octect )
     {
-        boolean decode = false;
+        //shall we ignore white space? JEFF??
+        return (octect == PAD || base64Alphabet[octect] != -1);
+    }
 
-        if (args.length == 0)
+    public static boolean isArrayByteBase64( byte[] arrayOctect )
+    {
+        int length = arrayOctect.length;
+        if (length == 0)
         {
-            System.out.println("usage:  java Base64 [-d[ecode]] filename");
-            System.exit(0);
+            // shouldn't a 0 length array be valid base64 data?
+            // return false;
+            return true;
         }
-        for (int i = 0; i < args.length; i++)
+        for (int i=0; i < length; i++)
         {
-            if ("-decode".equalsIgnoreCase(args[i]))
-                decode = true;
-            else if ("-d".equalsIgnoreCase(args[i]))
-                decode = true;
+            if ( !Base64.isBase64(arrayOctect[i]) )
+                return false;
         }
+        return true;
+    }
 
-        String filename = args[args.length - 1];
-        File file = new File(filename);
-        if (!file.exists())
-        {
-            System.out.println("Error:  file '" + filename + "' doesn't exist!");
-            System.exit(0);
-        }
+    /**
+     * Encodes hex octects into Base64.
+     *
+     * @param binaryData Array containing binary data to encode.
+     * @return Base64-encoded data.
+     */
+    public static byte[] encode( byte[] binaryData )
+    {
+        int      lengthDataBits    = binaryData.length*EIGHTBIT;
+        int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
+        int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
+        byte     encodedData[]     = null;
 
-        if (decode)
+
+        if (fewerThan24bits != 0)
         {
-            char[] encoded = readChars(file);
-            byte[] decoded = decode(encoded);
-            writeBytes(file, decoded);
+            //data not divisible by 24 bit
+            encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
         }
         else
         {
-            byte[] decoded = readBytes(file);
-            char[] encoded = encode(decoded);
-            writeChars(file, encoded);
+            // 16 or 8 bit
+            encodedData = new byte[ numberTriplets * 4 ];
         }
-    }
 
-    private static byte[] readBytes(File file)
-    {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try
-        {
-            InputStream fis = new FileInputStream(file);
-            InputStream is = new BufferedInputStream(fis);
-            int count = 0;
-            byte[] buf = new byte[16384];
-            while ((count = is.read(buf)) != -1)
-            {
-                if (count > 0)
-                    baos.write(buf, 0, count);
-            }
-            is.close();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
+        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+        int encodedIndex = 0;
+        int dataIndex   = 0;
+        int i           = 0;
+        //log.debug("number of triplets = " + numberTriplets);
+        for ( i = 0; i<numberTriplets; i++ )
+        {
+            dataIndex = i*3;
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            b3 = binaryData[dataIndex + 2];
+
+            //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
+
+            l  = (byte)(b2 & 0x0f);
+            k  = (byte)(b1 & 0x03);
+
+            encodedIndex = i * 4;
+            byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
+            byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
+            byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
+
+            encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ];
+            //log.debug( "val2 = " + val2 );
+            //log.debug( "k4   = " + (k<<4) );
+            //log.debug(  "vak  = " + (val2 | (k<<4)) );
+            encodedData[encodedIndex+1] =
+                lookUpBase64Alphabet[ val2 | ( k<<4 )];
+            encodedData[encodedIndex+2] =
+                lookUpBase64Alphabet[ (l <<2 ) | val3 ];
+            encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
+        }
+
+        // form integral number of 6-bit groups
+        dataIndex    = i*3;
+        encodedIndex = i*4;
+        if (fewerThan24bits == EIGHTBIT )
+        {
+            b1 = binaryData[dataIndex];
+            k = (byte) ( b1 &0x03 );
+            //log.debug("b1=" + b1);
+            //log.debug("b1<<2 = " + (b1>>2) );
+            byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
+            encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
+            encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
+            encodedData[encodedIndex + 2] = PAD;
+            encodedData[encodedIndex + 3] = PAD;
+        }
+        else if (fewerThan24bits == SIXTEENBIT)
+        {
+
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex +1 ];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
+            byte val2 = ((b2 & SIGN) == 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
+
+            encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
+            encodedData[encodedIndex + 1] =
+                lookUpBase64Alphabet[ val2 | ( k<<4 )];
+            encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
+            encodedData[encodedIndex + 3] = PAD;
         }
 
-        return baos.toByteArray();
+        return encodedData;
     }
 
-    private static char[] readChars(File file)
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param binaryData Byte array containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decode( byte[] base64Data )
     {
-        CharArrayWriter caw = new CharArrayWriter();
-        try
-        {
-            Reader fr = new FileReader(file);
-            Reader in = new BufferedReader(fr);
-            int count = 0;
-            char[] buf = new char[16384];
-            while ((count = in.read(buf)) != -1)
+        // handle the edge case, so we don't have to worry about it later
+        if(base64Data.length == 0) { return new byte[0]; }
+
+        int      numberQuadruple    = base64Data.length/FOURBYTE;
+        byte     decodedData[]      = null;
+        byte     b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
+
+        // Throw away anything not in base64Data
+
+        int encodedIndex = 0;
+        int dataIndex    = 0;
+        {
+            // this sizes the output array properly - rlw
+            int lastData = base64Data.length;
+            // ignore the '=' padding
+            while (base64Data[lastData-1] == PAD)
             {
-                if (count > 0)
-                    caw.write(buf, 0, count);
+                if (--lastData == 0)
+                {
+                    return new byte[0];
+                }
             }
-            in.close();
+            decodedData = new byte[ lastData - numberQuadruple ];
         }
-        catch (Exception e)
+
+        for (int i = 0; i < numberQuadruple; i++)
         {
-            e.printStackTrace();
-        }
+            dataIndex = i * 4;
+            marker0   = base64Data[dataIndex + 2];
+            marker1   = base64Data[dataIndex + 3];
 
-        return caw.toCharArray();
-    }
+            b1 = base64Alphabet[base64Data[dataIndex]];
+            b2 = base64Alphabet[base64Data[dataIndex +1]];
 
-    private static void writeBytes(File file, byte[] data)
-    {
-        try
-        {
-            OutputStream fos = new FileOutputStream(file);
-            OutputStream os = new BufferedOutputStream(fos);
-            os.write(data);
-            os.close();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-    }
+            if (marker0 != PAD && marker1 != PAD)
+            {
+                //No PAD e.g 3cQl
+                b3 = base64Alphabet[ marker0 ];
+                b4 = base64Alphabet[ marker1 ];
+
+                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ;
+                decodedData[encodedIndex + 1] =
+                    (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
+                decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
+            }
+            else if (marker0 == PAD)
+            {
+                //Two PAD e.g. 3c[Pad][Pad]
+                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ;
+            }
+            else if (marker1 == PAD)
+            {
+                //One PAD e.g. 3cQ[Pad]
+                b3 = base64Alphabet[ marker0 ];
 
-    private static void writeChars(File file, char[] data)
-    {
-        try
-        {
-            Writer fos = new FileWriter(file);
-            Writer os = new BufferedWriter(fos);
-            os.write(data);
-            os.close();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
+                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 );
+                decodedData[encodedIndex + 1] =
+                    (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
+            }
+            encodedIndex += 3;
         }
+        return decodedData;
     }
-    ///////////////////////////////////////////////////
-    // end of test code.
-    ///////////////////////////////////////////////////
+
 
 }
Index: WebServer.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
retrieving revision 1.4
diff -u -r1.4 WebServer.java
--- WebServer.java	13 Feb 2002 00:51:55 -0000	1.4
+++ WebServer.java	19 Feb 2002 01:20:21 -0000
@@ -87,6 +87,9 @@
     protected static final byte[] ok = " 200 OK\r\n".getBytes();
     protected static final byte[] server = "Server: Apache XML-RPC 1.0\r\n".getBytes();
 
+    private static final String HTTP_11 = "HTTP/1.1";
+    private static final String STAR = "*";
+
     /**
      * This <em>can</em> be called from command line, but you'll have to edit and recompile
      * to change the server port or handler objects. By default, it sets up the following responders:
@@ -113,44 +116,44 @@
         XmlRpc.setKeepAlive (true);
         try
         {
-            WebServer webserver = new WebServer (p);
+            WebServer webserver = new WebServer(p);
             // webserver.setParanoid (true);
             // webserver.acceptClient ("192.168.*.*");
-            webserver.addHandler ("string", "Welcome to XML-RPC!");
-            webserver.addHandler ("math", Math.class);
-            webserver.addHandler ("auth", new AuthDemo());
-            webserver.addHandler ("$default", new Echo());
+            webserver.addHandler("string", "Welcome to XML-RPC!");
+            webserver.addHandler("math", Math.class);
+            webserver.addHandler("auth", new AuthDemo());
+            webserver.addHandler("$default", new Echo());
             // XmlRpcClients can be used as Proxies in XmlRpcServers which is a cool feature for applets.
-            webserver.addHandler ("mttf", new XmlRpcClient ("http://www.mailtothefuture.com:80/RPC2"));
-            System.err.println ("started web server on port "+p);
+            webserver.addHandler("mttf", new XmlRpcClient("http://www.mailtothefuture.com:80/RPC2"));
+            System.err.println("started web server on port "+p);
         }
         catch (IOException x)
         {
-            System.err.println ("Error creating web server: "+x);
+            System.err.println("Error creating web server: "+x);
         }
     }
 
     /**
       * Creates a Web server at the specified port number.
       */
-    public WebServer (int port) 
+    public WebServer(int port) 
         throws IOException
     {
-        this (port, null);
+        this(port, null);
     }
 
     /**
       * Creates a Web server at the specified port number and IP address.
       */
-    public WebServer (int port, InetAddress add) 
+    public WebServer(int port, InetAddress add) 
         throws IOException
     {
         this.port = port;
-        xmlrpc = new XmlRpcServer ();
-        accept = new Vector ();
-        deny = new Vector ();
-        threadpool = new Stack ();
-        runners = new ThreadGroup ("XML-RPC Runner");
+        xmlrpc = new XmlRpcServer();
+        accept = new Vector();
+        deny = new Vector();
+        threadpool = new Stack();
+        runners = new ThreadGroup("XML-RPC Runner");
 
         try
         {
@@ -193,7 +196,7 @@
 
     public void start()
     {
-        listener = new Thread (this, "XML-RPC Weblistener");
+        listener = new Thread(this, "XML-RPC Weblistener");
         listener.start();
     }
 
@@ -201,17 +204,17 @@
       * Register a handler object with this name. Methods of this objects will be
       * callable over XML-RPC as "name.method".
       */
-    public void addHandler (String name, Object target)
+    public void addHandler(String name, Object target)
     {
-        xmlrpc.addHandler (name, target);
+        xmlrpc.addHandler(name, target);
     }
 
     /**
       * Remove a handler object that was previously registered with this server.
       */
-    public void removeHandler (String name)
+    public void removeHandler(String name)
     {
-        xmlrpc.removeHandler (name);
+        xmlrpc.removeHandler(name);
     }
 
     /**
@@ -219,7 +222,7 @@
       * @see acceptClient(java.lang.String)
       * @see denyClient(java.lang.String)
       */
-    public void setParanoid (boolean p)
+    public void setParanoid(boolean p)
     {
         paranoid = p;
     }
@@ -232,17 +235,19 @@
       * @see denyClient(java.lang.String)
       * @see setParanoid(boolean)
       */
-    public void acceptClient (String address)
-            throws IllegalArgumentException
+    public void acceptClient(String address)
+        throws IllegalArgumentException
     {
         try
         {
-            AddressMatcher m = new AddressMatcher (address);
-            accept.addElement (m);
+            AddressMatcher m = new AddressMatcher(address);
+            accept.addElement(m);
         }
         catch (Exception x)
         {
-            throw new IllegalArgumentException ("\""+address + "\" does not represent a valid IP address");
+            throw new IllegalArgumentException("\"" + 
+                address + 
+                "\" does not represent a valid IP address");
         }
     }
 
@@ -254,35 +259,41 @@
       * @see acceptClient(java.lang.String)
       * @see setParanoid(boolean)
       */
-    public void denyClient (String address) throws IllegalArgumentException
+    public void denyClient(String address) throws IllegalArgumentException
     {
         try
         {
-            AddressMatcher m = new AddressMatcher (address);
-            deny.addElement (m);
+            AddressMatcher m = new AddressMatcher(address);
+            deny.addElement(m);
         }
         catch (Exception x)
         {
-            throw new IllegalArgumentException ("\""+address + "\" does not represent a valid IP address");
+            throw new IllegalArgumentException("\"" + 
+                address + 
+                "\" does not represent a valid IP address");
         }
     }
 
-    protected boolean checkSocket (Socket s)
+    protected boolean checkSocket(Socket s)
     {
-        int l = deny.size ();
-        byte address[] = s.getInetAddress ().getAddress ();
+        int l = deny.size();
+        byte address[] = s.getInetAddress().getAddress();
         for (int i = 0; i < l; i++)
         {
-            AddressMatcher match = (AddressMatcher) deny.elementAt (i);
-            if (match.matches (address))
+            AddressMatcher match = (AddressMatcher)deny.elementAt(i);
+            if (match.matches(address))
+            {
                 return false;
+            }
         }
-        l = accept.size ();
+        l = accept.size();
         for (int i = 0; i < l; i++)
         {
-            AddressMatcher match = (AddressMatcher) accept.elementAt (i);
-            if (match.matches (address))
+            AddressMatcher match = (AddressMatcher)accept.elementAt(i);
+            if (match.matches(address))
+            {
                 return true;
+            }
         }
         return false;
     }
@@ -299,14 +310,15 @@
                 try
                 {
                     Socket socket = serverSocket.accept();
-                    if (!paranoid || checkSocket (socket))
+                    if (!paranoid || checkSocket(socket))
                     {
-                        Runner runner = getRunner ();
+                        Runner runner = getRunner();
                         runner.handle (socket);
-                        // new Connection (socket);
                     }
                     else
-                        socket.close ();
+                    {
+                        socket.close();
+                    }
                 }
                 catch (InterruptedIOException checkState)
                 {
@@ -341,14 +353,15 @@
                 serverSocket = null;
             }
             catch (IOException ignore)
-                {}
+            {
+            }
         }
     }
 
     /**
       * Stop listening on the server port.
       */
-    public void shutdown ()
+    public void shutdown()
     {
         if (listener != null)
         {
@@ -358,19 +371,19 @@
         }
     }
 
-
-
-    protected Runner getRunner ()
+    protected Runner getRunner()
     {
         try
         {
-            return (Runner) threadpool.pop ();
+            return (Runner)threadpool.pop();
         }
         catch (EmptyStackException empty)
         {
             if (runners.activeCount () > 255)
+            {
                 throw new RuntimeException ("System overload");
-            return new Runner ();
+            }
+            return new Runner();
         }
     }
 
@@ -381,28 +394,27 @@
 
     class Runner implements Runnable
     {
-
         Thread thread;
         Connection con;
         int count;
 
-        public synchronized void handle (Socket socket)
+        public synchronized void handle(Socket socket)
             throws IOException
         {
-            con = new Connection (socket);
+            con = new Connection(socket);
             count = 0;
             if (thread == null || !thread.isAlive())
             {
-                thread = new Thread (runners, this);
-                thread.start ();
+                thread = new Thread(runners, this);
+                thread.start();
             }
             else
             {
-                this.notify ();
+                this.notify();
             }
         }
 
-        public void run ()
+        public void run()
         {
             while (Thread.currentThread () == thread)
             {
@@ -411,14 +423,15 @@
                 con = null;
 
                 if (count > 200 || threadpool.size() > 20)
+                {
                     return;
-
-                synchronized (this)
+                }
+                synchronized(this)
                 {
-                    releaseRunner (this);
+                    releaseRunner(this);
                     try
                     {
-                        this.wait ();
+                        this.wait();
                     }
                     catch (InterruptedException ir)
                     {
@@ -427,19 +440,15 @@
                 }
             }
         }
-
-    } // end class Runner
-
+    }
 
     class Connection implements Runnable
     {
-
         private Socket socket;
         private BufferedInputStream input;
         private BufferedOutputStream output;
-        // private Thread responder;
-        private long lastRequest;
         private String user, password;
+        byte[] buffer;
 
         public Connection (Socket socket) throws IOException
         {
@@ -447,13 +456,11 @@
             socket.setSoTimeout (30000);
 
             this.socket = socket;
-            input = new BufferedInputStream (socket.getInputStream());
-            output = new BufferedOutputStream (socket.getOutputStream());
-            // responder = new Thread (this, "xmlrpc-worker");
-            // responder.start();
+            input = new BufferedInputStream(socket.getInputStream());
+            output = new BufferedOutputStream(socket.getOutputStream());
         }
 
-        public void run ()
+        public void run()
         {
             try
             {
@@ -463,43 +470,52 @@
                 {
                     // reset user authentication
                     user = password = null;
-                    String line = readLine ();
+                    String line = readLine();
                     // Netscape sends an extra \n\r after bodypart, swallow it
-                    if ("".equals (line))
+                    if (line != null && line.length() == 0)
+                    {
                         line = readLine();
+                    }
                     if (XmlRpc.debug)
+                    {
                         System.err.println (line);
-                    // get time of last request
-                    lastRequest = System.currentTimeMillis ();
+                    }
                     int contentLength = -1;
 
                     // tokenize first line of HTTP request
                     StringTokenizer tokens = new StringTokenizer(line);
                     String method = tokens.nextToken();
-                    String uri = tokens.nextToken ();
-                    String httpversion = tokens.nextToken ();
-                    keepalive = XmlRpc.getKeepAlive() && "HTTP/1.1".equals (httpversion);
+                    String uri = tokens.nextToken();
+                    String httpversion = tokens.nextToken();
+                    keepalive = XmlRpc.getKeepAlive() && HTTP_11.equals(httpversion);
                     do
                     {
                         line = readLine();
                         if (line != null)
                         {
                             if (XmlRpc.debug)
-                                System.err.println (line);
-                            String lineLower = line.toLowerCase ();
-                            if (lineLower.startsWith ("content-length:"))
-                                contentLength = Integer.parseInt (
-                                        line.substring (15).trim ());
-                            if (lineLower.startsWith ("connection:"))
+                            {
+                                System.err.println(line);
+                            }
+                            String lineLower = line.toLowerCase();
+                            if (lineLower.startsWith("content-length:"))
+                            {
+                                contentLength = Integer.parseInt(
+                                        line.substring(15).trim());
+                            }
+                            if (lineLower.startsWith("connection:"))
+                            {
                                 keepalive = XmlRpc.getKeepAlive() &&
                                         lineLower.indexOf ("keep-alive")
                                         > -1;
-                            if (lineLower.startsWith ("authorization: basic "))
+                            }
+                            if (lineLower.startsWith("authorization: basic "))
+                            {
                                 parseAuth (line);
+                            }
                         }
                     }
-                    while (line != null && ! line.equals(""))
-                        ;
+                    while (line != null && line.length() != 0);
 
                     if ("POST".equalsIgnoreCase (method))
                     {
@@ -508,35 +524,38 @@
                                 contentLength);
                         byte result[] =
                                 xmlrpc.execute (sin, user, password);
-                        output.write (httpversion.getBytes());
-                        output.write (ok);
-                        output.write (server);
+                        output.write(httpversion.getBytes());
+                        output.write(ok);
+                        output.write(server);
                         if (keepalive)
-                            output.write (conkeep);
+                        {
+                            output.write(conkeep);
+                        }
                         else
+                        {
                             output.write (conclose);
-                        output.write (ctype);
-                        output.write (clength);
-                        output.write ( Integer.toString (
+                        }
+                        output.write(ctype);
+                        output.write(clength);
+                        output.write(Integer.toString(
                                 result.length).getBytes());
-                        output.write (doubleNewline);
-                        output.write (result);
-                        output.flush ();
+                        output.write(doubleNewline);
+                        output.write(result);
+                        output.flush();
                     }
                     else
                     {
-                        output.write (httpversion.getBytes());
-                        output.write (" 400 Bad Request\r\n".getBytes());
-                        output.write (server);
-                        output.write ("\r\n".getBytes());
-                        output.write ( ("Method "+method +
-                                " not implemented (try POST)"). getBytes());
-                        output.flush ();
+                        output.write(httpversion.getBytes());
+                        output.write(" 400 Bad Request\r\n".getBytes());
+                        output.write(server);
+                        output.write("\r\n".getBytes());
+                        output.write(("Method "+method +
+                                " not implemented (try POST)").getBytes());
+                        output.flush();
                         keepalive = false;
                     }
                 }
-                while (keepalive)
-                    ;
+                while (keepalive);
             }
             catch (Exception exception)
             {
@@ -546,16 +565,22 @@
                     exception.printStackTrace ();
                 }
             }
-            finally { try
+            finally
+            {
+                try
                 {
-                    socket.close();
+                    if (socket != null)
+                    {
+                        socket.close();
+                    }
                 }
                 catch (IOException ignore)
-                    {}
-            } }
+                {
+                }
+            }
+        }
 
-        byte[] buffer;
-        private String readLine () throws IOException
+        private String readLine() throws IOException
         {
             if (buffer == null)
             {
@@ -567,51 +592,63 @@
             {
                 next = input.read();
                 if (next < 0 || next == '\n')
+                {
                     break;
+                }
                 if (next != '\r')
                 {
                     buffer[count++] = (byte) next;
                 }
                 if (count >= 512)
+                {
                     throw new IOException ("HTTP Header too long");
+                }
             }
             return new String (buffer, 0, count);
         }
 
-        private void parseAuth (String line)
+        private void parseAuth(String line)
         {
             try
             {
                 byte[] c =
-                        Base64.decode (line.substring (21).toCharArray());
+                        Base64.decode (line.substring(21).getBytes());
                 String str = new String (c);
-                int col = str.indexOf (":");
+                int col = str.indexOf (':');
                 user = str.substring (0, col);
                 password = str.substring (col + 1);
             }
             catch (Throwable ignore)
-                {}
+            {
+            }
         }
-
     }
 
     class AddressMatcher
     {
         int pattern[];
-
+        
         public AddressMatcher (String address) throws Exception
         {
             pattern = new int[4];
-            StringTokenizer st = new StringTokenizer (address, ".");
-            if (st.countTokens () != 4)
-                throw new Exception ("\""+address + "\" does not represent a valid IP address");
+            StringTokenizer st = new StringTokenizer(address, ".");
+            if (st.countTokens() != 4)
+            {
+                throw new Exception ("\"" + 
+                    address + 
+                    "\" does not represent a valid IP address");
+            }
             for (int i = 0; i < 4; i++)
             {
-                String next = st.nextToken ();
-                if ("*".equals (next))
+                String next = st.nextToken();
+                if (STAR.equals(next))
+                {
                     pattern[i] = 256;
+                }
                 else
-                    pattern[i] = (byte) Integer.parseInt (next);
+                {
+                    pattern[i] = (byte) Integer.parseInt(next);
+                }
             }
         }
 
@@ -620,10 +657,13 @@
             for (int i = 0; i < 4; i++)
             {
                 if (pattern[i] > 255)// wildcard
-
+                {
                     continue;
+                }
                 if (pattern[i] != address[i])
+                {
                     return false;
+                }
             }
             return true;
         }
Index: XmlRpc.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
retrieving revision 1.17
diff -u -r1.17 XmlRpc.java
--- XmlRpc.java	18 Feb 2002 23:22:29 -0000	1.17
+++ XmlRpc.java	19 Feb 2002 01:20:24 -0000
@@ -587,7 +587,7 @@
                     }
                     break;
                 case BASE64:
-                    value = Base64.decode (cdata.toCharArray());
+                    value = Base64.decode (cdata.getBytes());
                     break;
                 case STRING:
                     value = cdata;
@@ -700,7 +700,8 @@
             else if (obj instanceof byte[])
             {
                 startElement("base64");
-                write(Base64.encode((byte[]) obj));
+                // FIXME: Yucky! Find a better way!
+                write(new String(Base64.encode((byte[]) obj)).toCharArray());
                 endElement("base64");
             }
             else if (obj instanceof Vector)
Index: XmlRpcClient.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClient.java,v
retrieving revision 1.6
diff -u -r1.6 XmlRpcClient.java
--- XmlRpcClient.java	18 Feb 2002 23:22:29 -0000	1.6
+++ XmlRpcClient.java	19 Feb 2002 01:20:25 -0000
@@ -121,12 +121,12 @@
     public void setBasicAuthentication (String user, String password)
     {
         if (user == null || password == null)
+        {
             auth = null;
+        }
         else
         {
-            char[] basicAuth =
-                    Base64.encode ((user + ":"+password).getBytes());
-            auth = new String (basicAuth).trim();
+            auth = new String (Base64.encode((user + ':' + password).getBytes())).trim();
         }
     }
 
