1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package dk.sosi.seal.xml;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 @Deprecated
47 public final class Base64 {
48
49 static private final int BASELENGTH = 128;
50
51 static private final int LOOKUPLENGTH = 64;
52
53 static private final int TWENTYFOURBITGROUP = 24;
54
55 static private final int EIGHTBIT = 8;
56
57 static private final int SIXTEENBIT = 16;
58
59 static private final int FOURBYTE = 4;
60
61 static private final int SIGN = -128;
62
63 static private final char PAD = '=';
64
65 static final private byte[] base64Alphabet = new byte[BASELENGTH];
66
67 static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
68
69 static {
70
71 for (int i = 0; i < BASELENGTH; ++i) {
72 base64Alphabet[i] = -1;
73 }
74 for (int i = 'Z'; i >= 'A'; i--) {
75 base64Alphabet[i] = (byte) (i - 'A');
76 }
77 for (int i = 'z'; i >= 'a'; i--) {
78 base64Alphabet[i] = (byte) (i - 'a' + 26);
79 }
80
81 for (int i = '9'; i >= '0'; i--) {
82 base64Alphabet[i] = (byte) (i - '0' + 52);
83 }
84
85 base64Alphabet['+'] = 62;
86 base64Alphabet['/'] = 63;
87
88 for (int i = 0; i <= 25; i++)
89 lookUpBase64Alphabet[i] = (char) ('A' + i);
90
91 for (int i = 26, j = 0; i <= 51; i++, j++)
92 lookUpBase64Alphabet[i] = (char) ('a' + j);
93
94 for (int i = 52, j = 0; i <= 61; i++, j++)
95 lookUpBase64Alphabet[i] = (char) ('0' + j);
96 lookUpBase64Alphabet[62] = '+';
97 lookUpBase64Alphabet[63] = '/';
98
99 }
100
101 private static boolean isWhiteSpace(char octect) {
102 return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
103 }
104
105 private static boolean isPad(char octect) {
106 return (octect == PAD);
107 }
108
109 private static boolean isData(char octect) {
110 return (octect < BASELENGTH && base64Alphabet[octect] != -1);
111 }
112
113
114
115
116
117
118
119
120 public static String encode(byte[] binaryData) {
121 if (binaryData == null || binaryData.length == 0)
122 return null;
123
124 int lengthDataBits = binaryData.length * EIGHTBIT;
125 int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
126 int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
127 int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
128 : numberTriplets;
129 char encodedData[] = null;
130
131 encodedData = new char[numberQuartet * 4];
132
133 byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
134
135 int encodedIndex = 0;
136 int dataIndex = 0;
137
138 for (int i = 0; i < numberTriplets; i++) {
139 b1 = binaryData[dataIndex++];
140 b2 = binaryData[dataIndex++];
141 b3 = binaryData[dataIndex++];
142
143 l = (byte) (b2 & 0x0f);
144 k = (byte) (b1 & 0x03);
145
146 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
147 : (byte) ((b1) >> 2 ^ 0xc0);
148
149 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
150 : (byte) ((b2) >> 4 ^ 0xf0);
151 byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
152 : (byte) ((b3) >> 6 ^ 0xfc);
153
154 encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
155 encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
156 encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
157 encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
158 }
159
160
161 if (fewerThan24bits == EIGHTBIT) {
162 b1 = binaryData[dataIndex];
163 k = (byte) (b1 & 0x03);
164 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
165 : (byte) ((b1) >> 2 ^ 0xc0);
166 encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
167 encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
168 encodedData[encodedIndex++] = PAD;
169 encodedData[encodedIndex++] = PAD;
170 } else if (fewerThan24bits == SIXTEENBIT) {
171 b1 = binaryData[dataIndex];
172 b2 = binaryData[dataIndex + 1];
173 l = (byte) (b2 & 0x0f);
174 k = (byte) (b1 & 0x03);
175
176 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
177 : (byte) ((b1) >> 2 ^ 0xc0);
178 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
179 : (byte) ((b2) >> 4 ^ 0xf0);
180
181 encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
182 encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
183 encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
184 encodedData[encodedIndex++] = PAD;
185 }
186
187 return new String(encodedData);
188 }
189
190
191
192
193
194
195
196
197 public static byte[] decode(String encoded) {
198
199 if (encoded == null)
200 return null;
201
202 char[] base64Data = encoded.toCharArray();
203
204 int len = removeWhiteSpace(base64Data);
205
206 if (len % FOURBYTE != 0) {
207 return null;
208 }
209
210 int numberQuadruple = (len / FOURBYTE);
211
212 if (numberQuadruple == 0)
213 return new byte[0];
214
215 byte decodedData[] = null;
216 byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
217 char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
218
219 int i = 0;
220 int encodedIndex = 0;
221 int dataIndex = 0;
222 decodedData = new byte[(numberQuadruple) * 3];
223
224 for (; i < numberQuadruple - 1; i++) {
225
226 if (!isData((d1 = base64Data[dataIndex++]))
227 || !isData((d2 = base64Data[dataIndex++]))
228 || !isData((d3 = base64Data[dataIndex++]))
229 || !isData((d4 = base64Data[dataIndex++])))
230 return null;
231
232 b1 = base64Alphabet[d1];
233 b2 = base64Alphabet[d2];
234 b3 = base64Alphabet[d3];
235 b4 = base64Alphabet[d4];
236
237 decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
238 decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
239 decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
240 }
241
242 if (!isData((d1 = base64Data[dataIndex++]))
243 || !isData((d2 = base64Data[dataIndex++]))) {
244 return null;
245 }
246
247 b1 = base64Alphabet[d1];
248 b2 = base64Alphabet[d2];
249
250 d3 = base64Data[dataIndex++];
251 d4 = base64Data[dataIndex++];
252 if (!isData((d3)) || !isData((d4))) {
253
254 if (isPad(d3) && isPad(d4)) {
255 if ((b2 & 0xf) != 0)
256 return null;
257 byte[] tmp = new byte[i * 3 + 1];
258 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
259 tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
260 return tmp;
261 } else if (!isPad(d3) && isPad(d4)) {
262 b3 = base64Alphabet[d3];
263 if ((b3 & 0x3) != 0)
264 return null;
265 byte[] tmp = new byte[i * 3 + 2];
266 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
267 tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
268 tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
269 return tmp;
270 } else {
271 return null;
272
273 }
274 }
275
276
277 b3 = base64Alphabet[d3];
278 b4 = base64Alphabet[d4];
279 decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
280 decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
281 decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
282
283 return decodedData;
284 }
285
286
287
288
289
290
291
292
293 private static int removeWhiteSpace(char[] data) {
294
295 int newSize = 0;
296 int len = data.length;
297 for (int i = 0; i < len; i++) {
298 if (!isWhiteSpace(data[i]))
299 data[newSize++] = data[i];
300 }
301 return newSize;
302 }
303 }