KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > framework > tools > Base64


1 /*
2 Copyright (c) 2000 The Legion Of The Bouncy Castle
3 (http://www.bouncycastle.org)
4
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the Software
10 is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
22  */

23 /**
24  * Copyright (C) 2003-2005 Funambol
25  *
26  * This program is free software; you can redistribute it and/or modify
27  * it under the terms of the GNU General Public License as published by
28  * the Free Software Foundation; either version 2 of the License, or
29  * (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program; if not, write to the Free Software
38  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39  */

40 package sync4j.framework.tools;
41
42 /**
43  * @version $Id: Base64.java,v 1.6 2005/04/26 14:01:41 nichele Exp $
44  *
45  * Just repackaged into sync4j.framework.tools
46  */

47 public class Base64 {
48     private static final byte[] encodingTable = {
49         (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
50         (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
51         (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
52         (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
53         (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
54         (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
55         (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
56         (byte)'v',
57         (byte)'w', (byte)'x', (byte)'y', (byte)'z',
58         (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
59         (byte)'7', (byte)'8', (byte)'9',
60         (byte)'+', (byte)'/'
61     };
62
63     /**
64      * encode the input data producong a base 64 encoded byte array.
65      *
66      * @return a byte array containing the base 64 encoded data.
67      */

68     public static byte[] encode(
69     byte[] data) {
70         byte[] bytes;
71
72         int modulus = data.length % 3;
73         if (modulus == 0) {
74             bytes = new byte[4 * data.length / 3];
75         }
76         else {
77             bytes = new byte[4 * ((data.length / 3) + 1)];
78         }
79
80         int dataLength = (data.length - modulus);
81         int a1, a2, a3;
82         for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {
83             a1 = data[i] & 0xff;
84             a2 = data[i + 1] & 0xff;
85             a3 = data[i + 2] & 0xff;
86
87             bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
88             bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
89             bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
90             bytes[j + 3] = encodingTable[a3 & 0x3f];
91         }
92
93                 /*
94                  * process the tail end.
95                  */

96         int b1, b2, b3;
97         int d1, d2;
98
99         switch (modulus) {
100             case 0: /* nothing left to do */
101                 break;
102             case 1:
103                 d1 = data[data.length - 1] & 0xff;
104                 b1 = (d1 >>> 2) & 0x3f;
105                 b2 = (d1 << 4) & 0x3f;
106
107                 bytes[bytes.length - 4] = encodingTable[b1];
108                 bytes[bytes.length - 3] = encodingTable[b2];
109                 bytes[bytes.length - 2] = (byte)'=';
110                 bytes[bytes.length - 1] = (byte)'=';
111                 break;
112             case 2:
113                 d1 = data[data.length - 2] & 0xff;
114                 d2 = data[data.length - 1] & 0xff;
115
116                 b1 = (d1 >>> 2) & 0x3f;
117                 b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
118                 b3 = (d2 << 2) & 0x3f;
119
120                 bytes[bytes.length - 4] = encodingTable[b1];
121                 bytes[bytes.length - 3] = encodingTable[b2];
122                 bytes[bytes.length - 2] = encodingTable[b3];
123                 bytes[bytes.length - 1] = (byte)'=';
124                 break;
125         }
126
127         return bytes;
128     }
129
130     /*
131      * set up the decoding table.
132      */

133     private static final byte[] decodingTable;
134
135     static {
136         decodingTable = new byte[128];
137
138         for (int i = 0; i < 128; i++) {
139             decodingTable[i] = (byte) -1;
140         }
141
142         for (int i = 'A'; i <= 'Z'; i++) {
143             decodingTable[i] = (byte)(i - 'A');
144         }
145
146         for (int i = 'a'; i <= 'z'; i++) {
147             decodingTable[i] = (byte)(i - 'a' + 26);
148         }
149
150         for (int i = '0'; i <= '9'; i++) {
151             decodingTable[i] = (byte)(i - '0' + 52);
152         }
153
154         decodingTable['+'] = 62;
155         decodingTable['/'] = 63;
156     }
157
158     /**
159      * decode the base 64 encoded input data.
160      *
161      * @return a byte array representing the decoded data.
162      */

163     public static byte[] decode(byte[] data) {
164
165         byte[] bytes;
166         byte b1, b2, b3, b4;
167
168         data = discardNonBase64Bytes(data);
169
170         if (data[data.length - 2] == '=') {
171             bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
172         }
173         else if (data[data.length - 1] == '=') {
174             bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
175         }
176         else {
177             bytes = new byte[((data.length / 4) * 3)];
178         }
179
180         for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) {
181             b1 = decodingTable[data[i]];
182             b2 = decodingTable[data[i + 1]];
183             b3 = decodingTable[data[i + 2]];
184             b4 = decodingTable[data[i + 3]];
185
186             bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
187             bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
188             bytes[j + 2] = (byte)((b3 << 6) | b4);
189         }
190
191         if (data[data.length - 2] == '=') {
192             b1 = decodingTable[data[data.length - 4]];
193             b2 = decodingTable[data[data.length - 3]];
194
195             bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
196         }
197         else if (data[data.length - 1] == '=') {
198             b1 = decodingTable[data[data.length - 4]];
199             b2 = decodingTable[data[data.length - 3]];
200             b3 = decodingTable[data[data.length - 2]];
201
202             bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
203             bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
204         }
205         else {
206             b1 = decodingTable[data[data.length - 4]];
207             b2 = decodingTable[data[data.length - 3]];
208             b3 = decodingTable[data[data.length - 2]];
209             b4 = decodingTable[data[data.length - 1]];
210
211             bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
212             bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
213             bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
214         }
215
216         return bytes;
217     }
218
219     /**
220      * decode the base 64 encoded String data.
221      *
222      * @return a byte array representing the decoded data.
223      */

224     public static byte[] decode(String JavaDoc data) {
225         byte[] bytes;
226         byte b1, b2, b3, b4;
227
228         data = discardNonBase64Chars(data);
229
230         if (data.charAt(data.length() - 2) == '=') {
231             bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
232         }
233         else if (data.charAt(data.length() - 1) == '=') {
234             bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
235         }
236         else {
237             bytes = new byte[((data.length() / 4) * 3)];
238         }
239
240         for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) {
241             b1 = decodingTable[data.charAt(i)];
242             b2 = decodingTable[data.charAt(i + 1)];
243             b3 = decodingTable[data.charAt(i + 2)];
244             b4 = decodingTable[data.charAt(i + 3)];
245
246             bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
247             bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
248             bytes[j + 2] = (byte)((b3 << 6) | b4);
249         }
250
251         if (data.charAt(data.length() - 2) == '=') {
252             b1 = decodingTable[data.charAt(data.length() - 4)];
253             b2 = decodingTable[data.charAt(data.length() - 3)];
254
255             bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
256         }
257         else if (data.charAt(data.length() - 1) == '=') {
258             b1 = decodingTable[data.charAt(data.length() - 4)];
259             b2 = decodingTable[data.charAt(data.length() - 3)];
260             b3 = decodingTable[data.charAt(data.length() - 2)];
261
262             bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
263             bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
264         }
265         else {
266             b1 = decodingTable[data.charAt(data.length() - 4)];
267             b2 = decodingTable[data.charAt(data.length() - 3)];
268             b3 = decodingTable[data.charAt(data.length() - 2)];
269             b4 = decodingTable[data.charAt(data.length() - 1)];
270
271             bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
272             bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
273             bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
274         }
275
276         return bytes;
277     }
278
279     // --------------------------------------------------------- Private Methods
280

281     /**
282      * Discards any characters outside of the base64 alphabet (see page 25 of RFC 2045)
283      * "Any characters outside of the base64 alphabet are to be ignored in base64
284      * encoded data."
285      *
286      * @param data the base64 encoded data
287      * @return the data, less non-base64 characters.
288      */

289     private static byte[] discardNonBase64Bytes(byte[] data) {
290         byte temp[] = new byte[data.length];
291         int bytesCopied = 0;
292
293         for (int i = 0; i < data.length; i++) {
294             if (isValidBase64Byte(data[i])) {
295                 temp[bytesCopied++] = data[i];
296             }
297         }
298
299         byte newData[] = new byte[bytesCopied];
300
301         System.arraycopy(temp, 0, newData, 0, bytesCopied);
302
303         return newData;
304     }
305
306     /**
307      * Discards any characters outside of the base64 alphabet (see page 25 of RFC 2045)
308      * "Any characters outside of the base64 alphabet are to be ignored in base64
309      * encoded data."
310      *
311      * @param data the base64 encoded data
312      * @return the data, less non-base64 characters.
313      */

314     private static String JavaDoc discardNonBase64Chars(String JavaDoc data) {
315
316         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
317
318         int length = data.length();
319
320         for (int i = 0; i < length; i++) {
321             if (isValidBase64Byte((byte)(data.charAt(i)))) {
322                 sb.append(data.charAt(i));
323             }
324         }
325
326         return sb.toString();
327     }
328
329     /**
330      * Checks is the given byte is in base64 alphabet
331      * @param b the byte to check
332      * @return boolean true if the byte is in base64 alphabet
333      */

334     private static boolean isValidBase64Byte(byte b) {
335         if (b == '=') {
336             return true;
337         } else if (b < 0 || b >= 128) {
338             return false;
339         } else if (decodingTable[b] == -1) {
340             return false;
341         }
342         return true;
343     }
344 }
345
Popular Tags