KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > boot > Base64


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.sslexplorer.boot;
21
22 import java.io.ByteArrayOutputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.OutputStream JavaDoc;
25
26 /**
27  * Base 64 encoding / decoding utility class.
28  *
29  * @author Lee David Painter <a HREF="mailto: lee@3sp.com">&lt;lee@3sp.com&gt;</a>
30  */

31 public class Base64 {
32     private static final byte[] encodingTable = { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
33                     (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O',
34                     (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X',
35                     (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g',
36                     (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
37                     (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
38                     (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
39                     (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
40
41     /**
42      * encode the input data producing a base 64 encoded byte array.
43      *
44      * @param data data to encode
45      * @return a byte array containing the base 64 encoded data.
46      */

47     public static byte[] encode(byte[] data) {
48         byte[] bytes;
49
50         int modulus = data.length % 3;
51         if (modulus == 0) {
52             bytes = new byte[4 * data.length / 3];
53         } else {
54             bytes = new byte[4 * ((data.length / 3) + 1)];
55         }
56
57         int dataLength = (data.length - modulus);
58         int a1, a2, a3;
59         for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {
60             a1 = data[i] & 0xff;
61             a2 = data[i + 1] & 0xff;
62             a3 = data[i + 2] & 0xff;
63
64             bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
65             bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
66             bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
67             bytes[j + 3] = encodingTable[a3 & 0x3f];
68         }
69
70         /*
71          * process the tail end.
72          */

73         int b1, b2, b3;
74         int d1, d2;
75
76         switch (modulus) {
77             case 0: /* nothing left to do */
78                 break;
79             case 1:
80                 d1 = data[data.length - 1] & 0xff;
81                 b1 = (d1 >>> 2) & 0x3f;
82                 b2 = (d1 << 4) & 0x3f;
83
84                 bytes[bytes.length - 4] = encodingTable[b1];
85                 bytes[bytes.length - 3] = encodingTable[b2];
86                 bytes[bytes.length - 2] = (byte) '=';
87                 bytes[bytes.length - 1] = (byte) '=';
88                 break;
89             case 2:
90                 d1 = data[data.length - 2] & 0xff;
91                 d2 = data[data.length - 1] & 0xff;
92
93                 b1 = (d1 >>> 2) & 0x3f;
94                 b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
95                 b3 = (d2 << 2) & 0x3f;
96
97                 bytes[bytes.length - 4] = encodingTable[b1];
98                 bytes[bytes.length - 3] = encodingTable[b2];
99                 bytes[bytes.length - 2] = encodingTable[b3];
100                 bytes[bytes.length - 1] = (byte) '=';
101                 break;
102         }
103
104         return bytes;
105     }
106
107     /*
108      * set up the decoding table.
109      */

110     private static final byte[] decodingTable;
111
112     static {
113         decodingTable = new byte[128];
114
115         for (int i = 'A'; i <= 'Z'; i++) {
116             decodingTable[i] = (byte) (i - 'A');
117         }
118
119         for (int i = 'a'; i <= 'z'; i++) {
120             decodingTable[i] = (byte) (i - 'a' + 26);
121         }
122
123         for (int i = '0'; i <= '9'; i++) {
124             decodingTable[i] = (byte) (i - '0' + 52);
125         }
126
127         decodingTable['+'] = 62;
128         decodingTable['/'] = 63;
129     }
130
131     /**
132      * decode the base 64 encoded input data. It is assumed the input data is
133      * valid.
134      *
135      * @param data data to decode
136      * @return a byte array representing the decoded data.
137      */

138     public static byte[] decode(byte[] data) {
139         byte[] bytes;
140         byte b1, b2, b3, b4;
141
142         if (data[data.length - 2] == '=') {
143             bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
144         } else if (data[data.length - 1] == '=') {
145             bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
146         } else {
147             bytes = new byte[((data.length / 4) * 3)];
148         }
149
150         for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) {
151             b1 = decodingTable[data[i]];
152             b2 = decodingTable[data[i + 1]];
153             b3 = decodingTable[data[i + 2]];
154             b4 = decodingTable[data[i + 3]];
155
156             bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));
157             bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));
158             bytes[j + 2] = (byte) ((b3 << 6) | b4);
159         }
160
161         if (data[data.length - 2] == '=') {
162             b1 = decodingTable[data[data.length - 4]];
163             b2 = decodingTable[data[data.length - 3]];
164
165             bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));
166         } else if (data[data.length - 1] == '=') {
167             b1 = decodingTable[data[data.length - 4]];
168             b2 = decodingTable[data[data.length - 3]];
169             b3 = decodingTable[data[data.length - 2]];
170
171             bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));
172             bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));
173         } else {
174             b1 = decodingTable[data[data.length - 4]];
175             b2 = decodingTable[data[data.length - 3]];
176             b3 = decodingTable[data[data.length - 2]];
177             b4 = decodingTable[data[data.length - 1]];
178
179             bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));
180             bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));
181             bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);
182         }
183
184         return bytes;
185     }
186
187     private static boolean ignore(char c) {
188         return (c == '\n' || c == '\r' || c == '\t' || c == ' ');
189     }
190
191     /**
192      * decode the base 64 encoded String data - whitespace will be ignored.
193      *
194      * @param data data to decod
195      * @return a byte array representing the decoded data.
196      */

197     public static byte[] decode(String JavaDoc data) {
198         ByteArrayOutputStream JavaDoc bOut = new ByteArrayOutputStream JavaDoc();
199
200         try {
201             decode(data, bOut);
202         } catch (IOException JavaDoc e) {
203             throw new RuntimeException JavaDoc("exception decoding base64 string: " + e);
204         }
205
206         return bOut.toByteArray();
207     }
208
209     /**
210      * decode the base 64 encoded String data writing it to the given output
211      * stream, whitespace characters will be ignored.
212      *
213      * @param data data to decode
214      * @param out output stream to write to
215      * @return the number of bytes produced.
216      * @throws IOException
217      */

218     public static int decode(String JavaDoc data, OutputStream JavaDoc out) throws IOException JavaDoc {
219         byte b1, b2, b3, b4;
220         int length = 0;
221
222         int end = data.length();
223
224         while (end > 0) {
225             if (!ignore(data.charAt(end - 1))) {
226                 break;
227             }
228
229             end--;
230         }
231
232         for (int i = 0; i < end - 4; i += 4) {
233             if (ignore(data.charAt(i))) {
234                 continue;
235             }
236
237             b1 = decodingTable[data.charAt(i)];
238             b2 = decodingTable[data.charAt(i + 1)];
239             b3 = decodingTable[data.charAt(i + 2)];
240             b4 = decodingTable[data.charAt(i + 3)];
241
242             out.write((b1 << 2) | (b2 >> 4));
243             out.write((b2 << 4) | (b3 >> 2));
244             out.write((b3 << 6) | b4);
245
246             length += 3;
247         }
248
249         if (data.charAt(end - 2) == '=') {
250             b1 = decodingTable[data.charAt(end - 4)];
251             b2 = decodingTable[data.charAt(end - 3)];
252
253             out.write((b1 << 2) | (b2 >> 4));
254
255             length += 1;
256         } else if (data.charAt(end - 1) == '=') {
257             b1 = decodingTable[data.charAt(end - 4)];
258             b2 = decodingTable[data.charAt(end - 3)];
259             b3 = decodingTable[data.charAt(end - 2)];
260
261             out.write((b1 << 2) | (b2 >> 4));
262             out.write((b2 << 4) | (b3 >> 2));
263
264             length += 2;
265         } else {
266             b1 = decodingTable[data.charAt(end - 4)];
267             b2 = decodingTable[data.charAt(end - 3)];
268             b3 = decodingTable[data.charAt(end - 2)];
269             b4 = decodingTable[data.charAt(end - 1)];
270
271             out.write((b1 << 2) | (b2 >> 4));
272             out.write((b2 << 4) | (b3 >> 2));
273             out.write((b3 << 6) | b4);
274
275             length += 3;
276         }
277
278         return length;
279     }
280 }
281
Popular Tags