KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > misc > Base64


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.core.misc;
66
67 /**
68  * Base 64 encoding class.
69  * Many thanks goes to Wei Dai's
70  * <A HREF="http://www.eskimo.com/~weidai/cryptlib.html">Crypto++</A> for
71  * providing public domain C++ code
72  * that this could be derived from.
73  * </p>
74  *
75  * @since Expresso 3.0
76  */

77 public class Base64 {
78     static final private int bytesPerLine = 80; // number of bytes per line
79

80     /* This array maps the characters to their 6 bit values */
81     private final static char[] vec = {
82         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
83
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
84
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
85
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
86
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
87
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
88
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
89
'4', '5', '6', '7', '8', '9', '+', '/' // 7
90
};
91     private final static byte padding = (byte) '=';
92
93     public Base64() {
94     }
95
96     /**
97      * @param inByte
98      * @return
99      */

100     static private byte convertToNumber(byte inByte) {
101         if (inByte >= 'A' && inByte <= 'Z') {
102             return (byte) (inByte - 'A');
103         }
104         if (inByte >= 'a' && inByte <= 'z') {
105             return (byte) (inByte - 'a' + 26);
106         }
107         if (inByte >= '0' && inByte <= '9') {
108             return (byte) (inByte - '0' + 52);
109         }
110         if (inByte == '+') {
111             return (62);
112         }
113         if (inByte == '/') {
114             return (63);
115         }
116
117         return (-1);
118     } /* convertToNumber(byte) */
119
120     /**
121      * decode - Decodes a Base64 encoded string back into its original
122      * binary format. If the data is not a proper base64 encoded string,
123      * it might throw an ArrayIndexOutOfBoundsException.
124      *
125      * @param data the data to decode
126      * @return
127      */

128     static public byte[] decode(String JavaDoc data)
129             throws IllegalArgumentException JavaDoc {
130
131         //Check for NULL
132
if (data == null) {
133             throw new IllegalArgumentException JavaDoc("Base64.decode: data must not be null");
134         }
135         //Check to see if data is proper length
136
if (data.length() % 4 != 0) {
137             throw new IllegalArgumentException JavaDoc("Base64.decode: data is not of proper length");
138         }
139
140         byte[] inputBuffer = data.getBytes();
141         int validInputCount = 0;
142         byte[] inBuffer = new byte[inputBuffer.length];
143         int dataLength = inputBuffer.length;
144
145         //We use the same input and output buffer since
146
// the value will be the same
147
//
148
//Preprocess -- Strip the LF's et al
149
//
150
int i;
151
152         for (i = 0; i < dataLength; i++) {
153             byte temp = convertToNumber(inputBuffer[i]);
154
155             if (temp >= 0) {
156                 inBuffer[i] = temp;
157                 validInputCount++;
158             }
159         }
160
161         byte[] outBuffer = new byte[dataLength];
162         int startOut = 0;
163         int startIn = 0;
164
165         while (validInputCount > startIn) {
166             int dataLen = validInputCount;
167
168             if (dataLen - startIn > 3) {
169                 outBuffer[startOut] = (byte) ((inBuffer[startIn] << 2) +
170                         (inBuffer[startIn + 1] >>> 4));
171                 outBuffer[startOut + 1] = (byte) ((inBuffer[startIn + 1] << 4) +
172                         (inBuffer[startIn + 2] >>> 2));
173                 outBuffer[startOut + 2] = (byte) ((inBuffer[startIn + 2] << 6) +
174                         (inBuffer[startIn + 3]));
175                 startOut += 3;
176                 startIn += 4;
177             } else if (dataLen - startIn > 2) {
178                 outBuffer[startOut] = (byte) ((inBuffer[startIn] << 2) +
179                         (inBuffer[startIn + 1] >>> 4));
180                 outBuffer[startOut + 1] = (byte) ((inBuffer[startIn + 1] << 4) +
181                         (inBuffer[startIn + 2] >>> 2));
182                 startOut += 2;
183                 startIn += 3;
184             } else if (dataLen - startIn > 1) {
185                 outBuffer[startOut] = (byte) ((inBuffer[startIn] << 2) +
186                         (inBuffer[startIn + 1] >>> 4));
187                 startOut += 1;
188                 startIn += 2;
189             } else {
190                 throw new IllegalStateException JavaDoc("com.jcorporate.expresso.core.misc." +
191                         "Base64.Decode: Corrupt Input Data");
192             }
193         }
194
195         //Copy the final bytes over to a real output array
196
byte[] finalOutput = new byte[startOut];
197
198         for (i = 0; i < startOut; i++) {
199             finalOutput[i] = outBuffer[i];
200         }
201
202         inBuffer = null;
203         outBuffer = null;
204
205         return finalOutput;
206     } /* decode(String) */
207
208
209     /**
210      * <B>Note: this function does not process stricly compliant Base64
211      * code. To process strictly compliant Base64 encoded strings, use encode
212      * and decode functions with padding</B>
213      * <p/>
214      * Decodes a Base64 encoded string back into its original binary format.
215      * The only difference from decode is that this function will bad the
216      * end with as many ='s as necessary to make things work properly.
217      *
218      * @param data the Base64 encoded string
219      * @return the byte array of the original data.
220      * @throws IllegalArgumentException if the input data is null or zero bytes.
221      */

222     static public byte[] decodeNoPadding(String JavaDoc data)
223             throws IllegalArgumentException JavaDoc {
224         String JavaDoc myName = "Base64.decodeNoPadding";
225
226         if (data == null) {
227             throw new IllegalArgumentException JavaDoc(myName + " parameter 'data'" +
228                     " must not be null");
229         }
230         if (data.length() == 0) {
231             throw new IllegalArgumentException JavaDoc(myName + " parameter 'data'" +
232                     " must not be greater than zero length");
233         }
234         //Append as many zeros as necessary to make things work.
235
for (; data.length() % 4 != 0; data = data + "=") {
236             ;
237         }
238
239         return decode(data);
240     } /* decodeNoPadding(String) */
241
242
243     /**
244      * encode - Encodes a binary byte array into an Ascii String (including 80
245      * column line wrap.
246      *
247      * @param inBuffer[] the data to encode
248      * @return
249      */

250     static public String JavaDoc encode(byte[] inBuffer)
251             throws IllegalArgumentException JavaDoc {
252         if (inBuffer.length == 0) {
253             throw new IllegalArgumentException JavaDoc("Base64.encode: " +
254                     "inBuffer must be > zero bytes in length");
255         }
256
257         int dataSize = inBuffer.length;
258         int startIn = 0;
259         int startOut = 0;
260
261         //Create an output buffer that's twice the size of the input buffer
262
//that way we have enough room for sure
263
byte[] outBuffer;
264
265         if (dataSize < 4) {
266             outBuffer = new byte[4];
267         } else {
268             outBuffer = new byte[dataSize * 2];
269         }
270         //Iteratate
271
while (startIn < dataSize) {
272             int dataLen = inBuffer.length;
273             byte a;
274             byte b;
275             byte c;
276
277             //Check for linewrap
278
if ((startOut % bytesPerLine) + 4 > bytesPerLine) {
279                 outBuffer[startOut] = (byte) '\r';
280                 outBuffer[startOut + 1] = (byte) '\n';
281                 startOut += 2;
282             }
283             if (dataLen - startIn > 2) {
284                 a = inBuffer[startIn];
285                 b = inBuffer[startIn + 1];
286                 c = inBuffer[startIn + 2];
287                 outBuffer[startOut] = (byte) vec[(a >>> 2) & 0x3F];
288                 outBuffer[startOut + 1] = (byte) vec[((a << 4) & 0x30) +
289                         ((b >>> 4) & 0xf)];
290                 outBuffer[startOut + 2] = (byte) vec[((b << 2) & 0x3c) +
291                         ((c >>> 6) & 0x3)];
292                 outBuffer[startOut + 3] = (byte) vec[c & 0x3F];
293                 startOut += 4;
294                 startIn += 3;
295             } else if (dataLen - startIn == 1) {
296                 a = inBuffer[startIn];
297                 b = 0;
298                 c = 0;
299                 outBuffer[startOut] = (byte) vec[(a >>> 2) & 0x3F];
300                 outBuffer[startOut + 1] = (byte) vec[((a << 4) & 0x30) +
301                         ((b >>> 4) & 0xf)];
302                 outBuffer[startOut + 2] = padding;
303                 outBuffer[startOut + 3] = padding;
304                 startOut += 4;
305                 startIn += 2;
306             } else if (dataLen - startIn == 2) {
307                 a = inBuffer[startIn];
308                 b = inBuffer[startIn + 1];
309                 c = 0;
310                 outBuffer[startOut] = (byte) vec[(a >>> 2) & 0x3F];
311                 outBuffer[startOut + 1] = (byte) vec[((a << 4) & 0x30) +
312                         ((b >>> 4) & 0xf)];
313                 outBuffer[startOut + 2] = (byte) vec[((b << 2) & 0x3c) +
314                         ((c >>> 6) & 0x3)];
315                 outBuffer[startOut + 3] = padding;
316                 startOut += 4;
317                 startIn += 2;
318             }
319         }
320
321         return new String JavaDoc(outBuffer, 0, startOut);
322     } /* encode(byte) */
323
324
325     /* */
326     /* */
327     /* Encoding Part */
328     /* */
329     /* */
330     /**
331      * <B>Note: this function does not process stricly compliant Base64
332      * code. To process strictly compliant Base64 encoded strings, use encode
333      * and decode functions with padding</B>
334      * <p/>
335      * Encodes a binary bite array into Base64 coding. The difference between
336      * this and the other encode function, is that this function strips all
337      * padding from the final result before returning
338      *
339      * @param inBuffer[] the byte array to encode.
340      * @return a string that is the Base64 equiv of the input data without
341      * padding characters
342      * @throws IllegalArgumentException if the input data is null or zero bytes.
343      */

344     static public String JavaDoc encodeNoPadding(byte[] inBuffer)
345             throws IllegalArgumentException JavaDoc {
346         String JavaDoc stringWithPadding = encode(inBuffer);
347         int equalsPlacement = stringWithPadding.indexOf((int) '=');
348
349         if (equalsPlacement == -1) {
350             return stringWithPadding;
351         } else {
352             return stringWithPadding.substring(0, equalsPlacement);
353         }
354     } /* encodeNoPaggding(byte) */
355
356
357 } /* Base64 */
358
359
Popular Tags