001: /*
002: * Copyright 1995-1998 by Sun Microsystems, Inc.,
003: * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
004: * All rights reserved.
005: *
006: * This software is the confidential and proprietary information
007: * of Sun Microsystems, Inc. ("Confidential Information"). You
008: * shall not disclose such Confidential Information and shall use
009: * it only in accordance with the terms of the license agreement
010: * you entered into with Sun.
011: */
012:
013: package com.sun.portal.desktop.util;
014:
015: /**
016: * This class encodes and decodes data to and from the Base64 format according
017: * to the specs in RFC 1521 (Section 5.2).
018: *
019: * @author Dan Crawford
020: */
021: public class Base64 {
022:
023: private static byte[] DecodeMap;
024: private static byte[] theMap = { (byte) 'A', (byte) 'B',
025: (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',
026: (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
027: (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q',
028: (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
029: (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
030: (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
031: (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k',
032: (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
033: (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',
034: (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',
035: (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',
036: (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',
037: (byte) '+', (byte) '/' };
038:
039: //the Base64 mapping
040:
041: static {
042: DecodeMap = new byte[128];
043: for (int i = 0; i < theMap.length; i++) {
044: DecodeMap[theMap[i]] = (byte) i;
045: }
046: }
047:
048: /**
049: * Convert the String into an array of bytes then send the bytes
050: * through the
051: * encoding algorithim. Return the encoded data as a String object.
052: *
053: * @param theData the data that is to be Base64 encoded.
054: * @return String the base64 encoded data as a String object.
055: */
056: public static String encode(String theData) {
057:
058: if (theData == null) {
059: return null;
060: }
061:
062: byte[] theBytes = theData.getBytes();
063: theData = new String(encode(theBytes));
064:
065: return theData;
066: }
067:
068: /**
069: * This is where the actual encoding takes place.
070: * returns a byte array of the encoded bytes.
071: *
072: * @param theBytes a byte array that is to be Base64 encoded.
073: * @return byte[] the Base64 encoded data.
074: */
075: public static byte[] encode(byte[] theBytes) {
076: int i = 0, place = (-1);
077: byte byte1, byte2, byte3;
078: byte[] encodedBytes = new byte[((theBytes.length + 2) / 3) * 4];
079:
080: while ((i + 2) < theBytes.length) {
081: byte1 = theBytes[i];
082: byte2 = theBytes[++i];
083: byte3 = theBytes[++i];
084:
085: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
086: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
087: + ((byte2 >>> 4) & 0xf)];
088: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
089: + ((byte3 >>> 6) & 0x3)];
090: encodedBytes[++place] = theMap[byte3 & 0x3F];
091: ++i;
092: }
093:
094: if ((theBytes.length - 1 - i) == 0) {
095: byte1 = theBytes[i];
096: byte2 = 0;
097: byte3 = 0;
098:
099: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
100: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
101: + ((byte2 >>> 4) & 0xf)];
102: encodedBytes[++place] = (byte) '=';
103: encodedBytes[++place] = (byte) '=';
104: } else if ((theBytes.length - 1 - i) == 1) {
105: byte1 = theBytes[i];
106: byte2 = theBytes[i + 1];
107: byte3 = 0;
108:
109: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
110: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
111: + ((byte2 >>> 4) & 0xf)];
112: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
113: + ((byte3 >>> 6) & 0x3)];
114: encodedBytes[++place] = (byte) '=';
115: }
116:
117: //add padding if necessary;
118: while ((++place) < encodedBytes.length) {
119: encodedBytes[place] = (byte) '=';
120: }
121:
122: return encodedBytes;
123: }
124:
125: /**
126: * This is where the base 64 decoding is done.
127: *
128: * @param encData the Base64 encoded data that is to be decoded.
129: * @return byte[] the decoded data.
130: */
131: public static byte[] decode(byte[] encData) {
132: if (encData == null) {
133: return null;
134: }
135: if (encData.length == 0) {
136: return new byte[0];
137: }
138:
139: int tail = encData.length;
140: while (encData[tail - 1] == '=') {
141: tail--;
142: }
143:
144: byte decData[] = new byte[tail - encData.length / 4];
145:
146: // ascii printable to 0-63 conversion
147: for (int idx = 0; idx < encData.length; idx++) {
148: encData[idx] = DecodeMap[encData[idx]];
149: }
150:
151: // 4-byte to 3-byte conversion
152: int sidx, didx;
153: for (sidx = 0, didx = 0; didx < decData.length - 2; sidx += 4, didx += 3) {
154: decData[didx] = (byte) (((encData[sidx] << 2) & 255) | ((encData[sidx + 1] >>> 4) & 003));
155: decData[didx + 1] = (byte) (((encData[sidx + 1] << 4) & 255) | ((encData[sidx + 2] >>> 2) & 017));
156: decData[didx + 2] = (byte) (((encData[sidx + 2] << 6) & 255) | (encData[sidx + 3] & 077));
157:
158: }
159:
160: if (didx < decData.length) {
161: decData[didx] = (byte) (((encData[sidx] << 2) & 255) | ((encData[sidx + 1] >>> 4) & 003));
162: }
163: if (++didx < decData.length) {
164: decData[didx] = (byte) (((encData[sidx + 1] << 4) & 255) | ((encData[sidx + 2] >>> 2) & 017));
165: }
166:
167: return decData;
168: }
169: }
|