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 migration.modules.srap.ldap;
015:
016: import java.io.*;
017: import java.util.*;
018: import java.text.*;
019:
020: /**
021: *
022: * This class encodes and decodes data to and from the Base64 format according
023: * to the specs in RFC 1521 (Section 5.2).
024: *
025: * @author Dan Crawford
026: */
027: public class Base64 {
028:
029: private static byte[] DecodeMap;
030: private static byte[] theMap = { (byte) 'A', (byte) 'B',
031: (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G',
032: (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
033: (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q',
034: (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
035: (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
036: (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
037: (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k',
038: (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
039: (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u',
040: (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z',
041: (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4',
042: (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9',
043: (byte) '+', (byte) '/' };
044:
045: //the Base64 mapping
046:
047: static {
048: DecodeMap = new byte[128];
049: for (int i = 0; i < theMap.length; i++)
050: DecodeMap[theMap[i]] = (byte) i;
051: }
052:
053: /**
054: * Convert the String into an array of bytes then send the bytes
055: through the
056: * encoding algorithim. Return the encoded data as a String object.
057: *
058: * @param theData the data that is to be Base64 encoded.
059: * @return String the base64 encoded data as a String object.
060: */
061: public static String encode(String theData) {
062:
063: if (theData == null)
064: return null;
065:
066: byte[] 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.
074: * returns a byte array of the encoded bytes.
075: *
076: * @param theBytes a byte array that is to be Base64 encoded.
077: * @return byte[] the Base64 encoded data.
078: */
079: public static byte[] encode(byte[] theBytes) {
080: int i = 0, place = (-1);
081: byte byte1, byte2, byte3;
082: byte[] encodedBytes = new byte[((theBytes.length + 2) / 3) * 4];
083:
084: while ((i + 2) < theBytes.length) {
085: byte1 = theBytes[i];
086: byte2 = theBytes[++i];
087: byte3 = theBytes[++i];
088:
089: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
090: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
091: + ((byte2 >>> 4) & 0xf)];
092: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
093: + ((byte3 >>> 6) & 0x3)];
094: encodedBytes[++place] = theMap[byte3 & 0x3F];
095: ++i;
096: }
097:
098: if ((theBytes.length - 1 - i) == 0) {
099: byte1 = theBytes[i];
100: byte2 = 0;
101: byte3 = 0;
102:
103: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
104: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
105: + ((byte2 >>> 4) & 0xf)];
106: encodedBytes[++place] = (byte) '=';
107: encodedBytes[++place] = (byte) '=';
108: }
109:
110: else if ((theBytes.length - 1 - i) == 1) {
111: byte1 = theBytes[i];
112: byte2 = theBytes[i + 1];
113: byte3 = 0;
114:
115: encodedBytes[++place] = theMap[(byte1 >>> 2) & 0x3F];
116: encodedBytes[++place] = theMap[((byte1 << 4) & 0x30)
117: + ((byte2 >>> 4) & 0xf)];
118: encodedBytes[++place] = theMap[((byte2 << 2) & 0x3c)
119: + ((byte3 >>> 6) & 0x3)];
120: encodedBytes[++place] = (byte) '=';
121: }
122:
123: //add padding if necessary;
124: while ((++place) < encodedBytes.length) {
125: encodedBytes[place] = (byte) '=';
126: }
127:
128: return encodedBytes;
129: }
130:
131: /**
132: * This is where the base 64 decoding is done.
133: *
134: * @param encData 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: }
|