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.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
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;
28 /** Fast B64 Encoder/Decoder as described in RFC 1421.
29 * <p>Does not insert or interpret whitespace as described in RFC
30 * 1521. If you require this you must pre/post process your data.
31 * <p> Note that in a web context the usual case is to not want
32 * linebreaks or other white space in the encoded output.
37 private static final char __pad='=';
38 private static final char[] __rfc1421alphabet=
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','+','/'
46 private static final byte[] __rfc1421nibbles;
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;
62 * Base 64 encode as described in RFC 1421.
63 * <p>Does not insert whitespace as described in RFC 1521.
64 * @param s String to encode.
65 * @return String containing the encoded form of the input.
67 public static String encode(String s)
69 return encode(s, (Charset)null);
73 * Base 64 encode as described in RFC 1421.
74 * <p>Does not insert whitespace as described in RFC 1521.
75 * @param s String to encode.
76 * @param charEncoding String representing the name of
77 * the character encoding of the provided input String.
78 * @return String containing the encoded form of the input.
80 public static String encode(String s,String charEncoding)
83 if (charEncoding==null)
84 bytes=s.getBytes(StandardCharsets.ISO_8859_1);
86 bytes=s.getBytes(Charset.forName(charEncoding));
87 return new String(encode(bytes));
91 * Base 64 encode as described in RFC 1421.
92 * <p>Does not insert whitespace as described in RFC 1521.
93 * @param s String to encode.
94 * @param charEncoding The character encoding of the provided input String.
95 * @return String containing the encoded form of the input.
97 public static String encode(String s, Charset charEncoding)
99 byte[] bytes=s.getBytes(charEncoding==null ? StandardCharsets.ISO_8859_1 : charEncoding);
100 return new String(encode(bytes));
104 * Fast Base 64 encode as described in RFC 1421.
105 * <p>Does not insert whitespace as described in RFC 1521.
106 * <p> Avoids creating extra copies of the input/output.
107 * @param b byte array to encode.
108 * @return char array containing the encoded form of the input.
110 public static char[] encode(byte[] b)
116 int cLen=((bLen+2)/3)*4;
117 char c[]=new char[cLen];
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];
140 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
141 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
142 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
148 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
149 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
163 * Fast Base 64 encode as described in RFC 1421 and RFC2045
164 * <p>Does not insert whitespace as described in RFC 1521, unless rfc2045 is passed as true.
165 * <p> Avoids creating extra copies of the input/output.
166 * @param b byte array to encode.
167 * @param rfc2045 If true, break lines at 76 characters with CRLF
168 * @return char array containing the encoded form of the input.
170 public static char[] encode(byte[] b, boolean rfc2045)
178 int cLen=((bLen+2)/3)*4;
180 char c[]=new char[cLen];
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];
210 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
211 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
212 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
218 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
219 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
235 * Base 64 decode as described in RFC 2045.
236 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
237 * @param encoded String to decode.
238 * @param charEncoding String representing the character encoding
239 * used to map the decoded bytes into a String.
240 * @return String decoded byte array.
241 * @throws UnsupportedCharsetException if the encoding is not supported
242 * @throws IllegalArgumentException if the input is not a valid
245 public static String decode(String encoded,String charEncoding)
247 byte[] decoded=decode(encoded);
248 if (charEncoding==null)
249 return new String(decoded);
250 return new String(decoded,Charset.forName(charEncoding));
254 * Base 64 decode as described in RFC 2045.
255 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
256 * @param encoded String to decode.
257 * @param charEncoding Character encoding
258 * used to map the decoded bytes into a String.
259 * @return String decoded byte array.
260 * @throws IllegalArgumentException if the input is not a valid
263 public static String decode(String encoded, Charset charEncoding)
265 byte[] decoded=decode(encoded);
266 if (charEncoding==null)
267 return new String(decoded);
268 return new String(decoded, charEncoding);
272 * Fast Base 64 decode as described in RFC 1421.
274 * <p>Unlike other decode methods, this does not attempt to
275 * cope with extra whitespace as described in RFC 1521/2045.
276 * <p> Avoids creating extra copies of the input/output.
277 * <p> Note this code has been flattened for performance.
278 * @param b char array to decode.
279 * @return byte array containing the decoded form of the input.
280 * @throws IllegalArgumentException if the input is not a valid
283 public static byte[] decode(char[] b)
290 throw new IllegalArgumentException("Input block size is not 4");
293 while (li>=0 && b[li]==(byte)__pad)
299 // Create result array of exact required size.
300 int rLen=((li+1)*3)/4;
301 byte r[]=new byte[rLen];
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");
317 r[ri++]=(byte)(b0<<2|b1>>>4);
318 r[ri++]=(byte)(b1<<4|b2>>>2);
319 r[ri++]=(byte)(b2<<6|b3);
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);
337 b0=__rfc1421nibbles[b[bi++]];
338 b1=__rfc1421nibbles[b[bi++]];
340 throw new IllegalArgumentException("Not B64 encoded");
341 r[ri++]=(byte)(b0<<2|b1>>>4);
349 catch (IndexOutOfBoundsException e)
351 throw new IllegalArgumentException("char "+bi
352 +" was not B64 encoded");
359 * Base 64 decode as described in RFC 2045.
360 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
361 * @param encoded String to decode.
362 * @return byte array containing the decoded form of the input.
363 * @throws IllegalArgumentException if the input is not a valid
366 public static byte[] decode(String encoded)
371 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);
372 decode(encoded, bout);
373 return bout.toByteArray();
376 /* ------------------------------------------------------------ */
378 * Base 64 decode as described in RFC 2045.
379 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
380 * @param encoded String to decode.
381 * @param bout stream for decoded bytes
382 * @throws IllegalArgumentException if the input is not a valid
385 static public void decode (String encoded, ByteArrayOutputStream bout)
391 throw new IllegalArgumentException("No outputstream for decoded bytes");
394 byte nibbles[] = new byte[4];
397 while (ci<encoded.length())
399 char c=encoded.charAt(ci++);
404 if (Character.isWhitespace(c))
407 byte nibble=__rfc1421nibbles[c];
409 throw new IllegalArgumentException("Not B64 encoded");
411 nibbles[s++]=__rfc1421nibbles[c];
418 bout.write(nibbles[0]<<2|nibbles[1]>>>4);
421 bout.write(nibbles[1]<<4|nibbles[2]>>>2);
424 bout.write(nibbles[2]<<6|nibbles[3]);
435 public static void encode(int value,Appendable buf) throws IOException
437 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
438 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
439 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
440 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
441 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
442 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4)]);
446 public static void encode(long lvalue,Appendable buf) throws IOException
448 int value=(int)(0xFFFFFFFC&(lvalue>>32));
449 buf.append(__rfc1421alphabet[0x3f&((0xFC000000&value)>>26)]);
450 buf.append(__rfc1421alphabet[0x3f&((0x03F00000&value)>>20)]);
451 buf.append(__rfc1421alphabet[0x3f&((0x000FC000&value)>>14)]);
452 buf.append(__rfc1421alphabet[0x3f&((0x00003F00&value)>>8)]);
453 buf.append(__rfc1421alphabet[0x3f&((0x000000FC&value)>>2)]);
455 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
457 value=0x0FFFFFFF&(int)lvalue;
458 buf.append(__rfc1421alphabet[0x3f&((0x0FC00000&value)>>22)]);
459 buf.append(__rfc1421alphabet[0x3f&((0x003F0000&value)>>16)]);
460 buf.append(__rfc1421alphabet[0x3f&((0x0000FC00&value)>>10)]);
461 buf.append(__rfc1421alphabet[0x3f&((0x000003F0&value)>>4)]);
462 buf.append(__rfc1421alphabet[0x3f&((0x0000000F&value)<<2)]);