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 B64Code()
58 {
59 }
60
61
62
63
64
65
66
67 public static String encode(String s)
68 {
69 return encode(s, (Charset)null);
70 }
71
72
73
74
75
76
77
78
79
80 public static String encode(String s,String charEncoding)
81 {
82 byte[] bytes;
83 if (charEncoding==null)
84 bytes=s.getBytes(StandardCharsets.ISO_8859_1);
85 else
86 bytes=s.getBytes(Charset.forName(charEncoding));
87 return new String(encode(bytes));
88 }
89
90
91
92
93
94
95
96
97 public static String encode(String s, Charset charEncoding)
98 {
99 byte[] bytes=s.getBytes(charEncoding==null ? StandardCharsets.ISO_8859_1 : charEncoding);
100 return new String(encode(bytes));
101 }
102
103
104
105
106
107
108
109
110 public static char[] encode(byte[] b)
111 {
112 if (b==null)
113 return null;
114
115 int bLen=b.length;
116 int cLen=((bLen+2)/3)*4;
117 char c[]=new char[cLen];
118 int ci=0;
119 int bi=0;
120 byte b0, b1, b2;
121 int stop=(bLen/3)*3;
122 while (bi<stop)
123 {
124 b0=b[bi++];
125 b1=b[bi++];
126 b2=b[bi++];
127 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
128 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
129 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03];
130 c[ci++]=__rfc1421alphabet[b2&0x3f];
131 }
132
133 if (bLen!=bi)
134 {
135 switch (bLen%3)
136 {
137 case 2:
138 b0=b[bi++];
139 b1=b[bi++];
140 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
141 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
142 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
143 c[ci++]=__pad;
144 break;
145
146 case 1:
147 b0=b[bi++];
148 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
149 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
150 c[ci++]=__pad;
151 c[ci++]=__pad;
152 break;
153
154 default:
155 break;
156 }
157 }
158
159 return c;
160 }
161
162
163
164
165
166
167
168
169
170 public static char[] encode(byte[] b, boolean rfc2045)
171 {
172 if (b==null)
173 return null;
174 if (!rfc2045)
175 return encode(b);
176
177 int bLen=b.length;
178 int cLen=((bLen+2)/3)*4;
179 cLen+=2+2*(cLen/76);
180 char c[]=new char[cLen];
181 int ci=0;
182 int bi=0;
183 byte b0, b1, b2;
184 int stop=(bLen/3)*3;
185 int l=0;
186 while (bi<stop)
187 {
188 b0=b[bi++];
189 b1=b[bi++];
190 b2=b[bi++];
191 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
192 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
193 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03];
194 c[ci++]=__rfc1421alphabet[b2&0x3f];
195 l+=4;
196 if (l%76==0)
197 {
198 c[ci++]=13;
199 c[ci++]=10;
200 }
201 }
202
203 if (bLen!=bi)
204 {
205 switch (bLen%3)
206 {
207 case 2:
208 b0=b[bi++];
209 b1=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];
213 c[ci++]=__pad;
214 break;
215
216 case 1:
217 b0=b[bi++];
218 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
219 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
220 c[ci++]=__pad;
221 c[ci++]=__pad;
222 break;
223
224 default:
225 break;
226 }
227 }
228
229 c[ci++]=13;
230 c[ci++]=10;
231 return c;
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245 public static String decode(String encoded,String charEncoding)
246 {
247 byte[] decoded=decode(encoded);
248 if (charEncoding==null)
249 return new String(decoded);
250 return new String(decoded,Charset.forName(charEncoding));
251 }
252
253
254
255
256
257
258
259
260
261
262
263 public static String decode(String encoded, Charset charEncoding)
264 {
265 byte[] decoded=decode(encoded);
266 if (charEncoding==null)
267 return new String(decoded);
268 return new String(decoded, charEncoding);
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282
283 public static byte[] decode(char[] b)
284 {
285 if (b==null)
286 return null;
287
288 int bLen=b.length;
289 if (bLen%4!=0)
290 throw new IllegalArgumentException("Input block size is not 4");
291
292 int li=bLen-1;
293 while (li>=0 && b[li]==(byte)__pad)
294 li--;
295
296 if (li<0)
297 return new byte[0];
298
299
300 int rLen=((li+1)*3)/4;
301 byte r[]=new byte[rLen];
302 int ri=0;
303 int bi=0;
304 int stop=(rLen/3)*3;
305 byte b0,b1,b2,b3;
306 try
307 {
308 while (ri<stop)
309 {
310 b0=__rfc1421nibbles[b[bi++]];
311 b1=__rfc1421nibbles[b[bi++]];
312 b2=__rfc1421nibbles[b[bi++]];
313 b3=__rfc1421nibbles[b[bi++]];
314 if (b0<0 || b1<0 || b2<0 || b3<0)
315 throw new IllegalArgumentException("Not B64 encoded");
316
317 r[ri++]=(byte)(b0<<2|b1>>>4);
318 r[ri++]=(byte)(b1<<4|b2>>>2);
319 r[ri++]=(byte)(b2<<6|b3);
320 }
321
322 if (rLen!=ri)
323 {
324 switch (rLen%3)
325 {
326 case 2:
327 b0=__rfc1421nibbles[b[bi++]];
328 b1=__rfc1421nibbles[b[bi++]];
329 b2=__rfc1421nibbles[b[bi++]];
330 if (b0<0 || b1<0 || b2<0)
331 throw new IllegalArgumentException("Not B64 encoded");
332 r[ri++]=(byte)(b0<<2|b1>>>4);
333 r[ri++]=(byte)(b1<<4|b2>>>2);
334 break;
335
336 case 1:
337 b0=__rfc1421nibbles[b[bi++]];
338 b1=__rfc1421nibbles[b[bi++]];
339 if (b0<0 || b1<0)
340 throw new IllegalArgumentException("Not B64 encoded");
341 r[ri++]=(byte)(b0<<2|b1>>>4);
342 break;
343
344 default:
345 break;
346 }
347 }
348 }
349 catch (IndexOutOfBoundsException e)
350 {
351 throw new IllegalArgumentException("char "+bi
352 +" was not B64 encoded");
353 }
354
355 return r;
356 }
357
358
359
360
361
362
363
364
365
366 public static byte[] decode(String encoded)
367 {
368 if (encoded==null)
369 return null;
370
371 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);
372 decode(encoded, bout);
373 return bout.toByteArray();
374 }
375
376
377
378
379
380
381
382
383
384
385
386 static public void decode (String encoded, ByteArrayOutputStream bout)
387 {
388 if (encoded==null)
389 return;
390
391 if (bout == null)
392 throw new IllegalArgumentException("No outputstream for decoded bytes");
393
394 int ci=0;
395 byte nibbles[] = new byte[4];
396 int s=0;
397
398 while (ci<encoded.length())
399 {
400 char c=encoded.charAt(ci++);
401
402 if (c==__pad)
403 break;
404
405 if (Character.isWhitespace(c))
406 continue;
407
408 byte nibble=__rfc1421nibbles[c];
409 if (nibble<0)
410 throw new IllegalArgumentException("Not B64 encoded");
411
412 nibbles[s++]=__rfc1421nibbles[c];
413
414 switch(s)
415 {
416 case 1:
417 break;
418 case 2:
419 bout.write(nibbles[0]<<2|nibbles[1]>>>4);
420 break;
421 case 3:
422 bout.write(nibbles[1]<<4|nibbles[2]>>>2);
423 break;
424 case 4:
425 bout.write(nibbles[2]<<6|nibbles[3]);
426 s=0;
427 break;
428 }
429
430 }
431
432 return;
433 }
434
435
436 public static void encode(int value,Appendable buf) throws IOException
437 {
438 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
439 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
440 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
441 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
442 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
443 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]);
444 buf.append('=');
445 }
446
447 public static void encode(long lvalue,Appendable buf) throws IOException
448 {
449 int value=(int)(0xFFFFFFFC&(lvalue>>32));
450 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
451 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
452 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
453 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
454 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
455
456 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
457
458 value=0x0FFFFFFF&(int)lvalue;
459 buf.append(__rfc1421alphabet[0x3f&((0x0FC00000&value)>>22)]);
460 buf.append(__rfc1421alphabet[0x3f&((0x003F0000&value)>>16)]);
461 buf.append(__rfc1421alphabet[0x3f&((0x0000FC00&value)>>10)]);
462 buf.append(__rfc1421alphabet[0x3f&((0x000003F0&value)>>4)]);
463 buf.append(__rfc1421alphabet[0x3f&((0x0000000F&value)<<2)]);
464 }
465 }