KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > myvietnam > mvncore > misc > Base64


1 /*
2  * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/misc/Base64.java,v 1.9 2006/04/15 02:59:19 minhnn Exp $
3  * $Author: minhnn $
4  * $Revision: 1.9 $
5  * $Date: 2006/04/15 02:59:19 $
6  *
7  * ====================================================================
8  *
9  * Copyright (C) 2002-2006 by MyVietnam.net
10  *
11  * All copyright notices regarding MyVietnam and MyVietnam CoreLib
12  * MUST remain intact in the scripts and source code.
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  *
28  * Correspondence and Marketing Questions can be sent to:
29  * info at MyVietnam net
30  *
31  */

32 /*
33  * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/misc/Base64.java,v 1.9 2006/04/15 02:59:19 minhnn Exp $
34  * $Revision: 1.9 $
35  * $Date: 2006/04/15 02:59:19 $
36  *
37  * ====================================================================
38  *
39  * The Apache Software License, Version 1.1
40  *
41  * Copyright (c) 1999 The Apache Software Foundation. All rights
42  * reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  *
48  * 1. Redistributions of source code must retain the above copyright
49  * notice, this list of conditions and the following disclaimer.
50  *
51  * 2. Redistributions in binary form must reproduce the above copyright
52  * notice, this list of conditions and the following disclaimer in
53  * the documentation and/or other materials provided with the
54  * distribution.
55  *
56  * 3. The end-user documentation included with the redistribution, if
57  * any, must include the following acknowlegement:
58  * "This product includes software developed by the
59  * Apache Software Foundation (http://www.apache.org/)."
60  * Alternately, this acknowlegement may appear in the software itself,
61  * if and wherever such third-party acknowlegements normally appear.
62  *
63  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
64  * Foundation" must not be used to endorse or promote products derived
65  * from this software without prior written permission. For written
66  * permission, please contact apache@apache.org.
67  *
68  * 5. Products derived from this software may not be called "Apache"
69  * nor may "Apache" appear in their names without prior written
70  * permission of the Apache Group.
71  *
72  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
73  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
74  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
75  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
76  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
77  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
78  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
79  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
80  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
81  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
82  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83  * SUCH DAMAGE.
84  * ====================================================================
85  *
86  * This software consists of voluntary contributions made by many
87  * individuals on behalf of the Apache Software Foundation. For more
88  * information on the Apache Software Foundation, please see
89  * <http://www.apache.org/>.
90  *
91  * [Additional notices, if required by prior licensing conditions]
92  *
93  */

94
95 package net.myvietnam.mvncore.misc;
96
97 /**
98  * This class provides encode/decode for RFC 2045 Base64 as defined by
99  * RFC 2045, N. Freed and N. Borenstein. <a
100  * HREF="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>:
101  * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
102  * Internet Message Bodies. Reference 1996
103  *
104  * @author Jeffrey Rodriguez
105  * @version $Id: Base64.java,v 1.9 2006/04/15 02:59:19 minhnn Exp $
106  */

107 public final class Base64
108 {
109     static private final int BASELENGTH = 255;
110     static private final int LOOKUPLENGTH = 64;
111     static private final int TWENTYFOURBITGROUP = 24;
112     static private final int EIGHTBIT = 8;
113     static private final int SIXTEENBIT = 16;
114     static private final int SIXBIT = 6;
115     static private final int FOURBYTE = 4;
116     static private final int SIGN = -128;
117     static private final byte PAD = (byte) '=';
118     static private byte [] base64Alphabet = new byte[BASELENGTH];
119     static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
120     //static private final Log log = LogSource.getInstance("org.apache.commons.util.Base64");
121

122     static
123     {
124         for (int i = 0; i < BASELENGTH; i++ )
125         {
126             base64Alphabet[i] = -1;
127         }
128         for (int i = 'Z'; i >= 'A'; i--)
129         {
130             base64Alphabet[i] = (byte) (i - 'A');
131         }
132         for (int i = 'z'; i>= 'a'; i--)
133         {
134             base64Alphabet[i] = (byte) (i - 'a' + 26);
135         }
136         for (int i = '9'; i >= '0'; i--)
137         {
138             base64Alphabet[i] = (byte) (i - '0' + 52);
139         }
140
141         base64Alphabet['+'] = 62;
142         base64Alphabet['/'] = 63;
143
144         for (int i = 0; i <= 25; i++ )
145             lookUpBase64Alphabet[i] = (byte) ('A' + i);
146
147         for (int i = 26, j = 0; i <= 51; i++, j++ )
148             lookUpBase64Alphabet[i] = (byte) ('a'+ j);
149
150         for (int i = 52, j = 0; i <= 61; i++, j++ )
151             lookUpBase64Alphabet[i] = (byte) ('0' + j);
152
153         lookUpBase64Alphabet[62] = (byte) '+';
154         lookUpBase64Alphabet[63] = (byte) '/';
155     }
156
157     public static boolean isBase64( String JavaDoc isValidString )
158     {
159         return isArrayByteBase64(isValidString.getBytes());
160     }
161
162     public static boolean isBase64( byte octect )
163     {
164         //shall we ignore white space? JEFF??
165
return (octect == PAD || base64Alphabet[octect] != -1);
166     }
167
168     public static boolean isArrayByteBase64( byte[] arrayOctect )
169     {
170         int length = arrayOctect.length;
171         if (length == 0)
172         {
173             // shouldn't a 0 length array be valid base64 data?
174
// return false;
175
return true;
176         }
177         for (int i=0; i < length; i++)
178         {
179             if ( !Base64.isBase64(arrayOctect[i]) )
180                 return false;
181         }
182         return true;
183     }
184
185     /**
186      * Encodes hex octects into Base64.
187      *
188      * @param binaryData Array containing binary data to encode.
189      * @return Base64-encoded data.
190      */

191     public static byte[] encode( byte[] binaryData )
192     {
193         int lengthDataBits = binaryData.length*EIGHTBIT;
194         int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
195         int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
196         byte encodedData[] = null;
197
198
199         if (fewerThan24bits != 0)
200         {
201             //data not divisible by 24 bit
202
encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
203         }
204         else
205         {
206             // 16 or 8 bit
207
encodedData = new byte[ numberTriplets * 4 ];
208         }
209
210         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
211
212         int encodedIndex = 0;
213         int dataIndex = 0;
214         int i = 0;
215         //log.debug("number of triplets = " + numberTriplets);
216
for ( i = 0; i<numberTriplets; i++ )
217         {
218             dataIndex = i*3;
219             b1 = binaryData[dataIndex];
220             b2 = binaryData[dataIndex + 1];
221             b3 = binaryData[dataIndex + 2];
222
223             //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
224

225             l = (byte)(b2 & 0x0f);
226             k = (byte)(b1 & 0x03);
227
228             encodedIndex = i * 4;
229             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
230             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
231             byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
232
233             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
234             //log.debug( "val2 = " + val2 );
235
//log.debug( "k4 = " + (k<<4) );
236
//log.debug( "vak = " + (val2 | (k<<4)) );
237
encodedData[encodedIndex+1] =
238                 lookUpBase64Alphabet[ val2 | ( k<<4 )];
239             encodedData[encodedIndex+2] =
240                 lookUpBase64Alphabet[ (l <<2 ) | val3 ];
241             encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
242         }
243
244         // form integral number of 6-bit groups
245
dataIndex = i*3;
246         encodedIndex = i*4;
247         if (fewerThan24bits == EIGHTBIT )
248         {
249             b1 = binaryData[dataIndex];
250             k = (byte) ( b1 &0x03 );
251             //log.debug("b1=" + b1);
252
//log.debug("b1<<2 = " + (b1>>2) );
253
byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
254             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
255             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
256             encodedData[encodedIndex + 2] = PAD;
257             encodedData[encodedIndex + 3] = PAD;
258         }
259         else if (fewerThan24bits == SIXTEENBIT)
260         {
261
262             b1 = binaryData[dataIndex];
263             b2 = binaryData[dataIndex +1 ];
264             l = (byte) (b2 & 0x0f);
265             k = (byte) (b1 & 0x03);
266
267             byte val1 = ((b1 & SIGN) == 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
268             byte val2 = ((b2 & SIGN) == 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
269
270             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
271             encodedData[encodedIndex + 1] =
272                 lookUpBase64Alphabet[ val2 | ( k<<4 )];
273             encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
274             encodedData[encodedIndex + 3] = PAD;
275         }
276
277         return encodedData;
278     }
279
280     /**
281      * Decodes Base64 data into octects
282      *
283      * @param base64Data Byte array containing Base64 data
284      * @return Array containing decoded data.
285      */

286     public static byte[] decode( byte[] base64Data )
287     {
288         // handle the edge case, so we don't have to worry about it later
289
if(base64Data.length == 0) { return new byte[0]; }
290
291         int numberQuadruple = base64Data.length/FOURBYTE;
292         byte decodedData[] = null;
293         byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
294
295         // Throw away anything not in base64Data
296

297         int encodedIndex = 0;
298         int dataIndex = 0;
299         {
300             // this sizes the output array properly - rlw
301
int lastData = base64Data.length;
302             // ignore the '=' padding
303
while (base64Data[lastData-1] == PAD)
304             {
305                 if (--lastData == 0)
306                 {
307                     return new byte[0];
308                 }
309             }
310             decodedData = new byte[ lastData - numberQuadruple ];
311         }
312
313         for (int i = 0; i < numberQuadruple; i++)
314         {
315             dataIndex = i * 4;
316             marker0 = base64Data[dataIndex + 2];
317             marker1 = base64Data[dataIndex + 3];
318
319             b1 = base64Alphabet[base64Data[dataIndex]];
320             b2 = base64Alphabet[base64Data[dataIndex +1]];
321
322             if (marker0 != PAD && marker1 != PAD)
323             {
324                 //No PAD e.g 3cQl
325
b3 = base64Alphabet[ marker0 ];
326                 b4 = base64Alphabet[ marker1 ];
327
328                 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
329                 decodedData[encodedIndex + 1] =
330                     (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
331                 decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
332             }
333             else if (marker0 == PAD)
334             {
335                 //Two PAD e.g. 3c[Pad][Pad]
336
decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
337             }
338             else if (marker1 == PAD)
339             {
340                 //One PAD e.g. 3cQ[Pad]
341
b3 = base64Alphabet[ marker0 ];
342
343                 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 );
344                 decodedData[encodedIndex + 1] =
345                     (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
346             }
347             encodedIndex += 3;
348         }
349         return decodedData;
350     }
351
352
353 }
354
Popular Tags