View Javadoc
1   package org.itracker.util;
2   
3   /**
4    * A Base64 Encoder/Decoder.
5    * <p/>
6    * <p/>
7    * This class is used to encode and decode data in Base64 format as described in RFC 1521.
8    * <p/>
9    * <p/>
10   * This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU/LGPL</a> license.<br>
11   * It is provided "as is" without warranty of any kind.<br>
12   * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br>
13   * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br>
14   * <p/>
15   * <p/>
16   * Version history:<br>
17   * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br>
18   * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br>
19   * 2006-11-21 chdh:<br>
20   * &nbsp; Method encode(String) renamed to encodeString(String).<br>
21   * &nbsp; Method decode(String) renamed to decodeString(String).<br>
22   * &nbsp; New method encode(byte[],int) added.<br>
23   * &nbsp; New method decode(String) added.<br>
24   */
25  
26  public class Base64Coder {
27  
28      // Mapping table from 6-bit nibbles to Base64 characters.
29      private static char[] map1 = new char[64];
30  
31      static {
32          int i = 0;
33          for (char c = 'A'; c <= 'Z'; c++) map1[i++] = c;
34          for (char c = 'a'; c <= 'z'; c++) map1[i++] = c;
35          for (char c = '0'; c <= '9'; c++) map1[i++] = c;
36          map1[i++] = '+';
37          map1[i++] = '/';
38      }
39  
40      // Mapping table from Base64 characters to 6-bit nibbles.
41      private static byte[] map2 = new byte[128];
42  
43      static {
44          for (int i = 0; i < map2.length; i++) map2[i] = -1;
45          for (int i = 0; i < 64; i++) map2[map1[i]] = (byte) i;
46      }
47  
48      /**
49       * Encodes a string into Base64 format.
50       * No blanks or line breaks are inserted.
51       *
52       * @param s a String to be encoded.
53       * @return A String with the Base64 encoded data.
54       */
55      public static String encodeString(String s) {
56          return new String(encode(s.getBytes()));
57      }
58  
59      /**
60       * Encodes a byte array into Base64 format.
61       * No blanks or line breaks are inserted.
62       *
63       * @param in an array containing the data bytes to be encoded.
64       * @return A character array with the Base64 encoded data.
65       */
66      public static char[] encode(byte[] in) {
67          return encode(in, in.length);
68      }
69  
70      /**
71       * Encodes a byte array into Base64 format.
72       * No blanks or line breaks are inserted.
73       *
74       * @param in   an array containing the data bytes to be encoded.
75       * @param iLen number of bytes to process in <code>in</code>.
76       * @return A character array with the Base64 encoded data.
77       */
78      public static char[] encode(byte[] in, int iLen) {
79          int oDataLen = (iLen * 4 + 2) / 3;       // output length without padding
80          int oLen = ((iLen + 2) / 3) * 4;         // output length including padding
81          char[] out = new char[oLen];
82          int ip = 0;
83          int op = 0;
84          while (ip < iLen) {
85              int i0 = in[ip++] & 0xff;
86              int i1 = ip < iLen ? in[ip++] & 0xff : 0;
87              int i2 = ip < iLen ? in[ip++] & 0xff : 0;
88              int o0 = i0 >>> 2;
89              int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
90              int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
91              int o3 = i2 & 0x3F;
92              out[op++] = map1[o0];
93              out[op++] = map1[o1];
94              out[op] = op < oDataLen ? map1[o2] : '=';
95              op++;
96              out[op] = op < oDataLen ? map1[o3] : '=';
97              op++;
98          }
99          return out;
100     }
101 
102     /**
103      * Decodes a string from Base64 format.
104      *
105      * @param s a Base64 String to be decoded.
106      * @return A String containing the decoded data.
107      * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
108      */
109     public static String decodeString(String s) {
110         return new String(decode(s));
111     }
112 
113     /**
114      * Decodes a byte array from Base64 format.
115      *
116      * @param s a Base64 String to be decoded.
117      * @return An array containing the decoded data bytes.
118      * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
119      */
120     public static byte[] decode(String s) {
121         return decode(s.toCharArray());
122     }
123 
124     /**
125      * Decodes a byte array from Base64 format.
126      * No blanks or line breaks are allowed within the Base64 encoded data.
127      *
128      * @param in a character array containing the Base64 encoded data.
129      * @return An array containing the decoded data bytes.
130      * @throws IllegalArgumentException if the input is not valid Base64 encoded data.
131      */
132     public static byte[] decode(char[] in) {
133         int iLen = in.length;
134         if (iLen % 4 != 0)
135             throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4.");
136         while (iLen > 0 && in[iLen - 1] == '=') iLen--;
137         int oLen = (iLen * 3) / 4;
138         byte[] out = new byte[oLen];
139         int ip = 0;
140         int op = 0;
141         while (ip < iLen) {
142             int i0 = in[ip++];
143             int i1 = in[ip++];
144             int i2 = ip < iLen ? in[ip++] : 'A';
145             int i3 = ip < iLen ? in[ip++] : 'A';
146             if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
147                 throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
148             int b0 = map2[i0];
149             int b1 = map2[i1];
150             int b2 = map2[i2];
151             int b3 = map2[i3];
152             if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
153                 throw new IllegalArgumentException("Illegal character in Base64 encoded data.");
154             int o0 = (b0 << 2) | (b1 >>> 4);
155             int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
156             int o2 = ((b2 & 3) << 6) | b3;
157             out[op++] = (byte) o0;
158             if (op < oLen) out[op++] = (byte) o1;
159             if (op < oLen) out[op++] = (byte) o2;
160         }
161         return out;
162     }
163 
164     // Dummy constructor.
165     private Base64Coder() {
166     }
167 
168 } // end class Base64Coder