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