remm 01/04/04 11:12:19 Modified: catalina/src/share/org/apache/catalina/util Base64.java Log: - Update to the new version of the Xerces Base64 encoder/decoder. The old one had problems encoding binary content. Revision Changes Path 1.2 +77 -49 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Base64.java Index: Base64.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Base64.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Base64.java 2000/08/11 17:01:49 1.1 +++ Base64.java 2001/04/04 18:12:19 1.2 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Base64.java,v 1.1 2000/08/11 17:01:49 craigmcc Exp $ - * $Revision: 1.1 $ - * $Date: 2000/08/11 17:01:49 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Base64.java,v 1.2 2001/04/04 18:12:19 remm Exp $ + * $Revision: 1.2 $ + * $Date: 2001/04/04 18:12:19 $ * * ==================================================================== * @@ -67,36 +67,35 @@ /** * This class provides encode/decode for RFC 2045 Base64 as - * defined by RFC 2045, N. Freed and N. Borenstein. + * defined by RFC 2045, N. Freed and N. Borenstein. * RFC 2045: Multipurpose Internet Mail Extensions (MIME) * Part One: Format of Internet Message Bodies. Reference - * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt + * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt * This class is used by XML Schema binary format validation * * @author Jeffrey Rodriguez - * @version $Revision: 1.1 $ $Date: 2000/08/11 17:01:49 $ + * @version $Id: Base64.java,v 1.2 2001/04/04 18:12:19 remm Exp $ */ -public final class Base64 { - - - static private final int BASELENGTH = 255; - static private final int LOOKUPLENGTH = 63; +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 byte PAD = ( byte ) '='; - static private byte [] base64Alphabet = new byte[BASELENGTH]; + static private final int SIGN = -128; + static private final byte PAD = ( byte ) '='; + static private final boolean fDebug = false; + static private byte [] base64Alphabet = new byte[BASELENGTH]; static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; + static { for (int i = 0; i<BASELENGTH; i++ ) { - base64Alphabet[i] = -1; + base64Alphabet[i] = -1; } for ( int i = 'Z'; i >= 'A'; i-- ) { base64Alphabet[i] = (byte) (i-'A'); @@ -109,10 +108,10 @@ base64Alphabet[i] = (byte) (i-'0' + 52); } - base64Alphabet['+'] = 62; + base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; - for (int i = 0; i<=25; i++ ) + for (int i = 0; i<=25; i++ ) lookUpBase64Alphabet[i] = (byte) ('A'+i ); for (int i = 26, j = 0; i<=51; i++, j++ ) @@ -120,17 +119,23 @@ for (int i = 52, j = 0; i<=61; i++, j++ ) lookUpBase64Alphabet[i] = (byte) ('0' + j ); + lookUpBase64Alphabet[62] = (byte) '+'; + lookUpBase64Alphabet[63] = (byte) '/'; } + public static boolean isBase64( String isValidString ){ + return( isArrayByteBase64( isValidString.getBytes())); + } + - static boolean isBase64( byte octect ) { + public static boolean isBase64( byte octect ) { //shall we ignore white space? JEFF?? - return(octect == PAD || base64Alphabet[octect] != -1 ); + return(octect == PAD || base64Alphabet[octect] != -1 ); } - static boolean isArrayByteBase64( byte[] arrayOctect ) { + public static boolean isArrayByteBase64( byte[] arrayOctect ) { int length = arrayOctect.length; if ( length == 0 ) return false; @@ -143,13 +148,13 @@ /** * Encodes hex octects into Base64 - * + * * @param binaryData Array containing binaryData * @return Encoded Base64 array */ - public byte[] encode( byte[] binaryData ) { + public static byte[] encode( byte[] binaryData ) { int lengthDataBits = binaryData.length*EIGHTBIT; - int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; + int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; byte encodedData[] = null; @@ -164,22 +169,38 @@ int encodedIndex = 0; int dataIndex = 0; int i = 0; + if (fDebug ) { + System.out.println("number of triplets = " + numberTriplets ); + } for ( i = 0; i<numberTriplets; i++ ) { dataIndex = i*3; - b1 = binaryData[dataIndex]; + b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; b3 = binaryData[dataIndex + 2]; + if (fDebug) { + System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 ); + } + l = (byte)(b2 & 0x0f); k = (byte)(b1 & 0x03); encodedIndex = i*4; - encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; - encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | -( k<<4 )]; - encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | -( b3>>6)]; + 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 ]; + if (fDebug) { + System.out.println( "val2 = " + val2 ); + System.out.println( "k4 = " + (k<<4)); + System.out.println( "vak = " + (val2 | (k<<4))); + } + + encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )]; + encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ]; encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; } @@ -189,8 +210,13 @@ if (fewerThan24bits == EIGHTBIT ) { b1 = binaryData[dataIndex]; k = (byte) ( b1 &0x03 ); - encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; - encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; + if (fDebug ) { + System.out.println("b1=" + b1); + System.out.println("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 ) { @@ -199,10 +225,13 @@ b2 = binaryData[dataIndex +1 ]; l = ( byte ) ( b2 &0x0f ); k = ( byte ) ( b1 &0x03 ); - encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; - encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) -| ( k<<4 )]; - encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; + + 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 encodedData; @@ -211,11 +240,11 @@ /** * Decodes Base64 data into octects - * + * * @param binaryData Byte array containing Base64 data * @return Array containind decoded data. */ - public byte[] decode( byte[] base64Data ) { + public static byte[] decode( byte[] base64Data ) { int numberQuadruple = base64Data.length/FOURBYTE; byte decodedData[] = null; byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; @@ -229,10 +258,10 @@ for (int i = 0; i<numberQuadruple; i++ ) { dataIndex = i*4; - marker0 = base64Data[dataIndex +2]; - marker1 = base64Data[dataIndex +3]; + marker0 = base64Data[dataIndex +2]; + marker1 = base64Data[dataIndex +3]; - b1 = base64Alphabet[base64Data[dataIndex]]; + b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex +1]]; if ( marker0 != PAD && marker1 != PAD ) { //No PAD e.g 3cQl @@ -240,20 +269,18 @@ 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 ); + 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 ) ; - decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); - decodedData[encodedIndex+2] = (byte) 0; + decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; + decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); + decodedData[encodedIndex+2] = (byte) 0; } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[ marker0 ]; decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); - decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( -(b3>>2) & 0xf) ); - decodedData[encodedIndex+2] = (byte)( b3<<6); + decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); + decodedData[encodedIndex+2] = (byte)( b3<<6); } encodedIndex += 3; } @@ -261,4 +288,5 @@ } } +