KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > ristretto > coder > Base64


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is Ristretto Mail API.
15  *
16  * The Initial Developers of the Original Code are
17  * Timo Stich and Frederik Dietz.
18  * Portions created by the Initial Developers are Copyright (C) 2004
19  * All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */

36 package org.columba.ristretto.coder;
37
38 import java.nio.ByteBuffer JavaDoc;
39 import java.nio.charset.Charset JavaDoc;
40
41 /**
42  * Implementation of base64 en- and decoding methods.
43  * Base64 coding is used to efficiently represent a ByteBuffer as
44  * an US-ASCII compatible String.
45  * <br>
46  * <b>Note:</b> The size of the coded input will increase by about 33%.
47  *
48  * <br>
49  * <b>RFC(s):</b> 2045
50  *
51  * @author Timo Stich <tstich@users.sourceforge.net>
52  */

53 public class Base64 {
54     private static final char[] etable = {
55          65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
56          75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
57          85, 86, 87, 88, 89, 90, 97, 98, 99,100,
58         101,102,103,104,105,106,107,108,109,110,
59         111,112,113,114,115,116,117,118,119,120,
60         121,122, 48, 49, 50, 51, 52, 53, 54, 55,
61          56, 57, 43, 47 };
62
63     
64     // US-ASCII to Base64 Table
65

66     private static byte[] dtable =
67         {
68             000,
69             000,
70             000,
71             000,
72             000,
73             000,
74             000,
75             000,
76             000,
77             000,
78             000,
79             000,
80             000,
81             000,
82             000,
83             000,
84             000,
85             000,
86             000,
87             000,
88             000,
89             000,
90             000,
91             000,
92             000,
93             000,
94             000,
95             000,
96             000,
97             000,
98             000,
99             000,
100             000,
101             000,
102             000,
103             000,
104             000,
105             000,
106             000,
107             000,
108             000,
109             000,
110             000,
111             62,
112             000,
113             000,
114             000,
115             63,
116             52,
117             53,
118         // + / 0..
119
54, 55, 56, 57, 58, 59, 60, 61, 000, 000, // ..9
120
000, 0, 000, 000, 000, 0, 1, 2, 3, 4, // = A..
121
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // ..
122
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //
123
25, 000, 000, 000, 000, 000, 000, 26, 27, 28, // ..Z a..
124
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // ..
125
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // ..
126
49, 50, 51, 000, 000, 000, 000, 000 }; // ..z
127

128     /**
129      * Takes a base64 encoded String and decodes it into a ByteBuffer.
130      * If you need to have a byte array use decodeToArray.
131      *
132      * @param input a base64 String
133      * @return the decoded ByteBuffer
134      */

135     public static ByteBuffer JavaDoc decode(CharSequence JavaDoc input) {
136         // Create OutBuffer with maximal possible size
137
int size = (int) (input.length() * .75);
138         
139         byte[] outBytes = new byte[size];
140         byte[] pack = new byte[4];
141         int outPos = 0;
142         int packSize = 0;
143         int pads = 0;
144         char current;
145
146         // Decode the input
147
for (int i = 0; i < input.length(); i++) {
148             current = input.charAt(i);
149             if (current != '\r' && current != '\n') {
150                 pack[packSize++] = (byte) current;
151                 if (current == '=') {
152                     pads++;
153                 }
154             }
155             if (packSize == 4) {
156                 outBytes[outPos++] =
157                     (byte) ((dtable[pack[0]] << 2) | (dtable[pack[1]] >> 4));
158                 if (pads < 2)
159                     outBytes[outPos++] =
160                         (byte) ((dtable[pack[1]] << 4) | (dtable[pack[2]] >> 2));
161                 if (pads < 1)
162                     outBytes[outPos++] =
163                         (byte) ((dtable[pack[2]] << 6) | (dtable[pack[3]]));
164                 packSize = 0;
165                 if( pads != 0) break;
166             }
167         }
168
169         // Shorten the outBytes to the exact size if nessecary
170
return ByteBuffer.wrap(outBytes,0,outPos);
171     }
172     
173     /**
174      * Takes a base64 encoded String and decodes it into a byte[].
175      *
176      * @param input
177      * @return the base64 encoded input
178      */

179     public static byte[] decodeToArray(CharSequence JavaDoc input) {
180         ByteBuffer JavaDoc buffer = Base64.decode(input);
181         if( buffer.limit() == buffer.capacity()) return buffer.array();
182         
183         // Cut of trailing zeros
184
byte[] result = new byte[buffer.limit()];
185         System.arraycopy(buffer.array(),0,result,0,buffer.limit());
186         return result;
187     }
188     
189     /**
190      * Encodes a ByteBuffer in base64 code.
191      * If wrap is true, the output will be wrapped
192      * after 76 characters.
193      *
194      * @param input the raw bytes
195      * @param wrap wraps the output after 76 characters if true
196      * @return the base64 representation of the input
197      */

198     public static StringBuffer JavaDoc encode( ByteBuffer JavaDoc input, boolean wrap ) {
199         int lastPackSize = input.limit() % 3;
200         int estimatedEncodedSize = ((int) (input.limit() * 1.333 + .5)) +2;
201         StringBuffer JavaDoc result = new StringBuffer JavaDoc(estimatedEncodedSize + (estimatedEncodedSize / 76) * 2);
202         int packsPerLine = 0;
203         int i;
204
205         //Encode
206
for( i=0; i<(input.limit() - lastPackSize); i+=3) {
207             result.append( etable[(byte)(0x03F & (input.get(i)>>2))] );
208             result.append( etable[(byte)((0x03F & (input.get(i)<<4)) | (0x00F & (input.get(i+1)>>4)))]);
209             result.append( etable[(byte)((0x03F & (input.get(i+1)<<2)) | (0x003 & (input.get(i+2)>>6)))]);
210             result.append( etable[(byte)(0x03F & input.get(i+2))]);
211             
212             // No more than 76 chars/line
213
packsPerLine++;
214             if( packsPerLine == 25 && wrap) {
215                 result.append("\r\n");
216                 packsPerLine = 0;
217             }
218         }
219         
220         // Handle pads if necessary
221
if( lastPackSize == 2 ) {
222             result.append( etable[(byte)(0x03F & (input.get(i)>>2))] );
223             result.append( etable[(byte)((0x03F & (input.get(i)<<4)) | (0x00F & (input.get(i+1)>>4)))]);
224             result.append( etable[(byte)(0x03F & (input.get(i+1)<<2))] );
225             result.append( '=');
226         }
227         
228         if( lastPackSize == 1 ) {
229             result.append( etable[(byte)(0x03F & (input.get(i)>>2))] );
230             result.append( etable[(byte)(0x03F & (input.get(i)<<4))]);
231             result.append( '=' );
232             result.append( '=');
233         }
234         
235         return result;
236     }
237
238     /**
239      * Takes a String that is encoded in US-ASCII and converts it to base64.
240      * <br>
241      * Convenience method that uses {@link #encode(ByteBuffer)} after
242      * getting the bytes from the string.
243      *
244      * @param input the us-ascii input string
245      * @return StringBuffer with the encoded input
246      */

247     public static StringBuffer JavaDoc encode( String JavaDoc input ) {
248         Charset JavaDoc charset = Charset.forName("US-ASCII");
249         ByteBuffer JavaDoc bytes = charset.encode(input);
250         return encode( bytes);
251     }
252     
253     /**
254      * Encodes a ByteBuffer in base64.
255      * Wraps the result String after 76 characters.
256      *
257      * @see #encode(ByteBuffer, boolean)
258      *
259      * @param buffer
260      * @return StringBuffer with the encoded input
261      */

262     public static StringBuffer JavaDoc encode( ByteBuffer JavaDoc buffer ) {
263         return encode( buffer, true );
264     }
265
266 }
267
Popular Tags