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 int ci=0;
340 byte nibbles[] = new byte[4];
341 int s=0;
342 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);
343
344 while (ci<encoded.length())
345 {
346 char c=encoded.charAt(ci++);
347
348 if (c==__pad)
349 break;
350
351 if (Character.isWhitespace(c))
352 continue;
353
354 byte nibble=__rfc1421nibbles[c];
355 if (nibble<0)
356 throw new IllegalArgumentException("Not B64 encoded");
357
358 nibbles[s++]=__rfc1421nibbles[c];
359
360 switch(s)
361 {
362 case 1:
363 break;
364 case 2:
365 bout.write(nibbles[0]<<2|nibbles[1]>>>4);
366 break;
367 case 3:
368 bout.write(nibbles[1]<<4|nibbles[2]>>>2);
369 break;
370 case 4:
371 bout.write(nibbles[2]<<6|nibbles[3]);
372 s=0;
373 break;
374 }
375
376 }
377
378 return bout.toByteArray();
379 }
380
381 public static void encode(int value,Appendable buf) throws IOException
382 {
383 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
384 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
385 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
386 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
387 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
388 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]);
389 buf.append('=');
390 }
391
392 public static void encode(long lvalue,Appendable buf) throws IOException
393 {
394 int value=(int)(0xFFFFFFFC&(lvalue>>32));
395 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
396 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
397 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
398 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
399 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
400
401 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
402
403 value=0x0FFFFFFF&(int)lvalue;
404 buf.append(__rfc1421alphabet[0x3f&((0x0FC00000&value)>>22)]);
405 buf.append(__rfc1421alphabet[0x3f&((0x003F0000&value)>>16)]);
406 buf.append(__rfc1421alphabet[0x3f&((0x0000FC00&value)>>10)]);
407 buf.append(__rfc1421alphabet[0x3f&((0x000003F0&value)>>4)]);
408 buf.append(__rfc1421alphabet[0x3f&((0x0000000F&value)<<2)]);
409 }
410 }