Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mill/tools/Base64.java


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 mill.tools;
59  
60  import java.lang.*;
61  
62  
63  /**
64   * This class provides encode/decode for RFC 2045 Base64 as
65   * defined by RFC 2045, N. Freed and N. Borenstein.
66   * RFC 2045: Multipurpose Internet Mail Extensions (MIME)
67   * Part One: Format of Internet Message Bodies. Reference
68   * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
69   * This class is used by XML Schema binary format validation
70   * 
71   * This implementation does not encode/decode streaming 
72   * data. You need the data that you will encode/decode
73   * already on a byte arrray.
74   * 
75   * @author Jeffrey Rodriguez
76   * @author Sandy Gao
77   * @version $Id: Base64.java,v 1.8 2001/05/29 22:19:01 neilg Exp $
78   */
79  public final class  Base64 {
80      static private final int  BASELENGTH         = 255;
81      static private final int  LOOKUPLENGTH       = 64;
82      static private final int  TWENTYFOURBITGROUP = 24;
83      static private final int  EIGHTBIT           = 8;
84      static private final int  SIXTEENBIT         = 16;
85      static private final int  SIXBIT             = 6;
86      static private final int  FOURBYTE           = 4;
87      static private final int  SIGN               = -128;
88      static private final byte PAD                = ( byte ) '=';
89      static private final boolean fDebug          = false;
90      static private byte [] base64Alphabet       = new byte[BASELENGTH];
91      static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
92  
93  
94      static {
95  
96          for (int i = 0; i<BASELENGTH; i++) {
97              base64Alphabet[i] = -1;
98          }
99          for (int i = 'Z'; i >= 'A'; i--) {
100             base64Alphabet[i] = (byte) (i-'A');
101         }
102         for (int i = 'z'; i>= 'a'; i--) {
103             base64Alphabet[i] = (byte) ( i-'a' + 26);
104         }
105 
106         for (int i = '9'; i >= '0'; i--) {
107             base64Alphabet[i] = (byte) (i-'0' + 52);
108         }
109 
110         base64Alphabet['+']  = 62;
111         base64Alphabet['/']  = 63;
112 
113         for (int i = 0; i<=25; i++)
114             lookUpBase64Alphabet[i] = (byte) ('A'+i );
115 
116         for (int i = 26,  j = 0; i<=51; i++, j++)
117             lookUpBase64Alphabet[i] = (byte) ('a'+ j );
118 
119         for (int i = 52,  j = 0; i<=61; i++, j++)
120             lookUpBase64Alphabet[i] = (byte) ('0' + j );
121         lookUpBase64Alphabet[62] = (byte) '+';
122         lookUpBase64Alphabet[63] = (byte) '/';
123 
124     }
125 
126     protected static boolean isWhiteSpace (byte octect) {
127         return(octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
128     }
129 
130     protected static boolean isPad (byte octect) {
131         return(octect == PAD);
132     }
133 
134     protected static boolean isData (byte octect) {
135         return( base64Alphabet[octect] != -1);
136     }
137 
138     public static boolean isBase64( String isValidString ) {
139         if (isValidString == null)
140             return false;
141         return( isArrayByteBase64( isValidString.getBytes()));
142     }
143 
144 
145     public static boolean isBase64( byte octect ) {
146         return( isWhiteSpace(octect) || isPad(octect) || isData(octect));
147     }
148 
149 
150     /**
151      * remove WhiteSpace from MIME containing encoded Base64
152      * data.
153      * e.g.
154      * "   sdffferererrereresfsdfsdfsdff\n\r
155      * iiiiiiiiierejrlkwjerklwjerwerwr==\n\r"
156      * 
157      * @param data
158      * @return 
159      */
160     public static synchronized byte[] removeWhiteSpace( byte[] data ) {
161         if (data == null)
162             return null;
163 
164         int newSize = 0;
165         int len     = data.length;
166         int i =0;
167         for (; i<len; i++) {
168             if (!isWhiteSpace( data[i] ))
169                 newSize++;
170         }
171 
172         if (newSize == len)
173             return data;//return input array since no whiteSpace
174 
175 
176         byte[] arrayWithoutSpaces = new byte[newSize];//Allocate new array without whiteSpace
177 
178         int j = 0;
179         for (i=0;i<len;i++) {
180             if (isWhiteSpace( data[i] ))
181                 continue;
182             else
183                 arrayWithoutSpaces[j++] = data[i];//copy non-WhiteSpace 
184         }
185         return arrayWithoutSpaces;
186 
187     }
188 
189     public static synchronized boolean isArrayByteBase64( byte[] arrayOctect ) {
190         return(getDecodedDataLength(arrayOctect) >= 0);
191     }
192 
193     /**
194      * Encodes hex octects into Base64
195      *
196      * @param binaryData Array containing binaryData
197      * @return Encoded Base64 array
198      */
199     public static synchronized byte[] encode( byte[] binaryData ) {
200         if (binaryData == null)
201             return null;
202 
203         int      lengthDataBits    = binaryData.length*EIGHTBIT;
204         int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
205         int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
206         byte     encodedData[]     = null;
207 
208 
209         if (fewerThan24bits != 0) //data not divisible by 24 bit
210             encodedData = new byte[ (numberTriplets + 1 )*4  ];
211         else // 16 or 8 bit
212             encodedData = new byte[ numberTriplets*4 ];
213 
214         byte k=0, l=0, b1=0,b2=0,b3=0;
215 
216         int encodedIndex = 0;
217         int dataIndex   = 0;
218         int i           = 0;
219         if (fDebug) {
220             System.out.println("number of triplets = " + numberTriplets );
221         }
222         for (i = 0; i<numberTriplets; i++) {
223 
224             dataIndex = i*3;
225             b1 = binaryData[dataIndex];
226             b2 = binaryData[dataIndex + 1];
227             b3 = binaryData[dataIndex + 2];
228 
229             if (fDebug) {
230                 System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 );
231             }
232 
233             l  = (byte)(b2 & 0x0f);
234             k  = (byte)(b1 & 0x03);
235 
236             encodedIndex = i*4;
237             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
238 
239             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
240             byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
241 
242             encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ];
243             if (fDebug) {
244                 System.out.println( "val2 = " + val2 );
245                 System.out.println( "k4   = " + (k<<4));
246                 System.out.println( "vak  = " + (val2 | (k<<4)));
247             }
248 
249             encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
250             encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ];
251             encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
252         }
253 
254         // form integral number of 6-bit groups
255         dataIndex    = i*3;
256         encodedIndex = i*4;
257         if (fewerThan24bits == EIGHTBIT) {
258             b1 = binaryData[dataIndex];
259             k = (byte) ( b1 &0x03 );
260             if (fDebug) {
261                 System.out.println("b1=" + b1);
262                 System.out.println("b1<<2 = " + (b1>>2) );
263             }
264             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
265             encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
266             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
267             encodedData[encodedIndex + 2] = PAD;
268             encodedData[encodedIndex + 3] = PAD;
269         } else if (fewerThan24bits == SIXTEENBIT) {
270 
271             b1 = binaryData[dataIndex];
272             b2 = binaryData[dataIndex +1 ];
273             l = ( byte ) ( b2 &0x0f );
274             k = ( byte ) ( b1 &0x03 );
275 
276             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
277             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
278 
279             encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
280             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
281             encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
282             encodedData[encodedIndex + 3] = PAD;
283         }
284         return encodedData;
285     }
286 
287     /**
288      * Decodes Base64 data into octects
289      *
290      * @param binaryData Byte array containing Base64 data
291      * @return Array containind decoded data.
292      */
293     public static synchronized byte[] decode( byte[] base64Data ) {
294 
295         if (base64Data == null)
296             return null;
297 
298         byte[]   normalizedBase64Data = removeWhiteSpace( base64Data );
299 
300         if (normalizedBase64Data.length%FOURBYTE != 0) {
301             return null;//should be divisible by four
302         }
303 
304         int      numberQuadruple    = (normalizedBase64Data.length/FOURBYTE );
305 
306         if (numberQuadruple == 0)
307             return new byte[0];
308 
309         byte     decodedData[]      = null;
310         byte     b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
311         byte     d1=0,d2=0,d3=0,d4=0;
312 
313 
314 
315         // Throw away anything not in normalizedBase64Data
316         // Adjust size
317         int i = 0;
318         int encodedIndex = 0;
319         int dataIndex    = 0;
320         decodedData      = new byte[ (numberQuadruple)*3];
321 
322         for (; i<numberQuadruple-1; i++) {
323 
324             if (!isData( (d1 = normalizedBase64Data[dataIndex++]) )||  
325                 !isData( (d2 = normalizedBase64Data[dataIndex++]) )||
326                 !isData( (d3 = normalizedBase64Data[dataIndex++]) )||
327                 !isData( (d4 = normalizedBase64Data[dataIndex++]) ))
328                 return null;//if found "no data" just return null
329 
330             b1 = base64Alphabet[d1]; 
331             b2 = base64Alphabet[d2];
332             b3 = base64Alphabet[d3];
333             b4 = base64Alphabet[d4];
334 
335             decodedData[encodedIndex++] = (byte)(  b1 <<2 | b2>>4 ) ;
336             decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
337             decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); 
338         }
339 
340 
341         if (!isData( (d1 = normalizedBase64Data[dataIndex++]) ) ||  
342             !isData( (d2 = normalizedBase64Data[dataIndex++]) )) {
343             return null;//if found "no data" just return null
344         }
345 
346 
347         b1 = base64Alphabet[d1]; 
348         b2 = base64Alphabet[d2];
349 
350         d3 = normalizedBase64Data[dataIndex++];
351         d4 = normalizedBase64Data[dataIndex++];
352         if (!isData( (d3 ) ) ||
353             !isData( (d4 ) )) {//Check if they are PAD characters
354             if (isPad( d3 ) && isPad( d4)) {               //Two PAD e.g. 3c[Pad][Pad]
355                 if ((b2 & 0xf) != 0)//last 4 bits should be zero
356                     return null;
357                 byte[] tmp = new byte[ i*3 + 1 ];
358                 System.arraycopy( decodedData, 0, tmp, 0, i*3 ); 
359                 tmp[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ; 
360                 return tmp;
361             } else if (!isPad( d3) && isPad(d4)) {               //One PAD  e.g. 3cQ[Pad]
362                 b3 = base64Alphabet[ d3 ];
363                 if ((b3 & 0x3 ) != 0)//last 2 bits should be zero
364                     return null;
365                 byte[] tmp = new byte[ i*3 + 2 ];
366                 System.arraycopy( decodedData, 0, tmp, 0, i*3 );
367                 tmp[encodedIndex++] = (byte)(  b1 <<2 | b2>>4 );
368                 tmp[encodedIndex]   = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
369                 return tmp;
370             } else {
371                 return null;//an error  like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data 
372             }
373         } else { //No PAD e.g 3cQl
374             b3 = base64Alphabet[ d3 ];
375             b4 = base64Alphabet[ d4 ];
376             decodedData[encodedIndex++] = (byte)(  b1 <<2 | b2>>4 ) ;
377             decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
378             decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); 
379 
380         }
381 
382         return decodedData;
383     }
384 
385 
386     /**
387      * returns length of decoded data given an
388      * array containing encoded data.
389      * WhiteSpace removing is done if data array not
390      * valid.
391      * 
392      * @param base64Data
393      * @return         a -1 would be return if not
394      */
395     static public synchronized int getDecodedDataLength( byte[] base64Data ) {
396 
397         if (base64Data == null)
398             return -1;
399 
400         if (base64Data.length == 0)
401             return 0;
402 
403         //byte[] normalizedBase64Data =  removeWhiteSpace( base64Data );//Remove any whiteSpace 
404         byte[] decodedData = null;
405 
406         if ((decodedData = decode( base64Data ) ) == null)//decode could return a null byte array
407             return -1;
408 
409         return decodedData.length;
410     }
411 }