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