1 package com.sun.syndication.io.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import java.io.UnsupportedEncodingException;
21
22 /***
23 * Encodes/decodes byte arrays and Strings into/from a base 64 String.
24 * <p>
25 * @author Alejandro Abdelnur
26 *
27 */
28 public class Base64 {
29
30 /***
31 * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
32 * <p>
33 * @param s String to encode.
34 * @return encoded string.
35 *
36 */
37 public static String encode(String s) {
38 byte[] sBytes = s.getBytes();
39 sBytes = encode(sBytes);
40 s = new String(sBytes);
41 return s;
42 }
43
44 /***
45 * Decodes a base 64 String into a String.
46 * <p>
47 * @param s String to decode.
48 * @return encoded string.
49 * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
50 *
51 */
52 public static String decode(String s) throws IllegalArgumentException {
53 byte[] sBytes = s.getBytes();
54 sBytes = decode(sBytes);
55 s = new String(sBytes);
56 return s;
57 }
58
59
60 private static final byte[] ALPHASET =
61 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".getBytes();
62
63 private static final int I6O2 = 255 - 3;
64 private static final int O6I2 = 3;
65 private static final int I4O4 = 255 - 15;
66 private static final int O4I4 = 15;
67 private static final int I2O6 = 255 - 63;
68 private static final int O2I6 = 63;
69
70 /***
71 * Encodes a byte array into a base 64 byte array.
72 * <p>
73 * @param dData byte array to encode.
74 * @return encoded byte array.
75 *
76 */
77 public static byte[] encode(byte[] dData) {
78 if (dData==null) {
79 throw new IllegalArgumentException("Cannot encode null");
80 }
81 byte[] eData = new byte[((dData.length+2)/3)*4];
82
83 int eIndex = 0;
84 for (int i = 0; i<dData.length; i += 3) {
85 int d1;
86 int d2=0;
87 int d3=0;
88 int e1;
89 int e2;
90 int e3;
91 int e4;
92 int pad=0;
93
94 d1 = dData[i];
95 if ((i+1)<dData.length) {
96 d2 = dData[i+1];
97 if ((i+2)<dData.length) {
98 d3 = dData[i+2];
99 }
100 else {
101 pad =1;
102 }
103 }
104 else {
105 pad =2;
106 }
107
108 e1 = ALPHASET[(d1&I6O2)>>2];
109 e2 = ALPHASET[(d1&O6I2)<<4 | (d2&I4O4)>>4];
110 e3 = ALPHASET[(d2&O4I4)<<2 | (d3&I2O6)>>6];
111 e4 = ALPHASET[(d3&O2I6)];
112
113 eData[eIndex++] = (byte)e1;
114 eData[eIndex++] = (byte)e2;
115 eData[eIndex++] = (pad<2) ?(byte)e3 : (byte)'=';
116 eData[eIndex++] = (pad<1) ?(byte)e4 : (byte)'=';
117
118 }
119 return eData;
120 }
121
122 private final static int[] CODES = new int[256];
123
124 static {
125 for (int i=0;i<CODES.length;i++) {
126 CODES[i] = 64;
127 }
128 for (int i=0;i<ALPHASET.length;i++) {
129 CODES[ALPHASET[i]] = i;
130 }
131 }
132
133 /***
134 * Dencodes a com.sun.syndication.io.impl.Base64 byte array.
135 * <p>
136 * @param eData byte array to decode.
137 * @return decoded byte array.
138 * @throws java.lang.IllegalArgumentException thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
139 *
140 */
141 public static byte[] decode(byte[] eData) {
142 if (eData==null) {
143 throw new IllegalArgumentException("Cannot decode null");
144 }
145 byte[] cleanEData = (byte[]) eData.clone();
146 int cleanELength = 0;
147 for (int i=0;i<eData.length;i++) {
148 if (eData[i]<256 && CODES[eData[i]]<64) {
149 cleanEData[cleanELength++] = eData[i];
150 }
151 }
152
153 int dLength = (cleanELength/4)*3;
154 switch (cleanELength%4) {
155 case 3:
156 dLength += 2;
157 break;
158 case 2:
159 dLength++;
160 break;
161 }
162
163 byte[] dData = new byte[dLength];
164 int dIndex = 0;
165 for (int i=0;i<cleanELength;i+=4) {
166 if ((i+3)>cleanELength) {
167 throw new IllegalArgumentException("byte array is not a valid com.sun.syndication.io.impl.Base64 encoding");
168 }
169 int e1 = CODES[cleanEData[i]];
170 int e2 = CODES[cleanEData[i+1]];
171 int e3 = CODES[cleanEData[i+2]];
172 int e4 = CODES[cleanEData[i+3]];
173 dData[dIndex++] = (byte) ((e1<<2)|(e2>>4));
174 if (dIndex<dData.length) {
175 dData[dIndex++] = (byte) ((e2<<4) | (e3>>2));
176 }
177 if (dIndex<dData.length) {
178 dData[dIndex++] = (byte) ((e3<<6) | (e4));
179 }
180 }
181 return dData;
182 }
183
184 public static void main(String[] args) throws Exception {
185 String s =
186 "\nPGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCI+V2UncmUgcHJvcG9zaW5nIDxhIGhy\n"+
187 "ZWY9Imh0dHA6Ly93d3cuZ29vZ2xlLmNvbS9jb3Jwb3JhdGUvc29mdHdhcmVfcHJpbmNpcGxlcy5odG1sIj5z\n"+
188 "b21lIGd1aWRlbGluZXMgPC9hPnRvIGhlbHAgY3VyYiB0aGUgcHJvYmxlbSBvZiBJbnRlcm5ldCBzb2Z0d2Fy\n"+
189 "ZSB0aGF0IGluc3RhbGxzIGl0c2VsZiB3aXRob3V0IHRlbGxpbmcgeW91LCBvciBiZWhhdmVzIGJhZGx5IG9u\n"+
190 "Y2UgaXQgZ2V0cyBvbiB5b3VyIGNvbXB1dGVyLiBXZSd2ZSBiZWVuIGhlYXJpbmcgYSBsb3Qgb2YgY29tcGxh\n"+
191 "aW50cyBhYm91dCB0aGlzIGxhdGVseSBhbmQgaXQgc2VlbXMgdG8gYmUgZ2V0dGluZyB3b3JzZS4gV2UgdGhp\n"+
192 "bmsgaXQncyBpbXBvcnRhbnQgdGhhdCB5b3UgcmV0YWluIGNvbnRyb2wgb2YgeW91ciBjb21wdXRlciBhbmQg\n"+
193 "dGhhdCB0aGVyZSBiZSBzb21lIGNsZWFyIHN0YW5kYXJkcyBpbiBvdXIgaW5kdXN0cnkuIExldCB1cyBrbm93\n"+
194 "IGlmIHlvdSB0aGluayB0aGVzZSBndWlkZWxpbmVzIGFyZSB1c2VmdWwgb3IgaWYgeW91IGhhdmUgc3VnZ2Vz\n"+
195 "dGlvbnMgdG8gaW1wcm92ZSB0aGVtLgo8YnIgLz4KPGJyIC8+Sm9uYXRoYW4gUm9zZW5iZXJnCjxiciAvPgo8\n"+
196 "L2Rpdj4K\n";
197
198 System.out.println(decode(s));
199 }
200 }
201