KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > util > Base64


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.catalina.util;
19
20 import org.apache.tomcat.util.buf.ByteChunk;
21 import org.apache.tomcat.util.buf.CharChunk;
22
23 /**
24  * This class provides encode/decode for RFC 2045 Base64 as defined by
25  * RFC 2045, N. Freed and N. Borenstein. <a
26  * HREF="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>:
27  * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
28  * Internet Message Bodies. Reference 1996
29  *
30  * @author Jeffrey Rodriguez
31  * @version $Id: Base64.java 467222 2006-10-24 03:17:11Z markt $
32  */

33 public final class Base64
34 {
35     static private final int BASELENGTH = 255;
36     static private final int LOOKUPLENGTH = 64;
37     static private final int TWENTYFOURBITGROUP = 24;
38     static private final int EIGHTBIT = 8;
39     static private final int SIXTEENBIT = 16;
40     static private final int SIXBIT = 6;
41     static private final int FOURBYTE = 4;
42     static private final int SIGN = -128;
43     static private final byte PAD = (byte) '=';
44     static private byte [] base64Alphabet = new byte[BASELENGTH];
45     static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
46     //static private final Log log = LogSource.getInstance("org.apache.commons.util.Base64");
47

48     static
49     {
50         for (int i = 0; i < BASELENGTH; i++ )
51         {
52             base64Alphabet[i] = -1;
53         }
54         for (int i = 'Z'; i >= 'A'; i--)
55         {
56             base64Alphabet[i] = (byte) (i - 'A');
57         }
58         for (int i = 'z'; i>= 'a'; i--)
59         {
60             base64Alphabet[i] = (byte) (i - 'a' + 26);
61         }
62         for (int i = '9'; i >= '0'; i--)
63         {
64             base64Alphabet[i] = (byte) (i - '0' + 52);
65         }
66
67         base64Alphabet['+'] = 62;
68         base64Alphabet['/'] = 63;
69
70         for (int i = 0; i <= 25; i++ )
71             lookUpBase64Alphabet[i] = (byte) ('A' + i);
72
73         for (int i = 26, j = 0; i <= 51; i++, j++ )
74             lookUpBase64Alphabet[i] = (byte) ('a'+ j);
75
76         for (int i = 52, j = 0; i <= 61; i++, j++ )
77             lookUpBase64Alphabet[i] = (byte) ('0' + j);
78
79         lookUpBase64Alphabet[62] = (byte) '+';
80         lookUpBase64Alphabet[63] = (byte) '/';
81     }
82
83     public static boolean isBase64( String JavaDoc isValidString )
84     {
85         return isArrayByteBase64(isValidString.getBytes());
86     }
87
88     public static boolean isBase64( byte octect )
89     {
90         //shall we ignore white space? JEFF??
91
return (octect == PAD || base64Alphabet[octect] != -1);
92     }
93
94     public static boolean isArrayByteBase64( byte[] arrayOctect )
95     {
96         int length = arrayOctect.length;
97         if (length == 0)
98         {
99             // shouldn't a 0 length array be valid base64 data?
100
// return false;
101
return true;
102         }
103         for (int i=0; i < length; i++)
104         {
105             if ( !Base64.isBase64(arrayOctect[i]) )
106                 return false;
107         }
108         return true;
109     }
110
111     /**
112      * Encodes hex octects into Base64.
113      *
114      * @param binaryData Array containing binary data to encode.
115      * @return Base64-encoded data.
116      */

117     public static byte[] encode( byte[] binaryData )
118     {
119         int lengthDataBits = binaryData.length*EIGHTBIT;
120         int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
121         int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
122         byte encodedData[] = null;
123
124
125         if (fewerThan24bits != 0)
126         {
127             //data not divisible by 24 bit
128
encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
129         }
130         else
131         {
132             // 16 or 8 bit
133
encodedData = new byte[ numberTriplets * 4 ];
134         }
135
136         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
137
138         int encodedIndex = 0;
139         int dataIndex = 0;
140         int i = 0;
141         //log.debug("number of triplets = " + numberTriplets);
142
for ( i = 0; i<numberTriplets; i++ )
143         {
144             dataIndex = i*3;
145             b1 = binaryData[dataIndex];
146             b2 = binaryData[dataIndex + 1];
147             b3 = binaryData[dataIndex + 2];
148
149             //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
150

151             l = (byte)(b2 & 0x0f);
152             k = (byte)(b1 & 0x03);
153
154             encodedIndex = i * 4;
155             byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
156             byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
157             byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
158
159             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
160             //log.debug( "val2 = " + val2 );
161
//log.debug( "k4 = " + (k<<4) );
162
//log.debug( "vak = " + (val2 | (k<<4)) );
163
encodedData[encodedIndex+1] =
164                 lookUpBase64Alphabet[ val2 | ( k<<4 )];
165             encodedData[encodedIndex+2] =
166                 lookUpBase64Alphabet[ (l <<2 ) | val3 ];
167             encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
168         }
169
170         // form integral number of 6-bit groups
171
dataIndex = i*3;
172         encodedIndex = i*4;
173         if (fewerThan24bits == EIGHTBIT )
174         {
175             b1 = binaryData[dataIndex];
176             k = (byte) ( b1 &0x03 );
177             //log.debug("b1=" + b1);
178
//log.debug("b1<<2 = " + (b1>>2) );
179
byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
180             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
181             encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
182             encodedData[encodedIndex + 2] = PAD;
183             encodedData[encodedIndex + 3] = PAD;
184         }
185         else if (fewerThan24bits == SIXTEENBIT)
186         {
187
188             b1 = binaryData[dataIndex];
189             b2 = binaryData[dataIndex +1 ];
190             l = (byte) (b2 & 0x0f);
191             k = (byte) (b1 & 0x03);
192
193             byte val1 = ((b1 & SIGN) == 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
194             byte val2 = ((b2 & SIGN) == 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
195
196             encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
197             encodedData[encodedIndex + 1] =
198                 lookUpBase64Alphabet[ val2 | ( k<<4 )];
199             encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
200             encodedData[encodedIndex + 3] = PAD;
201         }
202
203         return encodedData;
204     }
205
206     /**
207      * Decodes Base64 data into octects
208      *
209      * @param base64DataBC Byte array containing Base64 data
210      * @param decodedDataCC The decoded data chars
211      */

212     public static void decode( ByteChunk base64DataBC, CharChunk decodedDataCC)
213     {
214         int start = base64DataBC.getStart();
215         int end = base64DataBC.getEnd();
216         byte[] base64Data = base64DataBC.getBuffer();
217         
218         decodedDataCC.recycle();
219         
220         // handle the edge case, so we don't have to worry about it later
221
if(end - start == 0) { return; }
222
223         int numberQuadruple = (end - start)/FOURBYTE;
224         byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
225
226         // Throw away anything not in base64Data
227

228         int encodedIndex = 0;
229         int dataIndex = start;
230         char[] decodedData = null;
231         
232         {
233             // this sizes the output array properly - rlw
234
int lastData = end - start;
235             // ignore the '=' padding
236
while (base64Data[start+lastData-1] == PAD)
237             {
238                 if (--lastData == 0)
239                 {
240                     return;
241                 }
242             }
243             decodedDataCC.allocate(lastData - numberQuadruple, -1);
244             decodedDataCC.setEnd(lastData - numberQuadruple);
245             decodedData = decodedDataCC.getBuffer();
246         }
247
248         for (int i = 0; i < numberQuadruple; i++)
249         {
250             dataIndex = start + i * 4;
251             marker0 = base64Data[dataIndex + 2];
252             marker1 = base64Data[dataIndex + 3];
253
254             b1 = base64Alphabet[base64Data[dataIndex]];
255             b2 = base64Alphabet[base64Data[dataIndex +1]];
256
257             if (marker0 != PAD && marker1 != PAD)
258             {
259                 //No PAD e.g 3cQl
260
b3 = base64Alphabet[ marker0 ];
261                 b4 = base64Alphabet[ marker1 ];
262
263                 decodedData[encodedIndex] = (char) (( b1 <<2 | b2>>4 ) & 0xff);
264                 decodedData[encodedIndex + 1] =
265                     (char) ((((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ) & 0xff);
266                 decodedData[encodedIndex + 2] = (char) (( b3<<6 | b4 ) & 0xff);
267             }
268             else if (marker0 == PAD)
269             {
270                 //Two PAD e.g. 3c[Pad][Pad]
271
decodedData[encodedIndex] = (char) (( b1 <<2 | b2>>4 ) & 0xff);
272             }
273             else if (marker1 == PAD)
274             {
275                 //One PAD e.g. 3cQ[Pad]
276
b3 = base64Alphabet[ marker0 ];
277
278                 decodedData[encodedIndex] = (char) (( b1 <<2 | b2>>4 ) & 0xff);
279                 decodedData[encodedIndex + 1] =
280                     (char) ((((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ) & 0xff);
281             }
282             encodedIndex += 3;
283         }
284     }
285
286
287 }
288
Popular Tags