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