]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/util/B64Code.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / util / B64Code.java
1 //
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.
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.nio.charset.Charset;
24 import java.nio.charset.StandardCharsets;
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     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      * 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.
65      */
66     public static String encode(String s)
67     {
68         return encode(s, (Charset)null);
69     }
70
71     /**
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.
78      */
79     public static String encode(String s,String charEncoding)
80     {
81         byte[] bytes;
82         if (charEncoding==null)
83             bytes=s.getBytes(StandardCharsets.ISO_8859_1);
84         else
85             bytes=s.getBytes(Charset.forName(charEncoding));
86         return new String(encode(bytes));
87     }
88
89     /**
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.
95      */
96     public static String encode(String s, Charset charEncoding)
97     {
98         byte[] bytes=s.getBytes(charEncoding==null ? StandardCharsets.ISO_8859_1 : charEncoding);
99         return new String(encode(bytes));
100     }
101
102     /**
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.
108      */
109     public static char[] encode(byte[] b)
110     {
111         if (b==null)
112             return null;
113
114         int bLen=b.length;
115         int cLen=((bLen+2)/3)*4;
116         char c[]=new char[cLen];
117         int ci=0;
118         int bi=0;
119         byte b0, b1, b2;
120         int stop=(bLen/3)*3;
121         while (bi<stop)
122         {
123             b0=b[bi++];
124             b1=b[bi++];
125             b2=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|(b2>>>6)&0x03];
129             c[ci++]=__rfc1421alphabet[b2&0x3f];
130         }
131
132         if (bLen!=bi)
133         {
134             switch (bLen%3)
135             {
136                 case 2:
137                     b0=b[bi++];
138                     b1=b[bi++];
139                     c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
140                     c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
141                     c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
142                     c[ci++]=__pad;
143                     break;
144
145                 case 1:
146                     b0=b[bi++];
147                     c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
148                     c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
149                     c[ci++]=__pad;
150                     c[ci++]=__pad;
151                     break;
152
153                 default:
154                     break;
155             }
156         }
157
158         return c;
159     }
160
161     /**
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.
168      */
169     public static char[] encode(byte[] b, boolean rfc2045)
170     {
171         if (b==null)
172             return null;
173         if (!rfc2045)
174             return encode(b);
175
176         int bLen=b.length;
177         int cLen=((bLen+2)/3)*4;
178         cLen+=2+2*(cLen/76);
179         char c[]=new char[cLen];
180         int ci=0;
181         int bi=0;
182         byte b0, b1, b2;
183         int stop=(bLen/3)*3;
184         int l=0;
185         while (bi<stop)
186         {
187             b0=b[bi++];
188             b1=b[bi++];
189             b2=b[bi++];
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];
194             l+=4;
195             if (l%76==0)
196             {
197                 c[ci++]=13;
198                 c[ci++]=10;
199             }
200         }
201
202         if (bLen!=bi)
203         {
204             switch (bLen%3)
205             {
206                 case 2:
207                     b0=b[bi++];
208                     b1=b[bi++];
209                     c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
210                     c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f|(b1>>>4)&0x0f];
211                     c[ci++]=__rfc1421alphabet[(b1<<2)&0x3f];
212                     c[ci++]=__pad;
213                     break;
214
215                 case 1:
216                     b0=b[bi++];
217                     c[ci++]=__rfc1421alphabet[(b0>>>2)&0x3f];
218                     c[ci++]=__rfc1421alphabet[(b0<<4)&0x3f];
219                     c[ci++]=__pad;
220                     c[ci++]=__pad;
221                     break;
222
223                 default:
224                     break;
225             }
226         }
227
228         c[ci++]=13;
229         c[ci++]=10;
230         return c;
231     }
232
233     /**
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
242      *         B64 encoding.
243      */
244     public static String decode(String encoded,String charEncoding)
245     {
246         byte[] decoded=decode(encoded);
247         if (charEncoding==null)
248             return new String(decoded);
249         return new String(decoded,Charset.forName(charEncoding));
250     }
251
252     /**
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
260      *         B64 encoding.
261      */
262     public static String decode(String encoded, Charset charEncoding)
263     {
264         byte[] decoded=decode(encoded);
265         if (charEncoding==null)
266             return new String(decoded);
267         return new String(decoded, charEncoding);
268     }
269
270     /**
271      * Fast Base 64 decode as described in RFC 1421.
272      *
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
280      *         B64 encoding.
281      */
282     public static byte[] decode(char[] b)
283     {
284         if (b==null)
285             return null;
286
287         int bLen=b.length;
288         if (bLen%4!=0)
289             throw new IllegalArgumentException("Input block size is not 4");
290
291         int li=bLen-1;
292         while (li>=0 && b[li]==(byte)__pad)
293             li--;
294
295         if (li<0)
296             return new byte[0];
297
298         // Create result array of exact required size.
299         int rLen=((li+1)*3)/4;
300         byte r[]=new byte[rLen];
301         int ri=0;
302         int bi=0;
303         int stop=(rLen/3)*3;
304         byte b0,b1,b2,b3;
305         try
306         {
307             while (ri<stop)
308             {
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");
315
316                 r[ri++]=(byte)(b0<<2|b1>>>4);
317                 r[ri++]=(byte)(b1<<4|b2>>>2);
318                 r[ri++]=(byte)(b2<<6|b3);
319             }
320
321             if (rLen!=ri)
322             {
323                 switch (rLen%3)
324                 {
325                     case 2:
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);
333                         break;
334
335                     case 1:
336                         b0=__rfc1421nibbles[b[bi++]];
337                         b1=__rfc1421nibbles[b[bi++]];
338                         if (b0<0 || b1<0)
339                             throw new IllegalArgumentException("Not B64 encoded");
340                         r[ri++]=(byte)(b0<<2|b1>>>4);
341                         break;
342
343                     default:
344                         break;
345                 }
346             }
347         }
348         catch (IndexOutOfBoundsException e)
349         {
350             throw new IllegalArgumentException("char "+bi
351                     +" was not B64 encoded");
352         }
353
354         return r;
355     }
356
357     /**
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
363      *         B64 encoding.
364      */
365     public static byte[] decode(String encoded)
366     {
367         if (encoded==null)
368             return null;
369
370         ByteArrayOutputStream bout = new ByteArrayOutputStream(4*encoded.length()/3);        
371         decode(encoded, bout);
372         return bout.toByteArray();
373     }
374     
375     /* ------------------------------------------------------------ */
376     /**
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
382      *         B64 encoding.
383      */
384     static public void decode (String encoded, ByteArrayOutputStream bout)
385     {
386         if (encoded==null)
387             return;
388         
389         if (bout == null)
390             throw new IllegalArgumentException("No outputstream for decoded bytes");
391         
392         int ci=0;
393         byte nibbles[] = new byte[4];
394         int s=0;
395   
396         while (ci<encoded.length())
397         {
398             char c=encoded.charAt(ci++);
399
400             if (c==__pad)
401                 break;
402
403             if (Character.isWhitespace(c))
404                 continue;
405
406             byte nibble=__rfc1421nibbles[c];
407             if (nibble<0)
408                 throw new IllegalArgumentException("Not B64 encoded");
409
410             nibbles[s++]=__rfc1421nibbles[c];
411
412             switch(s)
413             {
414                 case 1:
415                     break;
416                 case 2:
417                     bout.write(nibbles[0]<<2|nibbles[1]>>>4);
418                     break;
419                 case 3:
420                     bout.write(nibbles[1]<<4|nibbles[2]>>>2);
421                     break;
422                 case 4:
423                     bout.write(nibbles[2]<<6|nibbles[3]);
424                     s=0;
425                     break;
426             }
427
428         }
429
430         return;
431     }
432     
433
434     public static void encode(int value,Appendable buf) throws IOException
435     {
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)]);
442         buf.append('=');
443     }
444
445     public static void encode(long lvalue,Appendable buf) throws IOException
446     {
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)]);
453
454         buf.append(__rfc1421alphabet[0x3f&((0x00000003&value)<<4) + (0xf&(int)(lvalue>>28))]);
455
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)]);
462     }
463 }