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.rproxy.connectionhandler;
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: byte[] theBytes = theData.getBytes();
064: theData = new String(encode(theBytes));
065:
066: return theData;
067: }
068:
069: /**
070: * This is where the actual encoding takes place. returns a byte array of
071: * the encoded bytes.
072: *
073: * @param theBytes
074: * a byte array that is to be Base64 encoded.
075: * @return byte[] the Base64 encoded data.
076: */
077: public static byte[] encode(byte[] theBytes) {
078: int i = 0, place = (-1);
079: byte byte1, byte2, byte3;
080: byte[] encodedBytes = new byte[((theBytes.length + 2) / 3) * 4];
081:
082: while ((i + 2) < theBytes.length) {
083: byte1 = theBytes[i];
084: byte2 = theBytes[++i];
085: byte3 = theBytes[++i];
086:
087: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
088: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
089: + ((byte2 >>> 4) & 0xf)];
090: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
091: + ((byte3 >>> 6) & 0x3)];
092: encodedBytes[++place] = theMap[byte3 & 0x3F];
093: ++i;
094: }
095:
096: if ((theBytes.length - 1 - i) == 0) {
097: byte1 = theBytes[i];
098: byte2 = 0;
099: byte3 = 0;
100:
101: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
102: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
103: + ((byte2 >>> 4) & 0xf)];
104: encodedBytes[++place] = (byte) '=';
105: encodedBytes[++place] = (byte) '=';
106: }
107:
108: else if ((theBytes.length - 1 - i) == 1) {
109: byte1 = theBytes[i];
110: byte2 = theBytes[i + 1];
111: byte3 = 0;
112:
113: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
114: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
115: + ((byte2 >>> 4) & 0xf)];
116: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
117: + ((byte3 >>> 6) & 0x3)];
118: encodedBytes[++place] = (byte) '=';
119: }
120:
121: // add padding if necessary;
122: while ((++place) < encodedBytes.length) {
123: encodedBytes[place] = (byte) '=';
124: }
125:
126: return encodedBytes;
127: }
128:
129: /**
130: * This is where the base 64 decoding is done.
131: *
132: * @param encData
133: * the Base64 encoded data that is to be decoded.
134: * @return byte[] the decoded data.
135: */
136: public static byte[] decode(byte[] encData) {
137: if (encData == null)
138: return null;
139:
140: int tail = encData.length;
141: while (encData[tail - 1] == '=')
142: tail--;
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: if (++didx < decData.length)
163: decData[didx] = (byte) (((encData[sidx + 1] << 4) & 255) | ((encData[sidx + 2] >>> 2) & 017));
164:
165: return decData;
166: }
167: }
|