1 package name.angoca.zemucan.tools;
2
3 /**
4 * A Base64 Encoder/Decoder.
5 * <p>
6 * This class is used to encode and decode data in Base64 format as described in
7 * RFC 1521.
8 * <p>
9 * This is "Open Source" software and released under the <a
10 * 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 * Version history:<br>
16 * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br>
17 * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br>
18 * 2006-11-21 chdh:<br>
19 * Method encode(String) renamed to encodeString(String).<br>
20 * Method decode(String) renamed to decodeString(String).<br>
21 * New method encode(byte[],int) added.<br>
22 * New method decode(String) added.<br>
23 *
24 * @author Christian d'Heureuse
25 * @version 1.0.0 2010-05-13
26 */
27 public final class Base64 {
28 /**
29 * Mapping table from 6-bit nibbles to Base64 characters.
30 */
31 private static char[] map1 = new char[64];
32
33 /**
34 * Mapping table from Base64 characters to 6-bit nibbles.
35 */
36 private static byte[] map2 = new byte[128];
37 static {
38 int i = 0;
39 for (char c = 'A'; c <= 'Z'; c += 1) {
40 Base64.map1[i] = c;
41 i += 1;
42 }
43 for (char c = 'a'; c <= 'z'; c += 1) {
44 Base64.map1[i] = c;
45 i += 1;
46 }
47 for (char c = '0'; c <= '9'; c += 1) {
48 Base64.map1[i] = c;
49 i += 1;
50 }
51 Base64.map1[i] = '+';
52 i += 1;
53 Base64.map1[i] = '/';
54 i += 1;
55 }
56
57 static {
58 for (int i = 0; i < Base64.map2.length; i += 1) {
59 Base64.map2[i] = -1;
60 }
61 for (int i = 0; i < 64; i += 1) {
62 Base64.map2[Base64.map1[i]] = (byte) i;
63 }
64 }
65
66 /**
67 * Decodes a byte array from Base64 format. No blanks or line breaks are
68 * allowed within the Base64 encoded data.
69 *
70 * @param in
71 * a character array containing the Base64 encoded data.
72 * @return An array containing the decoded data bytes.
73 * @throws IllegalArgumentException
74 * if the input is not valid Base64 encoded data.
75 */
76 public static byte[] decode(final char[] in) {
77 int iLen = in.length;
78 if (iLen % 4 != 0) {
79 throw new IllegalArgumentException(
80 "Length of Base64 encoded input string is not a multiple of 4.");
81 }
82 while ((iLen > 0) && (in[iLen - 1] == '=')) {
83 iLen -= 1;
84 }
85 final int oLen = (iLen * 3) / 4;
86 final byte[] out = new byte[oLen];
87 int ip = 0;
88 int op = 0;
89 while (ip < iLen) {
90 final int i0 = in[ip];
91 ip += 1;
92 final int i1 = in[ip];
93 ip += 1;
94 final int i2 = (ip < iLen) ? in[ip] : 'A';
95 ip += 1;
96 final int i3 = (ip < iLen) ? in[ip] : 'A';
97 ip += 1;
98 if ((i0 > 127) || (i1 > 127) || (i2 > 127) || (i3 > 127)) {
99 throw new IllegalArgumentException(
100 "Illegal character in Base64 encoded data.");
101 }
102 final int b0 = Base64.map2[i0];
103 final int b1 = Base64.map2[i1];
104 final int b2 = Base64.map2[i2];
105 final int b3 = Base64.map2[i3];
106 if ((b0 < 0) || (b1 < 0) || (b2 < 0) || (b3 < 0)) {
107 throw new IllegalArgumentException(
108 "Illegal character in Base64 encoded data.");
109 }
110 final int o0 = (b0 << 2) | (b1 >>> 4);
111 final int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
112 final int o2 = ((b2 & 3) << 6) | b3;
113 out[op] = (byte) o0;
114 op += 1;
115 if (op < oLen) {
116 out[op] = (byte) o1;
117 op += 1;
118 }
119 if (op < oLen) {
120 out[op] = (byte) o2;
121 op += 1;
122 }
123 }
124 return out;
125 }
126
127 /**
128 * Decodes a byte array from Base64 format.
129 *
130 * @param s
131 * a Base64 String to be decoded.
132 * @return An array containing the decoded data bytes.
133 * @throws IllegalArgumentException
134 * if the input is not valid Base64 encoded data.
135 */
136 public static byte[] decode(final String s) {
137 return Base64.decode(s.toCharArray());
138 }
139
140 /**
141 * Decodes a string from Base64 format.
142 *
143 * @param s
144 * a Base64 String to be decoded.
145 * @return A String containing the decoded data.
146 * @throws IllegalArgumentException
147 * if the input is not valid Base64 encoded data.
148 */
149 public static String decodeString(final String s) {
150 return new String(Base64.decode(s));
151 }
152
153 /**
154 * Encodes a byte array into Base64 format. No blanks or line breaks are
155 * inserted.
156 *
157 * @param in
158 * an array containing the data bytes to be encoded.
159 * @return A character array with the Base64 encoded data.
160 */
161 public static char[] encode(final byte[] in) {
162 return Base64.encode(in, in.length);
163 }
164
165 /**
166 * Encodes a byte array into Base64 format. No blanks or line breaks are
167 * inserted.
168 *
169 * @param in
170 * an array containing the data bytes to be encoded.
171 * @param iLen
172 * number of bytes to process in <code>in</code>.
173 * @return A character array with the Base64 encoded data.
174 */
175 public static char[] encode(final byte[] in, final int iLen) {
176 // output length without padding
177 final int oDataLen = (iLen * 4 + 2) / 3;
178 // output length including padding
179 final int oLen = ((iLen + 2) / 3) * 4;
180 final char[] out = new char[oLen];
181 int ip = 0;
182 int op = 0;
183 while (ip < iLen) {
184 final int i0 = in[ip] & 0xff;
185 ip += 1;
186 final int i1 = (ip < iLen) ? in[ip] & 0xff : 0;
187 ip += 1;
188 final int i2 = (ip < iLen) ? in[ip] & 0xff : 0;
189 ip += 1;
190 final int o0 = i0 >>> 2;
191 final int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
192 final int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
193 final int o3 = i2 & 0x3F;
194 out[op] = Base64.map1[o0];
195 op += 1;
196 out[op] = Base64.map1[o1];
197 ip += 1;
198 out[op] = (op < oDataLen) ? Base64.map1[o2] : '=';
199 op += 1;
200 out[op] = (op < oDataLen) ? Base64.map1[o3] : '=';
201 op += 1;
202 }
203 return out;
204 }
205
206 /**
207 * Encodes a string into Base64 format. No blanks or line breaks are
208 * inserted.
209 *
210 * @param s
211 * a String to be encoded.
212 * @return A String with the Base64 encoded data.
213 */
214 public static String encodeString(final String s) {
215 return new String(Base64.encode(s.getBytes()));
216 }
217
218 /**
219 * Default constructor.
220 */
221 private Base64() {
222 // Nothing.
223 }
224 }