/* * Base64.java * * Brazil project web application toolkit, * export version: 2.3 * Copyright (c) 2000-2008 Sun Microsystems, Inc. * * Sun Public License Notice * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is included as the file "license.terms", * and also available at http://www.sun.com/ * * The Original Code is from: * Brazil project web application toolkit release 2.3. * The Initial Developer of the Original Code is: cstevens. * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): cstevens, suhler. * * Version: 2.4 * Created by cstevens on 00/04/17 * Last modified by suhler on 08/03/04 10:57:37 * * Version Histories: * * 2.4 08/03/04-10:57:37 (suhler) * StringMap.java * * 2.3 04/11/30-15:19:45 (suhler) * fixed sccs version string * * 2.2 03/08/01-16:17:06 (suhler) * fixes for javadoc * * 2.1 02/10/01-16:37:01 (suhler) * version change * * 1.9 02/07/24-10:49:48 (suhler) * doc updates * * 1.8 01/08/20-20:39:44 (suhler) * oops * * 1.7 01/08/20-17:30:25 (suhler) * can now encode partial byte arrays * * 1.6 01/08/01-11:07:34 (suhler) * added encode(byte[]) * * 1.5 01/01/07-19:07:58 (suhler) * added a simple decoder, useful for un-encoding basic authentication * credentials * * 1.4 00/10/31-10:20:41 (suhler) * doc fixes * * 1.3 00/05/31-13:52:53 (suhler) * docs * * 1.2 00/04/20-13:14:23 (cstevens) * copyright * * 1.2 00/04/17-16:41:48 (Codemgr) * SunPro Code Manager data about conflicts, renames, etc... * Name history : 1 0 util/Base64.java * * 1.1 00/04/17-16:41:47 (cstevens) * date and time created 00/04/17 16:41:47 by cstevens * */ package sunlabs.brazil.util; /** * Utility to base64 encode and decode a string. * @author Stephen Uhler * @version %I% */ public class Base64 { static byte[] encodeData; static String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static { encodeData = new byte[64]; for (int i = 0; i<64; i++) { byte c = (byte) charSet.charAt(i); encodeData[i] = c; } } private Base64() {} /** * base-64 encode a string * @param s The ascii string to encode * @return The base64 encoded result */ public static String encode(String s) { return encode(s.getBytes()); } /** * base-64 encode a byte array * @param src The byte array to encode * @return The base64 encoded result */ public static String encode(byte[] src) { return encode(src, 0, src.length); } /** * base-64 encode a byte array * @param src The byte array to encode * @param start The starting index * @param length The number of bytes * @return The base64 encoded result */ public static String encode(byte[] src, int start, int length) { byte[] dst = new byte[(length+2)/3 * 4 + length/54]; int x = 0; int dstIndex = 0; int state = 0; // which char in pattern int old = 0; // previous byte int len = 0; // length decoded so far int max = length + start; for (int srcIndex = start; srcIndex<max; srcIndex++) { x = src[srcIndex]; switch (++state) { case 1: dst[dstIndex++] = encodeData[(x>>2) & 0x3f]; break; case 2: dst[dstIndex++] = encodeData[((old<<4)&0x30) | ((x>>4)&0xf)]; break; case 3: dst[dstIndex++] = encodeData[((old<<2)&0x3C) | ((x>>6)&0x3)]; dst[dstIndex++] = encodeData[x&0x3F]; state = 0; break; } old = x; if (++len >= 54) { dst[dstIndex++] = (byte) '\n'; len = 0; } } /* * now clean up the end bytes */ switch (state) { case 1: dst[dstIndex++] = encodeData[(old<<4) & 0x30]; dst[dstIndex++] = (byte) '='; dst[dstIndex++] = (byte) '='; break; case 2: dst[dstIndex++] = encodeData[(old<<2) & 0x3c]; dst[dstIndex++] = (byte) '='; break; } return new String(dst); } /** * A Base64 decoder. This implementation is slow, and * doesn't handle wrapped lines. * The output is undefined if there are errors in the input. * @param s a Base64 encoded string * @return The byte array eith the decoded result */ public static byte[] decode(String s) { int end = 0; // end state if (s.endsWith("=")) { end++; } if (s.endsWith("==")) { end++; } int len = (s.length() + 3)/4 * 3 - end; byte[] result = new byte[len]; int dst = 0; try { for(int src = 0; src< s.length(); src++) { int code = charSet.indexOf(s.charAt(src)); if (code == -1) { break; } switch (src%4) { case 0: result[dst] = (byte) (code<<2); break; case 1: result[dst++] |= (byte) ((code>>4) & 0x3); result[dst] = (byte) (code<<4); break; case 2: result[dst++] |= (byte) ((code>>2) & 0xf); result[dst] = (byte) (code<<6); break; case 3: result[dst++] |= (byte) (code & 0x3f); break; } } } catch (ArrayIndexOutOfBoundsException e) {} return result; } /** * Test the decoder and encoder. * Call as <code>Base64 [string]</code>. */ public static void main(String[] args) { System.out.println("encode: " + args[0] + " -> (" + encode(args[0]) + ")"); System.out.println("decode: " + args[0] + " -> (" + new String(decode(args[0])) + ")"); } }