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 } |
