I'd love it if people of comments on this, and/or time to kick the
tires.  Also, if anyone has any ideas regarding line wrapping for
encode(), by all means please speak up...

[EMAIL PROTECTED] writes:

> dlr         2002/11/01 14:06:10
> 
>   Modified:    src/java/org/apache/xmlrpc Base64.java
>                src/test/org/apache/xmlrpc Base64Test.java
>   Log:
>   * Base64.java
>     Added a new discardWhitespace(byte[]) function which is called at
>     the beginning of decode(byte[]) to perform pre-processing on its
>     arguments.  Filtering whitespace the body of decode() would be both
>     more memory and CPU-efficient, but I'm not comfortable enough with
>     the the code to make that invasive of a change.  I'm curious what
>     the Tomcat folks are doing here these days.
>   
>     I noticed that encode() isn't line wrapping at 76 characters --
>     should we log this as a problem?  What effect is this going to have
>     on our interop?
>   
>   * Base64Test.java
>     Renamed the mis-named testWriter() to testBase64().  Implemented
>     more tests for encoding/decoding using output from Perl's
>     MIME::Base64 module.
>   
>   http://issues.apache.org/bugzilla/show_bug.cgi?id=9931
>   
>   Revision  Changes    Path
>   1.4       +75 -4     xml-rpc/src/java/org/apache/xmlrpc/Base64.java
>   
>   Index: Base64.java
>   ===================================================================
>   RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
>   retrieving revision 1.3
>   retrieving revision 1.4
>   diff -u -u -r1.3 -r1.4
>   --- Base64.java     20 Mar 2002 15:11:03 -0000      1.3
>   +++ Base64.java     1 Nov 2002 22:06:10 -0000       1.4
>   @@ -63,6 +63,9 @@
>     *
>     */
>    
>   +import java.util.Enumeration;
>   +import java.util.Vector;
>   +
>    /**
>     * This class provides encode/decode for RFC 2045 Base64 as defined by
>     * RFC 2045, N. Freed and N. Borenstein.  <a
>   @@ -71,7 +74,8 @@
>     * Internet Message Bodies. Reference 1996
>     *
>     * @author Jeffrey Rodriguez
>   - * @version $Id$
>   + * @author Daniel Rall
>   + * @since 1.2
>     */
>    public final class  Base64
>    {
>   @@ -254,6 +258,10 @@
>         */
>        public static byte[] decode( byte[] base64Data )
>        {
>   +        // RFC 2045 suggests line wrapping at (no more than) 76
>   +        // characters -- we may have embedded whitespace.
>   +        base64Data = discardWhitespace(base64Data);
>   +
>            // handle the edge case, so we don't have to worry about it later
>            if(base64Data.length == 0) { return new byte[0]; }
>    
>   @@ -316,5 +324,68 @@
>                encodedIndex += 3;
>            }
>            return decodedData;
>   +    }
>   +
>   +    /**
>   +     * Discards any whitespace from a base-64 encoded block.
>   +     *
>   +     * @param data The base-64 encoded data to discard the whitespace
>   +     * from.
>   +     * @return The data, less whitespace (see RFC 2045).
>   +     */
>   +    static byte[] discardWhitespace(byte[] data)
>   +    {
>   +        // Locate any regions of whitespace within our data.
>   +        int nbrToDiscard = 0;
>   +        Vector discardRegions = new Vector();
>   +        boolean discarding = false;
>   +        for (int i = 0; i < data.length; i++)
>   +        {
>   +            switch (data[i])
>   +            {
>   +            case (byte) ' ':
>   +            case (byte) '\n':
>   +            case (byte) '\r':
>   +            case (byte) '\t':
>   +                if (!discarding)
>   +                {
>   +                    int[] region = { i, data.length };
>   +                    discardRegions.addElement(region);
>   +                    discarding = true;
>   +                }
>   +                nbrToDiscard++;
>   +                break;
>   +
>   +            default:
>   +                if (discarding)
>   +                {
>   +                    // End region to discard.
>   +                    ((int []) discardRegions.lastElement())[1] = i;
>   +                    discarding = false;
>   +                }
>   +            }
>   +        }
>   +
>   +        if (nbrToDiscard > 0)
>   +        {
>   +            // Groom whitespace from the data.
>   +            byte[] groomed = new byte[data.length - nbrToDiscard];
>   +            int srcOffset = 0;
>   +            int destOffset = 0;
>   +            int[] region = null;
>   +            Enumeration enum = discardRegions.elements();
>   +            while (enum.hasMoreElements())
>   +            {
>   +                region = (int []) enum.nextElement();
>   +                int len = region[0] - srcOffset;
>   +                System.arraycopy(data, srcOffset, groomed, destOffset, len);
>   +                destOffset += len;
>   +                srcOffset = region[1];
>   +            }
>   +            System.arraycopy(data, srcOffset, groomed, destOffset,
>   +                             data.length - region[1]);
>   +            data = groomed;
>   +        }
>   +        return data;
>        }
>    }
>   
>   
>   
>   1.7       +30 -1     xml-rpc/src/test/org/apache/xmlrpc/Base64Test.java
>   
>   Index: Base64Test.java
>   ===================================================================
>   RCS file: /home/cvs/xml-rpc/src/test/org/apache/xmlrpc/Base64Test.java,v
>   retrieving revision 1.6
>   retrieving revision 1.7
>   diff -u -u -r1.6 -r1.7
>   --- Base64Test.java 27 Sep 2002 23:40:42 -0000      1.6
>   +++ Base64Test.java 1 Nov 2002 22:06:10 -0000       1.7
>   @@ -75,6 +75,29 @@
>            "foo bar\nbaz"
>        };
>    
>   +    private static final String UNENCODED =
>   +        "This module provides functions to encode and decode\n" +
>   +        "strings into the Base64 encoding specified in RFC 2045 -\n" +
>   +        "MIME (Multipurpose Internet Mail Extensions). The Base64\n" +
>   +        "encoding is designed to represent arbitrary sequences of\n" +
>   +        "octets in a form that need not be humanly readable. A\n" +
>   +        "65-character subset ([A-Za-z0-9+/=]) of US-ASCII is used,\n" +
>   +        "enabling 6 bits to be represented per printable character.";
>   +
>   +    /**
>   +     * The string <code>UNENCODED</code> after being encoded by Perl's
>   +     * MIME::Base64 module.
>   +     */
>   +    private static final String ENCODED =
>   +        
>"VGhpcyBtb2R1bGUgcHJvdmlkZXMgZnVuY3Rpb25zIHRvIGVuY29kZSBhbmQgZGVjb2RlCnN0cmlu\n" +
>   +        
>"Z3MgaW50byB0aGUgQmFzZTY0IGVuY29kaW5nIHNwZWNpZmllZCBpbiBSRkMgMjA0NSAtCk1JTUUg\n" +
>   +        
>"KE11bHRpcHVycG9zZSBJbnRlcm5ldCBNYWlsIEV4dGVuc2lvbnMpLiBUaGUgQmFzZTY0CmVuY29k\n" +
>   +        
>"aW5nIGlzIGRlc2lnbmVkIHRvIHJlcHJlc2VudCBhcmJpdHJhcnkgc2VxdWVuY2VzIG9mCm9jdGV0\n" +
>   +        
>"cyBpbiBhIGZvcm0gdGhhdCBuZWVkIG5vdCBiZSBodW1hbmx5IHJlYWRhYmxlLiBBCjY1LWNoYXJh\n" +
>   +        
>"Y3RlciBzdWJzZXQgKFtBLVphLXowLTkrLz1dKSBvZiBVUy1BU0NJSSBpcyB1c2VkLAplbmFibGlu\n" +
>   +        "ZyA2IGJpdHMgdG8gYmUgcmVwcmVzZW50ZWQgcGVyIHByaW50YWJsZSBjaGFyYWN0ZXIu";
>   +
>   +
>        /**
>         * Constructor
>         */
>   @@ -91,7 +114,7 @@
>            return new TestSuite(Base64Test.class);
>        }
>    
>   -    public void testWriter()
>   +    public void testBase64()
>            throws Exception
>        {
>            try
>   @@ -107,6 +130,12 @@
>                    assertEquals(raw, decoded);
>                    assertEquals(TEST_DATA[i], new String(decoded));
>                }
>   +
>   +            // FIXME: The Base64.encode() function doesn't wrap at 76 chars.
>   +            //assertEquals(Base64.encode(UNENCODED.getBytes()),
>   +            //             ENCODED.getBytes());
>   +            assertEquals(UNENCODED.getBytes(),
>   +                         Base64.decode(ENCODED.getBytes()));
>            }
>            catch (Exception e)
>            {
>   
>   
>   

-- 

Daniel Rall <[EMAIL PROTECTED]>

Reply via email to