1 /* Base64.java -- Base64 encoding and decoding.
2 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
4 This file is a part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version.
39 Base64 encoding derived from ISC's DHCP. Copyright notices from DHCP
40 follow. See http://www.isc.org/products/DHCP/.
42 Copyright (c) 1996 by Internet Software Consortium.
44 Permission to use, copy, modify, and distribute this software for any
45 purpose with or without fee is hereby granted, provided that the above
46 copyright notice and this permission notice appear in all copies.
48 THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
49 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
50 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
51 INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
52 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
53 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
54 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
55 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
58 Portions Copyright (c) 1995 by International Business Machines, Inc.
60 International Business Machines, Inc. (hereinafter called IBM) grants
61 permission under its copyrights to use, copy, modify, and distribute
62 this Software with or without fee, provided that the above copyright
63 notice and all paragraphs of this notice appear in all copies, and
64 that the name of IBM not be used in connection with the marketing of
65 any product incorporating the Software or modifications thereof,
66 without specific, written prior permission.
68 To the extent it has a right to do so, IBM grants an immunity from
69 suit under its patents, if any, for the use, sale or manufacture of
70 products to the extent that such products are used for performing
71 Domain Name System dynamic updates in TCP/IP networks by means of the
72 Software. No immunity is granted for any product per se or for any
73 other function of any product.
75 THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
76 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
77 PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
78 DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
79 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
80 SOFTWARE, EVEN IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH
84 package gnu.java.util;
86 import gnu.java.lang.CPStringBuilder;
88 import java.io.ByteArrayOutputStream;
89 import java.io.IOException;
91 public final class Base64
98 // -------------------------------------------------------------------------
100 /** Base-64 characters. */
101 private static final String BASE_64 =
102 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
104 /** Base-64 padding character. */
105 private static final char BASE_64_PAD = '=';
108 * Base64 encode a byte array, with no line wrapping.
110 * @param buf The byte array to encode.
111 * @return <tt>buf</tt> encoded in Base64.
113 public static String encode(byte[] buf)
115 return encode(buf, 0);
119 * Base64 encode a byte array, returning the returning string.
121 * @param buf The byte array to encode.
122 * @param tw The total length of any line, 0 for unlimited.
123 * @return <tt>buf</tt> encoded in Base64.
125 public static String encode(byte[] buf, int tw)
127 return encode(buf, 0, buf.length, tw);
131 * Base64 encode a byte array, returning the returning string.
133 * @param buf The byte array to encode.
134 * @param offset The offset in the byte array to start.
135 * @param length The number of bytes to encode.
136 * @param tw The total length of any line, 0 for unlimited.
137 * @return <tt>buf</tt> encoded in Base64.
139 public static String encode(byte[] buf, int offset, int length, int tw)
141 if (offset < 0 || length < 0 || offset + length > buf.length)
142 throw new ArrayIndexOutOfBoundsException(buf.length + " "
145 int srcLength = buf.length - offset;
146 byte[] input = new byte[3];
147 int[] output = new int[4];
148 CPStringBuilder out = new CPStringBuilder();
152 while (srcLength > 2)
159 output[0] = (input[0] & 0xff) >>> 2;
160 output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4);
161 output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6);
162 output[3] = input[2] & 0x3f;
164 out.append(BASE_64.charAt(output[0]));
165 if (tw > 0 && ++chars % tw == 0)
169 out.append(BASE_64.charAt(output[1]));
170 if (tw > 0 && ++chars % tw == 0)
174 out.append(BASE_64.charAt(output[2]));
175 if (tw > 0 && ++chars % tw == 0)
179 out.append(BASE_64.charAt(output[3]));
180 if (tw > 0 && ++chars % tw == 0)
188 input[0] = input[1] = input[2] = 0;
189 for (int j = 0; j < srcLength; j++)
193 output[0] = (input[0] & 0xff) >>> 2;
194 output[1] = ((input[0] & 0x03) << 4) + ((input[1] & 0xff) >>> 4);
195 output[2] = ((input[1] & 0x0f) << 2) + ((input[2] & 0xff) >>> 6);
197 out.append(BASE_64.charAt(output[0]));
198 if (tw > 0 && ++chars % tw == 0)
202 out.append(BASE_64.charAt(output[1]));
203 if (tw > 0 && ++chars % tw == 0)
209 out.append(BASE_64_PAD);
213 out.append(BASE_64.charAt(output[2]));
215 if (tw > 0 && ++chars % tw == 0)
219 out.append(BASE_64_PAD);
220 if (tw > 0 && ++chars % tw == 0)
230 return out.toString();
234 * Decode a Base-64 string into a byte array.
236 * @param b64 The Base-64 encoded string.
237 * @return The decoded bytes.
238 * @throws java.io.IOException If the argument is not a valid Base-64
241 public static byte[] decode(String b64) throws IOException
243 ByteArrayOutputStream result = new ByteArrayOutputStream(b64.length() / 3);
247 for (i = 0; i < b64.length(); i++)
249 if (Character.isWhitespace(b64.charAt(i)))
253 if (b64.charAt(i) == BASE_64_PAD)
258 int pos = BASE_64.indexOf(b64.charAt(i));
261 throw new IOException("non-Base64 character " + b64.charAt(i));
266 temp = (byte) (pos - BASE_64.indexOf('A') << 2);
271 temp |= (byte) (pos - BASE_64.indexOf('A') >>> 4);
273 temp = (byte) ((pos - BASE_64.indexOf('A') & 0x0f) << 4);
278 temp |= (byte) ((pos - BASE_64.indexOf('A') & 0x7f) >>> 2);
280 temp = (byte) ((pos - BASE_64.indexOf('A') & 0x03) << 6);
285 temp |= (byte) (pos - BASE_64.indexOf('A') & 0xff);
291 throw new Error("this statement should be unreachable");
295 if (i < b64.length() && b64.charAt(i) == BASE_64_PAD)
301 throw new IOException("malformed Base64 sequence");
305 for ( ; i < b64.length(); i++)
307 if (!Character.isWhitespace(b64.charAt(i)))
312 // We must see a second pad character here.
313 if (b64.charAt(i) != BASE_64_PAD)
315 throw new IOException("malformed Base64 sequence");
322 for ( ; i < b64.length(); i++)
324 // We should only see whitespace after this.
325 if (!Character.isWhitespace(b64.charAt(i)))
327 throw new IOException("malformed Base64 sequence");
336 throw new IOException("malformed Base64 sequence");
340 return result.toByteArray();