KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > utils > Base64


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.utils;
59
60
61
62 /**
63  * This class provides encode/decode for RFC 2045 Base64 as
64  * defined by RFC 2045, N. Freed and N. Borenstein.
65  * RFC 2045: Multipurpose Internet Mail Extensions (MIME)
66  * Part One: Format of Internet Message Bodies. Reference
67  * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
68  * This class is used by XML Schema binary format validation
69  *
70  * This implementation does not encode/decode streaming
71  * data. You need the data that you will encode/decode
72  * already on a byte arrray.
73  *
74  * @author Jeffrey Rodriguez
75  * @author Sandy Gao
76  * @version $Id: Base64.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
77  */

78 public final class Base64 {
79     static private final int BASELENGTH = 255;
80     static private final int LOOKUPLENGTH = 64;
81     static private final int TWENTYFOURBITGROUP = 24;
82     static private final int EIGHTBIT = 8;
83     static private final int SIXTEENBIT = 16;
84     static private final int SIXBIT = 6;
85     static private final int FOURBYTE = 4;
86     static private final int SIGN = -128;
87     static private final byte PAD = ( byte ) '=';
88     static private final boolean fDebug = false;
89     static private byte [] base64Alphabet = new byte[BASELENGTH];
90     static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
91
92
93     static {
94
95         for (int i = 0; i<BASELENGTH; i++) {
96             base64Alphabet[i] = -1;
97         }
98         for (int i = 'Z'; i >= 'A'; i--) {
99             base64Alphabet[i] = (byte) (i-'A');
100         }
101         for (int i = 'z'; i>= 'a'; i--) {
102             base64Alphabet[i] = (byte) ( i-'a' + 26);
103         }
104
105         for (int i = '9'; i >= '0'; i--) {
106             base64Alphabet[i] = (byte) (i-'0' + 52);
107         }
108
109         base64Alphabet['+'] = 62;
110         base64Alphabet['/'] = 63;
111
112         for (int i = 0; i<=25; i++)
113             lookUpBase64Alphabet[i] = (byte) ('A'+i );
114
115         for (int i = 26, j = 0; i<=51; i++, j++)
116             lookUpBase64Alphabet[i] = (byte) ('a'+ j );
117
118         for (int i = 52, j = 0; i<=61; i++, j++)
119             lookUpBase64Alphabet[i] = (byte) ('0' + j );
120         lookUpBase64Alphabet[62] = (byte) '+';
121         lookUpBase64Alphabet[63] = (byte) '/';
122
123     }
124
125     protected static boolean isWhiteSpace (byte octect) {
126         return(octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
127     }
128
129     protected static boolean isPad (byte octect) {
130         return(octect == PAD);
131     }
132
133     protected static boolean isData (byte octect) {
134         return( base64Alphabet[octect] != -1);
135     }
136
137     public static boolean isBase64( String JavaDoc isValidString ) {
138         if (isValidString == null)
139             return false;
140         return( isArrayByteBase64( isValidString.getBytes()));
141     }
142
143
144     public static boolean isBase64( byte octect ) {
145         return( isWhiteSpace(octect) || isPad(octect) || isData(octect));
146     }
147
148
149     /**
150      * remove WhiteSpace from MIME containing encoded Base64
151      * data.
152      * e.g.
153      * " sdffferererrereresfsdfsdfsdff\n\r
154      * iiiiiiiiierejrlkwjerklwjerwerwr==\n\r"
155      *
156      * @param data
157      * @return
158      */

159     public static synchronized byte[] removeWhiteSpace( byte[] data ) {
160         if (data == null)
161             return null;
162
163         int newSize = 0;
164         int len = data.length;
165         int i =0;
166         for (; i<len; i++) {
167             if (!isWhiteSpace( data[i] ))
168                 newSize++;
169         }
170
171         if (newSize == len)
172             return data;//return input array since no whiteSpace
173

174
175         byte[] arrayWithoutSpaces = new byte[newSize];//Allocate new array without whiteSpace
176

177         int j = 0;
178         for (i=0;i<len;i++) {
179             if (isWhiteSpace( data[i] ))
180                 continue;
181             else
182                 arrayWithoutSpaces[j++] = data[i];//copy non-WhiteSpace
183
}
184         return arrayWithoutSpaces;
185
186     }
187
188     public static synchronized boolean isArrayByteBase64( byte[] arrayOctect ) {
189         return(getDecodedDataLength(arrayOctect) >= 0);
190     }
191
192     /**
193      * Encodes hex octects into Base64
194      *
195      * @param binaryData Array containing binaryData
196      * @return Encoded Base64 array
197      */

198     public static synchronized byte[] encode( byte[] binaryData ) {
199         if (binaryData == null)
200             return null;
201
202         int lengthDataBits = binaryData.length*EIGHTBIT;
203         int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
204         int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
205         byte encodedData[] = null;
206
207
208         if (fewerThan24bits != 0) //data not divisible by 24 bit
209
encodedData = new byte[ (numberTriplets + 1 )*4 ];
210         else // 16 or 8 bit
211
encodedData = new byte[ numberTriplets*4 ];
212
213         byte k=0, l=0, b1=0,b2=0,b3=0;
214
215         int encodedIndex = 0;
216         int dataIndex = 0;
217         int i = 0;
218         if (fDebug) {
219             System.out.println("number of triplets = " + numberTriplets );
220         }
221         for (i = 0; i<numberTriplets; i++) {
222
223             dataIndex = i*3;
224             b1 = binaryData[dataIndex];
225             b2 = binaryData[dataIndex + 1];
226             b3 = binaryData[dataIndex + 2];
227
228             if (fDebug) {
229                 System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 );
230             }
231
232             l = (byte)(b2 & 0x0f);
233             k = (byte)(b1 & 0x03);
234
235             encodedIndex = i*4;
236             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
237
238             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
239             byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
240
241             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
242             if (fDebug) {
243                 System.out.println( "val2 = " + val2 );
244                 System.out.println( "k4 = " + (k<<4));
245                 System.out.println( "vak = " + (val2 | (k<<4)));
246             }
247
248             encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
249             encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ];
250             encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
251         }
252
253         // form integral number of 6-bit groups
254
dataIndex = i*3;
255         encodedIndex = i*4;
256         if (fewerThan24bits == EIGHTBIT) {
257             b1 = binaryData[dataIndex];
258             k = (byte) ( b1 &0x03 );
259             if (fDebug) {
260                 System.out.println("b1=" + b1);
261                 System.out.println("b1<<2 = " + (b1>>2) );
262             }
263             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
264             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
265             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
266             encodedData[encodedIndex + 2] = PAD;
267             encodedData[encodedIndex + 3] = PAD;
268         } else if (fewerThan24bits == SIXTEENBIT) {
269
270             b1 = binaryData[dataIndex];
271             b2 = binaryData[dataIndex +1 ];
272             l = ( byte ) ( b2 &0x0f );
273             k = ( byte ) ( b1 &0x03 );
274
275             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
276             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
277
278             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
279             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
280             encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
281             encodedData[encodedIndex + 3] = PAD;
282         }
283         return encodedData;
284     }
285
286     /**
287      * Decodes Base64 data into octects
288      *
289      * @param binaryData Byte array containing Base64 data
290      * @return Array containind decoded data.
291      */

292     public static synchronized byte[] decode( byte[] base64Data ) {
293
294         if (base64Data == null)
295             return null;
296
297         byte[] normalizedBase64Data = removeWhiteSpace( base64Data );
298
299         if (normalizedBase64Data.length%FOURBYTE != 0) {
300             return null;//should be divisible by four
301
}
302
303         int numberQuadruple = (normalizedBase64Data.length/FOURBYTE );
304
305         if (numberQuadruple == 0)
306             return new byte[0];
307
308         byte decodedData[] = null;
309         byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
310         byte d1=0,d2=0,d3=0,d4=0;
311
312
313
314         // Throw away anything not in normalizedBase64Data
315
// Adjust size
316
int i = 0;
317         int encodedIndex = 0;
318         int dataIndex = 0;
319         decodedData = new byte[ (numberQuadruple)*3];
320
321         for (; i<numberQuadruple-1; i++) {
322
323             if (!isData( (d1 = normalizedBase64Data[dataIndex++]) )||
324                 !isData( (d2 = normalizedBase64Data[dataIndex++]) )||
325                 !isData( (d3 = normalizedBase64Data[dataIndex++]) )||
326                 !isData( (d4 = normalizedBase64Data[dataIndex++]) ))
327                 return null;//if found "no data" just return null
328

329             b1 = base64Alphabet[d1];
330             b2 = base64Alphabet[d2];
331             b3 = base64Alphabet[d3];
332             b4 = base64Alphabet[d4];
333
334             decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
335             decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
336             decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
337         }
338
339
340         if (!isData( (d1 = normalizedBase64Data[dataIndex++]) ) ||
341             !isData( (d2 = normalizedBase64Data[dataIndex++]) )) {
342             return null;//if found "no data" just return null
343
}
344
345
346         b1 = base64Alphabet[d1];
347         b2 = base64Alphabet[d2];
348
349         d3 = normalizedBase64Data[dataIndex++];
350         d4 = normalizedBase64Data[dataIndex++];
351         if (!isData( (d3 ) ) ||
352             !isData( (d4 ) )) {//Check if they are PAD characters
353
if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad]
354
if ((b2 & 0xf) != 0)//last 4 bits should be zero
355
return null;
356                 byte[] tmp = new byte[ i*3 + 1 ];
357                 System.arraycopy( decodedData, 0, tmp, 0, i*3 );
358                 tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
359                 return tmp;
360             } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad]
361
b3 = base64Alphabet[ d3 ];
362                 if ((b3 & 0x3 ) != 0)//last 2 bits should be zero
363
return null;
364                 byte[] tmp = new byte[ i*3 + 2 ];
365                 System.arraycopy( decodedData, 0, tmp, 0, i*3 );
366                 tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 );
367                 tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
368                 return tmp;
369             } else {
370                 return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
371
}
372         } else { //No PAD e.g 3cQl
373
b3 = base64Alphabet[ d3 ];
374             b4 = base64Alphabet[ d4 ];
375             decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
376             decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
377             decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
378
379         }
380
381         return decodedData;
382     }
383
384
385     /**
386      * returns length of decoded data given an
387      * array containing encoded data.
388      * WhiteSpace removing is done if data array not
389      * valid.
390      *
391      * @param base64Data
392      * @return a -1 would be return if not
393      */

394     static public synchronized int getDecodedDataLength( byte[] base64Data ) {
395
396         if (base64Data == null)
397             return -1;
398
399         if (base64Data.length == 0)
400             return 0;
401
402         //byte[] normalizedBase64Data = removeWhiteSpace( base64Data );//Remove any whiteSpace
403
byte[] decodedData = null;
404
405         if ((decodedData = decode( base64Data ) ) == null)//decode could return a null byte array
406
return -1;
407
408         return decodedData.length;
409     }
410 }
411
Popular Tags