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]>
