Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/B64Code.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
16 // ======================================================================== | |
17 // | |
18 | |
19 package org.eclipse.jetty.util; | |
20 | |
21 import java.io.ByteArrayOutputStream; | |
22 import java.io.IOException; | |
23 import java.io.UnsupportedEncodingException; | |
24 | |
25 | |
26 /* ------------------------------------------------------------ */ | |
27 /** Fast B64 Encoder/Decoder as described in RFC 1421. | |
28 * <p>Does not insert or interpret whitespace as described in RFC | |
29 * 1521. If you require this you must pre/post process your data. | |
30 * <p> Note that in a web context the usual case is to not want | |
31 * linebreaks or other white space in the encoded output. | |
32 * | |
33 */ | |
34 public class B64Code | |
35 { | |
36 // ------------------------------------------------------------------ | |
37 static final char __pad='='; | |
38 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 static final byte[] __rfc1421nibbles; | |
47 | |
48 static | |
49 { | |
50 __rfc1421nibbles=new byte[256]; | |
51 for (int i=0;i<256;i++) | |
52 __rfc1421nibbles[i]=-1; | |
53 for (byte b=0;b<64;b++) | |
54 __rfc1421nibbles[(byte)__rfc1421alphabet[b]]=b; | |
55 __rfc1421nibbles[(byte)__pad]=0; | |
56 } | |
57 | |
58 // ------------------------------------------------------------------ | |
59 /** | |
60 * Base 64 encode as described in RFC 1421. | |
61 * <p>Does not insert whitespace as described in RFC 1521. | |
62 * @param s String to encode. | |
63 * @return String containing the encoded form of the input. | |
64 */ | |
65 static public String encode(String s) | |
66 { | |
67 try | |
68 { | |
69 return encode(s,null); | |
70 } | |
71 catch (UnsupportedEncodingException e) | |
72 { | |
73 throw new IllegalArgumentException(e.toString()); | |
74 } | |
75 } | |
76 | |
77 // ------------------------------------------------------------------ | |
78 /** | |
79 * Base 64 encode as described in RFC 1421. | |
80 * <p>Does not insert whitespace as described in RFC 1521. | |
81 * @param s String to encode. | |
82 * @param charEncoding String representing the name of | |
83 * the character encoding of the provided input String. | |
84 * @return String containing the encoded form of the input. | |
85 */ | |
86 static public String encode(String s,String charEncoding) | |
87 throws UnsupportedEncodingException | |
88 { | |
89 byte[] bytes; | |
90 if (charEncoding==null) | |
91 bytes=s.getBytes(StringUtil.__ISO_8859_1); | |
92 else | |
93 bytes=s.getBytes(charEncoding); | |
94 | |
95 return new String(encode(bytes)); | |
96 } | |
97 | |
98 // ------------------------------------------------------------------ | |
99 /** | |
100 * Fast Base 64 encode as described in RFC 1421. | |
101 * <p>Does not insert whitespace as described in RFC 1521. | |
102 * <p> Avoids creating extra copies of the input/output. | |
103 * @param b byte array to encode. | |
104 * @return char array containing the encoded form of the input. | |
105 */ | |
106 static public char[] encode(byte[] b) | |
107 { | |
108 if (b==null) | |
109 return null; | |
110 | |
111 int bLen=b.length; | |
112 int cLen=((bLen+2)/3)*4; | |
113 char c[]=new char[cLen]; | |
114 int ci=0; | |
115 int bi=0; | |
116 byte b0, b1, b2; | |
117 int stop=(bLen/3)*3; | |
118 while (bi<stop) | |
119 { | |
120 b0=b[bi++]; | |
121 b1=b[bi++]; | |
122 b2=b[bi++]; | |
123 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
124 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f]; | |
125 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03]; | |
126 c[ci++]=__rfc1421alphabet[b2&077]; | |
127 } | |
128 | |
129 if (bLen!=bi) | |
130 { | |
131 switch (bLen%3) | |
132 { | |
133 case 2: | |
134 b0=b[bi++]; | |
135 b1=b[bi++]; | |
136 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
137 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f]; | |
138 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f]; | |
139 c[ci++]=__pad; | |
140 break; | |
141 | |
142 case 1: | |
143 b0=b[bi++]; | |
144 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
145 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f]; | |
146 c[ci++]=__pad; | |
147 c[ci++]=__pad; | |
148 break; | |
149 | |
150 default: | |
151 break; | |
152 } | |
153 } | |
154 | |
155 return c; | |
156 } | |
157 | |
158 // ------------------------------------------------------------------ | |
159 /** | |
160 * Fast Base 64 encode as described in RFC 1421 and RFC2045 | |
161 * <p>Does not insert whitespace as described in RFC 1521, unless rfc2045 is passed as true. | |
162 * <p> Avoids creating extra copies of the input/output. | |
163 * @param b byte array to encode. | |
164 * @param rfc2045 If true, break lines at 76 characters with CRLF | |
165 * @return char array containing the encoded form of the input. | |
166 */ | |
167 static public char[] encode(byte[] b, boolean rfc2045) | |
168 { | |
169 if (b==null) | |
170 return null; | |
171 if (!rfc2045) | |
172 return encode(b); | |
173 | |
174 int bLen=b.length; | |
175 int cLen=((bLen+2)/3)*4; | |
176 cLen+=2+2*(cLen/76); | |
177 char c[]=new char[cLen]; | |
178 int ci=0; | |
179 int bi=0; | |
180 byte b0, b1, b2; | |
181 int stop=(bLen/3)*3; | |
182 int l=0; | |
183 while (bi<stop) | |
184 { | |
185 b0=b[bi++]; | |
186 b1=b[bi++]; | |
187 b2=b[bi++]; | |
188 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
189 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f]; | |
190 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f|(b2>>>6)&0x03]; | |
191 c[ci++]=__rfc1421alphabet[b2&077]; | |
192 l+=4; | |
193 if (l%76==0) | |
194 { | |
195 c[ci++]=13; | |
196 c[ci++]=10; | |
197 } | |
198 } | |
199 | |
200 if (bLen!=bi) | |
201 { | |
202 switch (bLen%3) | |
203 { | |
204 case 2: | |
205 b0=b[bi++]; | |
206 b1=b[bi++]; | |
207 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
208 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f]; | |
209 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f]; | |
210 c[ci++]=__pad; | |
211 break; | |
212 | |
213 case 1: | |
214 b0=b[bi++]; | |
215 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f]; | |
216 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f]; | |
217 c[ci++]=__pad; | |
218 c[ci++]=__pad; | |
219 break; | |
220 | |
221 default: | |
222 break; | |
223 } | |
224 } | |
225 | |
226 c[ci++]=13; | |
227 c[ci++]=10; | |
228 return c; | |
229 } | |
230 | |
231 // ------------------------------------------------------------------ | |
232 /** | |
233 * Base 64 decode as described in RFC 2045. | |
234 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored. | |
235 * @param encoded String to decode. | |
236 * @param charEncoding String representing the character encoding | |
237 * used to map the decoded bytes into a String. | |
238 * @return String decoded byte array. | |
239 * @throws UnsupportedEncodingException if the encoding is not supported | |
240 * @throws IllegalArgumentException if the input is not a valid | |
241 * B64 encoding. | |
242 */ | |
243 static public String decode(String encoded,String charEncoding) | |
244 throws UnsupportedEncodingException | |
245 { | |
246 byte[] decoded=decode(encoded); | |
247 if (charEncoding==null) | |
248 return new String(decoded); | |
249 return new String(decoded,charEncoding); | |
250 } | |
251 | |
252 /* ------------------------------------------------------------ */ | |
253 /** | |
254 * Fast Base 64 decode as described in RFC 1421. | |
255 * | |
256 * <p>Unlike other decode methods, this does not attempt to | |
257 * cope with extra whitespace as described in RFC 1521/2045. | |
258 * <p> Avoids creating extra copies of the input/output. | |
259 * <p> Note this code has been flattened for performance. | |
260 * @param b char array to decode. | |
261 * @return byte array containing the decoded form of the input. | |
262 * @throws IllegalArgumentException if the input is not a valid | |
263 * B64 encoding. | |
264 */ | |
265 static public byte[] decode(char[] b) | |
266 { | |
267 if (b==null) | |
268 return null; | |
269 | |
270 int bLen=b.length; | |
271 if (bLen%4!=0) | |
272 throw new IllegalArgumentException("Input block size is not 4"); | |
273 | |
274 int li=bLen-1; | |
275 while (li>=0 && b[li]==(byte)__pad) | |
276 li--; | |
277 | |
278 if (li<0) | |
279 return new byte[0]; | |
280 | |
281 // Create result array of exact required size. | |
282 int rLen=((li+1)*3)/4; | |
283 byte r[]=new byte[rLen]; | |
284 int ri=0; | |
285 int bi=0; | |
286 int stop=(rLen/3)*3; | |
287 byte b0,b1,b2,b3; | |
288 try | |
289 { | |
290 while (ri<stop) | |
291 { | |
292 b0=__rfc1421nibbles[b[bi++]]; | |
293 b1=__rfc1421nibbles[b[bi++]]; | |
294 b2=__rfc1421nibbles[b[bi++]]; | |
295 b3=__rfc1421nibbles[b[bi++]]; | |
296 if (b0<0 || b1<0 || b2<0 || b3<0) | |
297 throw new IllegalArgumentException("Not B64 encoded"); | |
298 | |
299 r[ri++]=(byte)(b0<<2|b1>>>4); | |
300 r[ri++]=(byte)(b1<<4|b2>>>2); | |
301 r[ri++]=(byte)(b2<<6|b3); | |
302 } | |
303 | |
304 if (rLen!=ri) | |
305 { | |
306 switch (rLen%3) | |
307 { | |
308 case 2: | |
309 b0=__rfc1421nibbles[b[bi++]]; | |
310 b1=__rfc1421nibbles[b[bi++]]; | |
311 b2=__rfc1421nibbles[b[bi++]]; | |
312 if (b0<0 || b1<0 || b2<0) | |
313 throw new IllegalArgumentException("Not B64 encoded"); | |
314 r[ri++]=(byte)(b0<<2|b1>>>4); | |
315 r[ri++]=(byte)(b1<<4|b2>>>2); | |
316 break; | |
317 | |
318 case 1: | |
319 b0=__rfc1421nibbles[b[bi++]]; | |
320 b1=__rfc1421nibbles[b[bi++]]; | |
321 if (b0<0 || b1<0) | |
322 throw new IllegalArgumentException("Not B64 encoded"); | |
323 r[ri++]=(byte)(b0<<2|b1>>>4); | |
324 break; | |
325 | |
326 default: | |
327 break; | |
328 } | |
329 } | |
330 } | |
331 catch (IndexOutOfBoundsException e) | |
332 { | |
333 throw new IllegalArgumentException("char "+bi | |
334 +" was not B64 encoded"); | |
335 } | |
336 | |
337 return r; | |
338 } | |
339 | |
340 /* ------------------------------------------------------------ */ | |
341 /** | |
342 * Base 64 decode as described in RFC 2045. | |
343 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored. | |
344 * @param encoded String to decode. | |
345 * @return byte array containing the decoded form of the input. | |
346 * @throws IllegalArgumentException if the input is not a valid | |
347 * B64 encoding. | |
348 */ | |
349 static public byte[] decode(String encoded) | |
350 { | |
351 if (encoded==null) | |
352 return null; | |
353 | |
354 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3); | |
355 decode(encoded, bout); | |
356 return bout.toByteArray(); | |
357 } | |
358 | |
359 /* ------------------------------------------------------------ */ | |
360 /** | |
361 * Base 64 decode as described in RFC 2045. | |
362 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored. | |
363 * @param encoded String to decode. | |
364 * @param output stream for decoded bytes | |
365 * @return byte array containing the decoded form of the input. | |
366 * @throws IllegalArgumentException if the input is not a valid | |
367 * B64 encoding. | |
368 */ | |
369 static public void decode (String encoded, ByteArrayOutputStream bout) | |
370 { | |
371 if (encoded==null) | |
372 return; | |
373 | |
374 if (bout == null) | |
375 throw new IllegalArgumentException("No outputstream for decoded bytes"); | |
376 | |
377 int ci=0; | |
378 byte nibbles[] = new byte[4]; | |
379 int s=0; | |
380 | |
381 while (ci<encoded.length()) | |
382 { | |
383 char c=encoded.charAt(ci++); | |
384 | |
385 if (c==__pad) | |
386 break; | |
387 | |
388 if (Character.isWhitespace(c)) | |
389 continue; | |
390 | |
391 byte nibble=__rfc1421nibbles[c]; | |
392 if (nibble<0) | |
393 throw new IllegalArgumentException("Not B64 encoded"); | |
394 | |
395 nibbles[s++]=__rfc1421nibbles[c]; | |
396 | |
397 switch(s) | |
398 { | |
399 case 1: | |
400 break; | |
401 case 2: | |
402 bout.write(nibbles[0]<<2|nibbles[1]>>>4); | |
403 break; | |
404 case 3: | |
405 bout.write(nibbles[1]<<4|nibbles[2]>>>2); | |
406 break; | |
407 case 4: | |
408 bout.write(nibbles[2]<<6|nibbles[3]); | |
409 s=0; | |
410 break; | |
411 } | |
412 | |
413 } | |
414 | |
415 return; | |
416 } | |
417 | |
418 | |
419 /* ------------------------------------------------------------ */ | |
420 public static void encode(int value,Appendable buf) throws IOException | |
421 { | |
422 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]); | |
423 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]); | |
424 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]); | |
425 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]); | |
426 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]); | |
427 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]); | |
428 buf.append('='); | |
429 } | |
430 | |
431 /* ------------------------------------------------------------ */ | |
432 public static void encode(long lvalue,Appendable buf) throws IOException | |
433 { | |
434 int value=(int)(0xFFFFFFFC&(lvalue>>32)); | |
435 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]); | |
436 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]); | |
437 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]); | |
438 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]); | |
439 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]); | |
440 | |
441 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]); | |
442 | |
443 value=0x0FFFFFFF&(int)lvalue; | |
444 buf.append(__rfc1421alphabet[0x3f&((0x0FC00000&value)>>22)]); | |
445 buf.append(__rfc1421alphabet[0x3f&((0x003F0000&value)>>16)]); | |
446 buf.append(__rfc1421alphabet[0x3f&((0x0000FC00&value)>>10)]); | |
447 buf.append(__rfc1421alphabet[0x3f&((0x000003F0&value)>>4)]); | |
448 buf.append(__rfc1421alphabet[0x3f&((0x0000000F&value)<<2)]); | |
449 } | |
450 } |