2 // ========================================================================
3 // Copyright (c) 1995-2016 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;
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.
36 private static final char __pad='=';
37 private static final char[] __rfc1421alphabet=
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','+','/'
45 private static final byte[] __rfc1421nibbles;
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;
61 * Base 64 encode as described in RFC 1421.
62 * <p>Does not insert whitespace as described in RFC 1521.
63 * @param s String to encode.
64 * @return String containing the encoded form of the input.
66 public static String encode(String s)
68 return encode(s, (Charset)null);
72 * Base 64 encode as described in RFC 1421.
73 * <p>Does not insert whitespace as described in RFC 1521.
74 * @param s String to encode.
75 * @param charEncoding String representing the name of
76 * the character encoding of the provided input String.
77 * @return String containing the encoded form of the input.
79 public static String encode(String s,String charEncoding)
82 if (charEncoding==null)
83 bytes=s.getBytes(StandardCharsets.ISO_8859_1);
85 bytes=s.getBytes(Charset.forName(charEncoding));
86 return new String(encode(bytes));
90 * Base 64 encode as described in RFC 1421.
91 * <p>Does not insert whitespace as described in RFC 1521.
92 * @param s String to encode.
93 * @param charEncoding The character encoding of the provided input String.
94 * @return String containing the encoded form of the input.
96 public static String encode(String s, Charset charEncoding)
98 byte[] bytes=s.getBytes(charEncoding==null ? StandardCharsets.ISO_8859_1 : charEncoding);
99 return new String(encode(bytes));
103 * Fast Base 64 encode as described in RFC 1421.
104 * <p>Does not insert whitespace as described in RFC 1521.
105 * <p> Avoids creating extra copies of the input/output.
106 * @param b byte array to encode.
107 * @return char array containing the encoded form of the input.
109 public static char[] encode(byte[] b)
115 int cLen=((bLen+2)/3)*4;
116 char c[]=new char[cLen];
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];
139 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
140 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
141 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
147 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
148 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
162 * Fast Base 64 encode as described in RFC 1421 and RFC2045
163 * <p>Does not insert whitespace as described in RFC 1521, unless rfc2045 is passed as true.
164 * <p> Avoids creating extra copies of the input/output.
165 * @param b byte array to encode.
166 * @param rfc2045 If true, break lines at 76 characters with CRLF
167 * @return char array containing the encoded form of the input.
169 public static char[] encode(byte[] b, boolean rfc2045)
177 int cLen=((bLen+2)/3)*4;
179 char c[]=new char[cLen];
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];
209 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
210 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
211 c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
217 c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
218 c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
234 * Base 64 decode as described in RFC 2045.
235 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
236 * @param encoded String to decode.
237 * @param charEncoding String representing the character encoding
238 * used to map the decoded bytes into a String.
239 * @return String decoded byte array.
240 * @throws UnsupportedCharsetException if the encoding is not supported
241 * @throws IllegalArgumentException if the input is not a valid
244 public static String decode(String encoded,String charEncoding)
246 byte[] decoded=decode(encoded);
247 if (charEncoding==null)
248 return new String(decoded);
249 return new String(decoded,Charset.forName(charEncoding));
253 * Base 64 decode as described in RFC 2045.
254 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
255 * @param encoded String to decode.
256 * @param charEncoding Character encoding
257 * used to map the decoded bytes into a String.
258 * @return String decoded byte array.
259 * @throws IllegalArgumentException if the input is not a valid
262 public static String decode(String encoded, Charset charEncoding)
264 byte[] decoded=decode(encoded);
265 if (charEncoding==null)
266 return new String(decoded);
267 return new String(decoded, charEncoding);
271 * Fast Base 64 decode as described in RFC 1421.
273 * <p>Unlike other decode methods, this does not attempt to
274 * cope with extra whitespace as described in RFC 1521/2045.
275 * <p> Avoids creating extra copies of the input/output.
276 * <p> Note this code has been flattened for performance.
277 * @param b char array to decode.
278 * @return byte array containing the decoded form of the input.
279 * @throws IllegalArgumentException if the input is not a valid
282 public static byte[] decode(char[] b)
289 throw new IllegalArgumentException("Input block size is not 4");
292 while (li>=0 && b[li]==(byte)__pad)
298 // Create result array of exact required size.
299 int rLen=((li+1)*3)/4;
300 byte r[]=new byte[rLen];
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");
316 r[ri++]=(byte)(b0<<2|b1>>>4);
317 r[ri++]=(byte)(b1<<4|b2>>>2);
318 r[ri++]=(byte)(b2<<6|b3);
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);
336 b0=__rfc1421nibbles[b[bi++]];
337 b1=__rfc1421nibbles[b[bi++]];
339 throw new IllegalArgumentException("Not B64 encoded");
340 r[ri++]=(byte)(b0<<2|b1>>>4);
348 catch (IndexOutOfBoundsException e)
350 throw new IllegalArgumentException("char "+bi
351 +" was not B64 encoded");
358 * Base 64 decode as described in RFC 2045.
359 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
360 * @param encoded String to decode.
361 * @return byte array containing the decoded form of the input.
362 * @throws IllegalArgumentException if the input is not a valid
365 public static byte[] decode(String encoded)
370 ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);
371 decode(encoded, bout);
372 return bout.toByteArray();
375 /* ------------------------------------------------------------ */
377 * Base 64 decode as described in RFC 2045.
378 * <p>Unlike {@link #decode(char[])}, extra whitespace is ignored.
379 * @param encoded String to decode.
380 * @param bout stream for decoded bytes
381 * @throws IllegalArgumentException if the input is not a valid
384 static public void decode (String encoded, ByteArrayOutputStream bout)
390 throw new IllegalArgumentException("No outputstream for decoded bytes");
393 byte nibbles[] = new byte[4];
396 while (ci<encoded.length())
398 char c=encoded.charAt(ci++);
403 if (Character.isWhitespace(c))
406 byte nibble=__rfc1421nibbles[c];
408 throw new IllegalArgumentException("Not B64 encoded");
410 nibbles[s++]=__rfc1421nibbles[c];
417 bout.write(nibbles[0]<<2|nibbles[1]>>>4);
420 bout.write(nibbles[1]<<4|nibbles[2]>>>2);
423 bout.write(nibbles[2]<<6|nibbles[3]);
434 public static void encode(int value,Appendable buf) throws IOException
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)]);
445 public static void encode(long lvalue,Appendable buf) throws IOException
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)]);
454 buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
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)]);