1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.nio.charset.Charset;
24 import java.nio.charset.UnsupportedCharsetException;
25
26
27
28
29
30
31
32
33
34 public class B64Code
35 {
36 private static final char __pad='=';
37 private static final char[] __rfc1421alphabet=
38 {
39 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
40 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
41 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
42 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
43 };
44
45 private static final byte[] __rfc1421nibbles;
46 static
47 {
48 __rfc1421nibbles=new byte[256];
49 for (int i=0;i<256;i++)
50 __rfc1421nibbles[i]=-1;
51 for (byte b=0;b<64;b++)
52 __rfc1421nibbles[(byte)__rfc1421alphabet[b]]=b;
53 __rfc1421nibbles[(byte)__pad]=0;
54 }
55
56 private B64Code()
57 {
58 }
59
60
61
62
63
64
65
66 public static String encode(String s)
67 {
68 return encode(s,null);
69 }
70
71
72
73
74
75
76
77
78
79 public static String encode(String s,String charEncoding)
80 {
81 byte[] bytes;
82 if (charEncoding==null)
83 bytes=s.getBytes(Charset.forName(StringUtil.__ISO_8859_1));
84 else
85 bytes=s.getBytes(Charset.forName(charEncoding));
86 return new String(encode(bytes));
87 }
88
89
90
91
92
93
94
95
96 public static char[] encode(byte[] b)
97 {
98 if (b==null)
99 return null;
100
101 int bLen=b.length;
102 int cLen=((bLen+2)/3)*4;
103 char c[]=new char[cLen];
104 int ci=0;
105 int bi=0;
106 byte b0, b1, b2;
107 int stop=(bLen/3)*3;
108 while (bi<stop)
109 {
110 b0=b[bi++];
111 b1=b[bi++];
112 b2=b[bi++];
113 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
114 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
115 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03];
116 c[ci++]=__rfc1421alphabet[b2&0x3f];
117 }
118
119 if (bLen!=bi)
120 {
121 switch (bLen%3)
122 {
123 case 2:
124 b0=b[bi++];
125 b1=b[bi++];
126 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
127 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
128 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
129 c[ci++]=__pad;
130 break;
131
132 case 1:
133 b0=b[bi++];
134 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
135 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
136 c[ci++]=__pad;
137 c[ci++]=__pad;
138 break;
139
140 default:
141 break;
142 }
143 }
144
145 return c;
146 }
147
148
149
150
151
152
153
154
155
156 public static char[] encode(byte[] b, boolean rfc2045)
157 {
158 if (b==null)
159 return null;
160 if (!rfc2045)
161 return encode(b);
162
163 int bLen=b.length;
164 int cLen=((bLen+2)/3)*4;
165 cLen+=2+2*(cLen/76);
166 char c[]=new char[cLen];
167 int ci=0;
168 int bi=0;
169 byte b0, b1, b2;
170 int stop=(bLen/3)*3;
171 int l=0;
172 while (bi<stop)
173 {
174 b0=b[bi++];
175 b1=b[bi++];
176 b2=b[bi++];
177 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
178 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
179 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03];
180 c[ci++]=__rfc1421alphabet[b2&0x3f];
181 l+=4;
182 if (l%76==0)
183 {
184 c[ci++]=13;
185 c[ci++]=10;
186 }
187 }
188
189 if (bLen!=bi)
190 {
191 switch (bLen%3)
192 {
193 case 2:
194 b0=b[bi++];
195 b1=b[bi++];
196 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
197 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
198 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
199 c[ci++]=__pad;
200 break;
201
202 case 1:
203 b0=b[bi++];
204 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
205 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
206 c[ci++]=__pad;
207 c[ci++]=__pad;
208 break;
209
210 default:
211 break;
212 }
213 }
214
215 c[ci++]=13;
216 c[ci++]=10;
217 return c;
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231 public static String decode(String encoded,String charEncoding)
232 {
233 byte[] decoded=decode(encoded);
234 if (charEncoding==null)
235 return new String(decoded);
236 return new String(decoded,Charset.forName(charEncoding));
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251 public static byte[] decode(char[] b)
252 {
253 if (b==null)
254 return null;
255
256 int bLen=b.length;
257 if (bLen%4!=0)
258 throw new IllegalArgumentException("Input block size is not 4");
259
260 int li=bLen-1;
261 while (li>=0 && b[li]==(byte)__pad)
262 li--;
263
264 if (li<0)
265 return new byte[0];
266
267
268 int rLen=((li+1)*3)/4;
269 byte r[]=new byte[rLen];
270 int ri=0;
271 int bi=0;
272 int stop=(rLen/3)*3;
273 byte b0,b1,b2,b3;
274 try
275 {
276 while (ri<stop)
277 {
278 b0=__rfc1421nibbles[b[bi++]];
279 b1=__rfc1421nibbles[b[bi++]];
280 b2=__rfc1421nibbles[b[bi++]];
281 b3=__rfc1421nibbles[b[bi++]];
282 if (b0<0 || b1<0 || b2<0 || b3<0)
283 throw new IllegalArgumentException("Not B64 encoded");
284
285 r[ri++]=(byte)(b0<<2|b1>>>4);
286 r[ri++]=(byte)(b1<<4|b2>>>2);
287 r[ri++]=(byte)(b2<<6|b3);
288 }
289
290 if (rLen!=ri)
291 {
292 switch (rLen%3)
293 {
294 case 2:
295 b0=__rfc1421nibbles[b[bi++]];
296 b1=__rfc1421nibbles[b[bi++]];
297 b2=__rfc1421nibbles[b[bi++]];
298 if (b0<0 || b1<0 || b2<0)
299 throw new IllegalArgumentException("Not B64 encoded");
300 r[ri++]=(byte)(b0<<2|b1>>>4);
301 r[ri++]=(byte)(b1<<4|b2>>>2);
302 break;
303
304 case 1:
305 b0=__rfc1421nibbles[b[bi++]];
306 b1=__rfc1421nibbles[b[bi++]];
307 if (b0<0 || b1<0)
308 throw new IllegalArgumentException("Not B64 encoded");
309 r[ri++]=(byte)(b0<<2|b1>>>4);
310 break;
311
312 default:
313 break;
314 }
315 }
316 }
317 catch (IndexOutOfBoundsException e)
318 {
319 throw new IllegalArgumentException("char "+bi
320 +" was not B64 encoded");
321 }
322
323 return r;
324 }
325
326
327
328
329
330
331
332
333
334 public static byte[] decode(String encoded)
335 {
336 if (encoded==null)
337 return null;
338
339 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);
340 decode(encoded, bout);
341 return bout.toByteArray();
342 }
343
344
345
346
347
348
349
350
351
352
353
354 static public void decode (String encoded, ByteArrayOutputStream bout)
355 {
356 if (encoded==null)
357 return;
358
359 if (bout == null)
360 throw new IllegalArgumentException("No outputstream for decoded bytes");
361
362 int ci=0;
363 byte nibbles[] = new byte[4];
364 int s=0;
365
366 while (ci<encoded.length())
367 {
368 char c=encoded.charAt(ci++);
369
370 if (c==__pad)
371 break;
372
373 if (Character.isWhitespace(c))
374 continue;
375
376 byte nibble=__rfc1421nibbles[c];
377 if (nibble<0)
378 throw new IllegalArgumentException("Not B64 encoded");
379
380 nibbles[s++]=__rfc1421nibbles[c];
381
382 switch(s)
383 {
384 case 1:
385 break;
386 case 2:
387 bout.write(nibbles[0]<<2|nibbles[1]>>>4);
388 break;
389 case 3:
390 bout.write(nibbles[1]<<4|nibbles[2]>>>2);
391 break;
392 case 4:
393 bout.write(nibbles[2]<<6|nibbles[3]);
394 s=0;
395 break;
396 }
397
398 }
399
400 return;
401 }
402
403
404 public static void encode(int value,Appendable buf) throws IOException
405 {
406 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
407 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
408 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
409 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
410 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
411 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]);
412 buf.append('=');
413 }
414
415 public static void encode(long lvalue,Appendable buf) throws IOException
416 {
417 int value=(int)(0xFFFFFFFC&(lvalue>>32));
418 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
419 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
420 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
421 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
422 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
423
424 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
425
426 value=0x0FFFFFFF&(int)lvalue;
427 buf.append(__rfc1421alphabet[0x3f&((0x0FC00000&value)>>22)]);
428 buf.append(__rfc1421alphabet[0x3f&((0x003F0000&value)>>16)]);
429 buf.append(__rfc1421alphabet[0x3f&((0x0000FC00&value)>>10)]);
430 buf.append(__rfc1421alphabet[0x3f&((0x000003F0&value)>>4)]);
431 buf.append(__rfc1421alphabet[0x3f&((0x0000000F&value)<<2)]);
432 }
433 }