001: /*
002: * Base64.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 2000-2001 Sun Microsystems, Inc.
007: *
008: * Sun Public License Notice
009: *
010: * The contents of this file are subject to the Sun Public License Version
011: * 1.0 (the "License"). You may not use this file except in compliance with
012: * the License. A copy of the License is included as the file "license.terms",
013: * and also available at http://www.sun.com/
014: *
015: * The Original Code is from:
016: * Brazil project web application Framework release 1.1.
017: * The Initial Developer of the Original Code is: cstevens.
018: * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc.
019: * All Rights Reserved.
020: *
021: * Contributor(s): cstevens, suhler.
022: *
023: * Version: 1.5
024: * Created by cstevens on 00/04/17
025: * Last modified by suhler on 01/01/07 19:07:58
026: */
027:
028: package sunlabs.brazil.util;
029:
030: /**
031: * Utility to base64 encode and decode a string.
032: * @author Stephen Uhler
033: * @version 1.5, 01/01/07
034: */
035:
036: public class Base64 {
037: static byte[] encodeData;
038: static String charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
039:
040: static {
041: encodeData = new byte[64];
042: for (int i = 0; i < 64; i++) {
043: byte c = (byte) charSet.charAt(i);
044: encodeData[i] = c;
045: }
046: }
047:
048: /**
049: * base-64 encode a string
050: * @param s The ascii string to encode
051: * @returns The base64 encoded result
052: */
053:
054: public static String encode(String s) {
055: byte[] src = s.getBytes();
056: byte[] dst = new byte[(src.length + 2) / 3 * 4 + src.length
057: / 72];
058: int x = 0;
059: int dstIndex = 0;
060: int state = 0; // which char in pattern
061: int old = 0; // previous byte
062: int len = 0; // length decoded so far
063: for (int srcIndex = 0; srcIndex < src.length; srcIndex++) {
064: x = src[srcIndex];
065: switch (++state) {
066: case 1:
067: dst[dstIndex++] = encodeData[(x >> 2) & 0x3f];
068: break;
069: case 2:
070: dst[dstIndex++] = encodeData[((old << 4) & 0x30)
071: | ((x >> 4) & 0xf)];
072: break;
073: case 3:
074: dst[dstIndex++] = encodeData[((old << 2) & 0x3C)
075: | ((x >> 6) & 0x3)];
076: dst[dstIndex++] = encodeData[x & 0x3F];
077: state = 0;
078: break;
079: }
080: old = x;
081: if (++len >= 72) {
082: dst[dstIndex++] = (byte) '\n';
083: len = 0;
084: }
085: }
086:
087: /*
088: * now clean up the end bytes
089: */
090:
091: switch (state) {
092: case 1:
093: dst[dstIndex++] = encodeData[(old << 4) & 0x30];
094: dst[dstIndex++] = (byte) '=';
095: dst[dstIndex++] = (byte) '=';
096: break;
097: case 2:
098: dst[dstIndex++] = encodeData[(old << 2) & 0x3c];
099: dst[dstIndex++] = (byte) '=';
100: break;
101: }
102: return new String(dst);
103: }
104:
105: /**
106: * A Base64 decoder. This implementation is slow, and
107: * doesn't handle wrapped lines.
108: * The output is undefined if there are errors in the input.
109: * @param s a Base64 encoded string
110: * @returns The byte array eith the decoded result
111: */
112:
113: public static byte[] decode(String s) {
114: int end = 0; // end state
115: if (s.endsWith("=")) {
116: end++;
117: }
118: if (s.endsWith("==")) {
119: end++;
120: }
121: int len = (s.length() + 3) / 4 * 3 - end;
122: byte[] result = new byte[len];
123: int dst = 0;
124: try {
125: for (int src = 0; src < s.length(); src++) {
126: int code = charSet.indexOf(s.charAt(src));
127: if (code == -1) {
128: break;
129: }
130: switch (src % 4) {
131: case 0:
132: result[dst] = (byte) (code << 2);
133: break;
134: case 1:
135: result[dst++] |= (byte) ((code >> 4) & 0x3);
136: result[dst] = (byte) (code << 4);
137: break;
138: case 2:
139: result[dst++] |= (byte) ((code >> 2) & 0xf);
140: result[dst] = (byte) (code << 6);
141: break;
142: case 3:
143: result[dst++] |= (byte) (code & 0x3f);
144: break;
145: }
146: }
147: } catch (ArrayIndexOutOfBoundsException e) {
148: }
149: return result;
150: }
151:
152: /**
153: * Test the decoder and encoder
154: */
155:
156: public static void main(String[] args) {
157: System.out.println("encode: " + args[0] + " -> ("
158: + encode(args[0]) + ")");
159: System.out.println("decode: " + args[0] + " -> ("
160: + new String(decode(args[0])) + ")");
161: }
162: }
|