View Javadoc

1   //////////////////////license & copyright header///////////////////////
2   
3   //                                                                   //
4   
5   //                Copyright (c) 1998 by Kevin Kelley                 //
6   
7   //                                                                   //
8   
9   // This program is free software; you can redistribute it and/or     //
10  
11  // modify it under the terms of the GNU General Public License as    //
12  
13  // published by the Free Software Foundation; either version 2 of    //
14  
15  // the License, or (at your option) any later version.               //
16  
17  //                                                                   //
18  
19  // This program is distributed in the hope that it will be useful,   //
20  
21  // but WITHOUT ANY WARRANTY; without even the implied warranty of    //
22  
23  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     //
24  
25  // GNU General Public License for more details.                      //
26  
27  //                                                                   //
28  
29  // You should have received a copy of the GNU General Public License //
30  
31  // along with this program in the file 'gpl.html'; if not, write to  //
32  
33  // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,  //
34  
35  // Boston, MA 02111-1307, USA, or contact the author:                //
36  
37  //                                                                   //
38  
39  //                       Kevin Kelley  <kelley@iguana.ruralnet.net>  //
40  
41  //                                                                   //
42  
43  ////////////////////end license & copyright header/////////////////////
44  
45  package JADE_SL;
46  
47  
48  
49  /***
50  
51  *   Provides encoding of raw bytes to base64-encoded characters, and
52  
53  *  decoding of base64 characters to raw bytes.
54  
55  *
56  
57  * @author Kevin Kelley (kelley@iguana.ruralnet.net)
58  
59  * @version 1.0
60  
61  * @date 06 August 1998
62  
63  */
64  
65  public class Base64 {
66  
67  
68  
69  /***
70  
71  * returns an array of base64-encoded characters to represent the
72  
73  * passed data array.
74  
75  *
76  
77  * @param data the array of bytes to encode
78  
79  * @return base64-coded character array.
80  
81  */
82  
83  static public char[] encode(byte[] data)
84  
85  {
86  
87      char[] out = new char[((data.length + 2) / 3) * 4];
88  
89  
90  
91      //
92  
93      // 3 bytes encode to 4 chars.  Output is always an even
94  
95      // multiple of 4 characters.
96  
97      //
98  
99      for (int i=0, index=0; i<data.length; i+=3, index+=4) {
100 
101         boolean quad = false;
102 
103         boolean trip = false;
104 
105 
106 
107         int val = (0xFF & (int) data[i]);
108 
109         val <<= 8;
110 
111         if ((i+1) < data.length) {
112 
113             val |= (0xFF & (int) data[i+1]);
114 
115             trip = true;
116 
117         }
118 
119         val <<= 8;
120 
121         if ((i+2) < data.length) {
122 
123             val |= (0xFF & (int) data[i+2]);
124 
125             quad = true;
126 
127         }
128 
129         out[index+3] = alphabet[(quad? (val & 0x3F): 64)];
130 
131         val >>= 6;
132 
133         out[index+2] = alphabet[(trip? (val & 0x3F): 64)];
134 
135         val >>= 6;
136 
137         out[index+1] = alphabet[val & 0x3F];
138 
139         val >>= 6;
140 
141         out[index+0] = alphabet[val & 0x3F];
142 
143     }
144 
145     return out;
146 
147 }
148 
149 
150 
151 /***
152 
153 * Returns an array of bytes which were encoded in the passed
154 
155 * character array.
156 
157 *
158 
159 * @param data the array of base64-encoded characters
160 
161 * @return decoded data array
162 
163 */
164 
165 static public byte[] decode(char[] data)
166 
167 {
168 
169     int len = ((data.length + 3) / 4) * 3;
170 
171     if (data.length>0 && data[data.length-1] == '=') --len;
172 
173     if (data.length>1 && data[data.length-2] == '=') --len;
174 
175     byte[] out = new byte[len];
176 
177 
178 
179     int shift = 0;   // # of excess bits stored in accum
180 
181     int accum = 0;   // excess bits
182 
183     int index = 0;
184 
185 
186 
187     for (int ix=0; ix<data.length; ix++)
188 
189     {
190 
191         int value = codes[ data[ix] & 0xFF ];   // ignore high byte of char
192 
193         if ( value >= 0 ) {                     // skip over non-code
194 
195             accum <<= 6;            // bits shift up by 6 each time thru
196 
197             shift += 6;             // loop, with new bits being put in
198 
199             accum |= value;         // at the bottom.
200 
201             if ( shift >= 8 ) {     // whenever there are 8 or more shifted in,
202 
203                 shift -= 8;         // write them out (from the top, leaving any
204 
205                 out[index++] =      // excess at the bottom for next iteration.
206 
207                     (byte) ((accum >> shift) & 0xff);
208 
209     }   }   }
210 
211     if (index != out.length)
212 
213         throw new Error("miscalculated data length!");
214 
215 
216 
217     return out;
218 
219 }
220 
221 
222 
223 //
224 
225 // code characters for values 0..63
226 
227 //
228 
229 static private char[] alphabet =
230 
231     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
232 
233         .toCharArray();
234 
235 
236 
237 //
238 
239 // lookup table for converting base64 characters to value in range 0..63
240 
241 //
242 
243 static private byte[] codes = new byte[256];
244 
245 static {
246 
247     for (int i=0; i<256; i++) codes[i] = -1;
248 
249     for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte)(     i - 'A');
250 
251     for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte)(26 + i - 'a');
252 
253     for (int i = '0'; i <= '9'; i++) codes[i] = (byte)(52 + i - '0');
254 
255     codes['+'] = 62;
256 
257     codes['/'] = 63;
258 
259 }
260 
261 
262 
263 }
264