Author: mturk Date: Tue Jun 30 06:14:13 2009 New Revision: 789570 URL: http://svn.apache.org/viewvc?rev=789570&view=rev Log: Use byte and char arrays instead casting
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Base64.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java?rev=789570&r1=789569&r2=789570&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java Tue Jun 30 06:14:13 2009 @@ -23,6 +23,7 @@ * Character Classification routines. * * @author Mladen Turk + * @since Runtime 1.0 */ public final class Ascii { Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Base64.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Base64.java?rev=789570&r1=789569&r2=789570&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Base64.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Base64.java Tue Jun 30 06:14:13 2009 @@ -19,7 +19,14 @@ import java.io.UnsupportedEncodingException; /** - * Base64 encoding enumeration + * Provides Base64 encoding and decoding as defined by {...@code RFC 2045}. + * <p> + * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> + * from RFC 2045 <cite>Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> + * by Freed and Borenstein. + * </p> + * + * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a> * * @author Mladen Turk * @@ -33,12 +40,29 @@ } /** - * Wrap encoded lines after {...@code COLS} character {...@code (default 72)}. + * Wrap encoded lines after {...@value} character. + * <p> + * The {...@value} character limit does not count the trailing {...@code CRLF}, + * but counts all other characters, including any equal signs. + * </p> + * + * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a> */ - public static final int COLS = 72; + public static final int COLS = 76; + private static final String CHARSET = "ISO-8859-1"; private static final char padding = '='; + private static final char CR = '\r'; private static final char LF = '\n'; - private static final char[] basis64 = { + private static final byte[] base64b = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' + }; + private static final char[] base64c = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', @@ -50,9 +74,9 @@ // ASCII table private static final byte[] pr2six = { - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 63, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64, 65, 65, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 62, 65, 65, 65, 64, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 62, 65, 65, 65, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 65, 65, 65, 65, 65, 65, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 65, 65, 65, 65, 65, @@ -85,11 +109,13 @@ { int dstlen; + if (len < 1) + len = src.length - srcPos; dstlen = (((len + 2) / 3) * 4); if (wrap == -1) wrap = COLS; if (wrap > 0) - dstlen += (dstlen / wrap); + dstlen += ((dstlen / wrap) * 2); return dstlen; } @@ -106,6 +132,8 @@ int[] inp = new int[3]; int[] out = new int[4]; + if (len < 1) + len = src.length - srcPos; if (wrap == -1) wrap = COLS; while (len >= 3) { @@ -121,13 +149,15 @@ if (dp + 4 > dl) throw new IndexOutOfBoundsException("Destination is too small"); - dst[dp++] = (byte)basis64[out[0]]; - dst[dp++] = (byte)basis64[out[1]]; - dst[dp++] = (byte)basis64[out[2]]; - dst[dp++] = (byte)basis64[out[3]]; + dst[dp++] = base64b[out[0]]; + dst[dp++] = base64b[out[1]]; + dst[dp++] = base64b[out[2]]; + dst[dp++] = base64b[out[3]]; if (wrap > 0) { - if (++oc % (wrap / 4) == 0) + if (++oc % (wrap / 4) == 0) { + dst[dp++] = CR; dst[dp++] = LF; + } } } // Pad with remaining 1 or 2 bytes @@ -142,12 +172,12 @@ if (dp + 4 > dl) throw new IndexOutOfBoundsException("Destination is too small"); - dst[dp++] = (byte)basis64[out[0]]; - dst[dp++] = (byte)basis64[out[1]]; + dst[dp++] = base64b[out[0]]; + dst[dp++] = base64b[out[1]]; if (len == 1) dst[dp++] = padding; else - dst[dp++] = (byte)basis64[out[2]]; + dst[dp++] = base64b[out[2]]; dst[dp++] = padding; } return dp - dstPos; @@ -165,6 +195,8 @@ int[] inp = new int[3]; int[] out = new int[4]; + if (len < 1) + len = src.length - srcPos; if (wrap == -1) wrap = COLS; while (len >= 3) { @@ -180,13 +212,15 @@ if (dp + 4 > dl) throw new IndexOutOfBoundsException("Destination is too small"); - dst[dp++] = basis64[out[0]]; - dst[dp++] = basis64[out[1]]; - dst[dp++] = basis64[out[2]]; - dst[dp++] = basis64[out[3]]; + dst[dp++] = base64c[out[0]]; + dst[dp++] = base64c[out[1]]; + dst[dp++] = base64c[out[2]]; + dst[dp++] = base64c[out[3]]; if (wrap > 0) { - if (++oc % (wrap / 4) == 0) + if (++oc % (wrap / 4) == 0) { + dst[dp++] = CR; dst[dp++] = LF; + } } } // Pad with remaining 1 or 2 bytes @@ -201,12 +235,12 @@ if (dp + 4 > dl) throw new IndexOutOfBoundsException("Destination is too small"); - dst[dp++] = basis64[out[0]]; - dst[dp++] = basis64[out[1]]; + dst[dp++] = base64c[out[0]]; + dst[dp++] = base64c[out[1]]; if (len == 1) dst[dp++] = padding; else - dst[dp++] = basis64[out[2]]; + dst[dp++] = base64c[out[2]]; dst[dp++] = padding; } return dp - dstPos; @@ -215,7 +249,7 @@ /** * Encode String using Base64 encoding. * <p> - * Input string is encoded from the {...@code ISO 8859-1} charset. + * Input string is encoded from the {...@code ISO-8859-1} charset. * </p> * * @param string String to encode. @@ -226,7 +260,7 @@ public static String encode(String string, int wrap) { try { - byte [] data = string.getBytes("8859_1"); + byte [] data = string.getBytes(CHARSET); char [] dest = new char[encodeLength(data, 0, data.length, 0)]; int nencoded = encode(data, 0, dest, 0, data.length, 0); @@ -267,16 +301,17 @@ int lf = 0; int nprbytes; + if (len < 1) + len = src.length - srcPos; while (sc < len) { int ch = (int)src[srcPos + sc] & 0xFF; if (pr2six[ch] == 64) lf++; if (pr2six[ch] == 65) break; - sc ++; + sc++; } - nprbytes = sc; - return ((nprbytes + 3) / 4) * 3 - lf; + return ((sc + 3) / 4) * 3 - lf; } public static int decode(byte[] src, int srcPos, byte[] dst, @@ -288,12 +323,18 @@ int dp = dstPos; int nprbytes; + if (len < 1) + len = src.length - srcPos; while (sc < len && pr2six[(int)src[srcPos + sc++] & 0xFF] <= 64); nprbytes = sc - 1; - while (nprbytes > 4) { - if (src[sp + 0] == LF) { + if (src[sp] == CR || src[sp] == LF) { + /* Just skip any CRLF combination. + * We don't care for format the validity. + * For us any line ending is valid, eg. + * LF, CRLF, CR, LFCR, ... + */ sp += 1; nprbytes -= 1; continue; @@ -319,7 +360,7 @@ public static String decode(String string) { try { - byte [] data = string.getBytes("8859_1"); + byte [] data = string.getBytes(CHARSET); byte [] dest = new byte[decodeLength(data, 0, data.length)]; int ndecoded = decode(data, 0, dest, 0, data.length);