001: package com.sun.syndication.io.impl;
002:
003: /*
004: * Copyright 2004 Sun Microsystems, Inc.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: */
019:
020: /**
021: * Encodes/decodes byte arrays and Strings into/from a base 64 String.
022: * <p>
023: * @author Alejandro Abdelnur
024: *
025: */
026: public class Base64 {
027:
028: /**
029: * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
030: * <p>
031: * @param s String to encode.
032: * @return encoded string.
033: *
034: */
035: public static String encode(String s) {
036: byte[] sBytes = s.getBytes();
037: sBytes = encode(sBytes);
038: s = new String(sBytes);
039: return s;
040: }
041:
042: /**
043: * Decodes a base 64 String into a String.
044: * <p>
045: * @param s String to decode.
046: * @return encoded string.
047: * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
048: *
049: */
050: public static String decode(String s)
051: throws IllegalArgumentException {
052: byte[] sBytes = s.getBytes();
053: sBytes = decode(sBytes);
054: s = new String(sBytes);
055: return s;
056: }
057:
058: private static final byte[] ALPHASET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
059: .getBytes();
060:
061: private static final int I6O2 = 255 - 3;
062: private static final int O6I2 = 3;
063: private static final int I4O4 = 255 - 15;
064: private static final int O4I4 = 15;
065: private static final int I2O6 = 255 - 63;
066: private static final int O2I6 = 63;
067:
068: /**
069: * Encodes a byte array into a base 64 byte array.
070: * <p>
071: * @param dData byte array to encode.
072: * @return encoded byte array.
073: *
074: */
075: public static byte[] encode(byte[] dData) {
076: if (dData == null) {
077: throw new IllegalArgumentException("Cannot encode null");
078: }
079: byte[] eData = new byte[((dData.length + 2) / 3) * 4];
080:
081: int eIndex = 0;
082: for (int i = 0; i < dData.length; i += 3) {
083: int d1;
084: int d2 = 0;
085: int d3 = 0;
086: int e1;
087: int e2;
088: int e3;
089: int e4;
090: int pad = 0;
091:
092: d1 = dData[i];
093: if ((i + 1) < dData.length) {
094: d2 = dData[i + 1];
095: if ((i + 2) < dData.length) {
096: d3 = dData[i + 2];
097: } else {
098: pad = 1;
099: }
100: } else {
101: pad = 2;
102: }
103:
104: e1 = ALPHASET[(d1 & I6O2) >> 2];
105: e2 = ALPHASET[(d1 & O6I2) << 4 | (d2 & I4O4) >> 4];
106: e3 = ALPHASET[(d2 & O4I4) << 2 | (d3 & I2O6) >> 6];
107: e4 = ALPHASET[(d3 & O2I6)];
108:
109: eData[eIndex++] = (byte) e1;
110: eData[eIndex++] = (byte) e2;
111: eData[eIndex++] = (pad < 2) ? (byte) e3 : (byte) '=';
112: eData[eIndex++] = (pad < 1) ? (byte) e4 : (byte) '=';
113:
114: }
115: return eData;
116: }
117:
118: private final static int[] CODES = new int[256];
119:
120: static {
121: for (int i = 0; i < CODES.length; i++) {
122: CODES[i] = 64;
123: }
124: for (int i = 0; i < ALPHASET.length; i++) {
125: CODES[ALPHASET[i]] = i;
126: }
127: }
128:
129: /**
130: * Dencodes a com.sun.syndication.io.impl.Base64 byte array.
131: * <p>
132: * @param eData byte array to decode.
133: * @return decoded byte array.
134: * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
135: *
136: */
137: public static byte[] decode(byte[] eData) {
138: if (eData == null) {
139: throw new IllegalArgumentException("Cannot decode null");
140: }
141: byte[] cleanEData = (byte[]) eData.clone();
142: int cleanELength = 0;
143: for (int i = 0; i < eData.length; i++) {
144: if (eData[i] < 256 && CODES[eData[i]] < 64) {
145: cleanEData[cleanELength++] = eData[i];
146: }
147: }
148:
149: int dLength = (cleanELength / 4) * 3;
150: switch (cleanELength % 4) {
151: case 3:
152: dLength += 2;
153: break;
154: case 2:
155: dLength++;
156: break;
157: }
158:
159: byte[] dData = new byte[dLength];
160: int dIndex = 0;
161: for (int i = 0; i < cleanELength; i += 4) {
162: if ((i + 3) > cleanELength) {
163: throw new IllegalArgumentException(
164: "byte array is not a valid com.sun.syndication.io.impl.Base64 encoding");
165: }
166: int e1 = CODES[cleanEData[i]];
167: int e2 = CODES[cleanEData[i + 1]];
168: int e3 = CODES[cleanEData[i + 2]];
169: int e4 = CODES[cleanEData[i + 3]];
170: dData[dIndex++] = (byte) ((e1 << 2) | (e2 >> 4));
171: if (dIndex < dData.length) {
172: dData[dIndex++] = (byte) ((e2 << 4) | (e3 >> 2));
173: }
174: if (dIndex < dData.length) {
175: dData[dIndex++] = (byte) ((e3 << 6) | (e4));
176: }
177: }
178: return dData;
179: }
180:
181: public static void main(String[] args) throws Exception {
182: String s = "\nPGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+V2UncmUgcHJvcG9zaW5nIDxhIGhy\n"
183: + "ZWY9Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbS9jb3Jwb3JhdGUvc29mdHdhcmVfcHJpbmNpcGxlcy5odG1sIj5z\n"
184: + "b21lIGd1aWRlbGluZXMgPC9hPnRvIGhlbHAgY3VyYiB0aGUgcHJvYmxlbSBvZiBJbnRlcm5ldCBzb2Z0d2Fy\n"
185: + "ZSB0aGF0IGluc3RhbGxzIGl0c2VsZiB3aXRob3V0IHRlbGxpbmcgeW91LCBvciBiZWhhdmVzIGJhZGx5IG9u\n"
186: + "Y2UgaXQgZ2V0cyBvbiB5b3VyIGNvbXB1dGVyLiBXZSd2ZSBiZWVuIGhlYXJpbmcgYSBsb3Qgb2YgY29tcGxh\n"
187: + "aW50cyBhYm91dCB0aGlzIGxhdGVseSBhbmQgaXQgc2VlbXMgdG8gYmUgZ2V0dGluZyB3b3JzZS4gV2UgdGhp\n"
188: + "bmsgaXQncyBpbXBvcnRhbnQgdGhhdCB5b3UgcmV0YWluIGNvbnRyb2wgb2YgeW91ciBjb21wdXRlciBhbmQg\n"
189: + "dGhhdCB0aGVyZSBiZSBzb21lIGNsZWFyIHN0YW5kYXJkcyBpbiBvdXIgaW5kdXN0cnkuIExldCB1cyBrbm93\n"
190: + "IGlmIHlvdSB0aGluayB0aGVzZSBndWlkZWxpbmVzIGFyZSB1c2VmdWwgb3IgaWYgeW91IGhhdmUgc3VnZ2Vz\n"
191: + "dGlvbnMgdG8gaW1wcm92ZSB0aGVtLgo8YnIgLz4KPGJyIC8+Sm9uYXRoYW4gUm9zZW5iZXJnCjxiciAvPgo8\n"
192: + "L2Rpdj4K\n";
193:
194: System.out.println(decode(s));
195: }
196: }
|