|
1 | 1 | /**
|
2 | 2 | * Copyright Microsoft Corporation
|
3 |
| - * |
| 3 | + * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
6 | 6 | * You may obtain a copy of the License at
|
7 | 7 | * http://www.apache.org/licenses/LICENSE-2.0
|
8 |
| - * |
| 8 | + * |
9 | 9 | * Unless required by applicable law or agreed to in writing, software
|
10 | 10 | * distributed under the License is distributed on an "AS IS" BASIS,
|
11 | 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15 | 15 | package com.microsoft.windowsazure.core.utils;
|
16 | 16 |
|
17 | 17 | /**
|
18 |
| - * RESERVED FOR INTERNAL USE. Provides Base64 encoding, decoding, and validation |
19 |
| - * functionality. |
| 18 | + * Provides Base64 encoding, decoding, and validation functionality. |
20 | 19 | */
|
21 | 20 | public final class Base64 {
|
22 |
| - /** |
23 |
| - * The Base 64 Characters. |
24 |
| - */ |
25 |
| - private static final String BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
26 |
| - |
27 |
| - /** |
28 |
| - * Decoded values, -1 is invalid character, -2 is = pad character. |
29 |
| - */ |
30 |
| - private static final byte [] DECODE_64 = { |
31 |
| - -1, -1, -1, -1, -1, -1, -1, -1, |
32 |
| - -1, -1, -1, -1, -1, -1, -1, -1, // 0-15 |
33 |
| - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* |
34 |
| - * 16- |
35 |
| - * 31 |
36 |
| - */ |
37 |
| - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* |
38 |
| - * 32- |
39 |
| - * 47 |
40 |
| - */ |
41 |
| - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, /* |
42 |
| - * 48- |
43 |
| - * 63 |
44 |
| - */ |
45 |
| - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64-79 */ |
46 |
| - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* |
47 |
| - * 80- |
48 |
| - * 95 |
49 |
| - */ |
50 |
| - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* |
51 |
| - * 96- |
52 |
| - * 111 |
53 |
| - */ |
54 |
| - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* |
55 |
| - * 112- |
56 |
| - * 127 |
57 |
| - */ |
58 |
| - }; |
59 |
| - |
60 | 21 | /**
|
61 | 22 | * Decodes a given Base64 string into its corresponding byte array.
|
62 |
| - * |
| 23 | + * |
63 | 24 | * @param data
|
64 | 25 | * the Base64 string, as a <code>String</code> object, to decode
|
65 |
| - * |
| 26 | + * |
66 | 27 | * @return the corresponding decoded byte array
|
67 | 28 | * @throws IllegalArgumentException
|
68 | 29 | * If the string is not a valid base64 encoded string
|
69 | 30 | */
|
70 | 31 | public static byte[] decode(final String data) {
|
71 |
| - int byteArrayLength = 3 * data.length() / 4; |
72 |
| - |
73 |
| - if (data.endsWith("==")) { |
74 |
| - byteArrayLength -= 2; |
75 |
| - } else if (data.endsWith("=")) { |
76 |
| - byteArrayLength -= 1; |
77 |
| - } |
78 |
| - |
79 |
| - final byte[] retArray = new byte[byteArrayLength]; |
80 |
| - int byteDex = 0; |
81 |
| - int charDex = 0; |
82 |
| - |
83 |
| - for (; charDex < data.length(); charDex += 4) { |
84 |
| - // get 4 chars, convert to 3 bytes |
85 |
| - final int char1 = DECODE_64[(byte) data.charAt(charDex)]; |
86 |
| - final int char2 = DECODE_64[(byte) data.charAt(charDex + 1)]; |
87 |
| - final int char3 = DECODE_64[(byte) data.charAt(charDex + 2)]; |
88 |
| - final int char4 = DECODE_64[(byte) data.charAt(charDex + 3)]; |
89 |
| - |
90 |
| - if (char1 < 0 || char2 < 0 || char3 == -1 || char4 == -1) { |
91 |
| - // invalid character(-1), or bad padding (-2) |
92 |
| - throw new IllegalArgumentException( |
93 |
| - "The String is not a valid Base64-encoded string."); |
94 |
| - } |
95 |
| - |
96 |
| - int tVal = char1 << 18; |
97 |
| - tVal += char2 << 12; |
98 |
| - tVal += (char3 & 0xff) << 6; |
99 |
| - tVal += char4 & 0xff; |
100 |
| - |
101 |
| - if (char3 == -2) { |
102 |
| - // two "==" pad chars, check bits 12-24 |
103 |
| - tVal &= 0x00FFF000; |
104 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
105 |
| - } else if (char4 == -2) { |
106 |
| - // one pad char "=" , check bits 6-24. |
107 |
| - tVal &= 0x00FFFFC0; |
108 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
109 |
| - retArray[byteDex++] = (byte) (tVal >> 8 & 0xFF); |
110 |
| - |
111 |
| - } else { |
112 |
| - // No pads take all 3 bytes, bits 0-24 |
113 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
114 |
| - retArray[byteDex++] = (byte) (tVal >> 8 & 0xFF); |
115 |
| - retArray[byteDex++] = (byte) (tVal & 0xFF); |
116 |
| - } |
117 |
| - } |
118 |
| - return retArray; |
119 |
| - } |
120 |
| - |
121 |
| - /** |
122 |
| - * Decodes a given Base64 string into its corresponding byte array. |
123 |
| - * |
124 |
| - * @param data |
125 |
| - * the Base64 string, as a <code>String</code> object, to decode |
126 |
| - * |
127 |
| - * @return the corresponding decoded byte array |
128 |
| - * @throws IllegalArgumentException |
129 |
| - * If the string is not a valid base64 encoded string |
130 |
| - */ |
131 |
| - public static Byte[] decodeAsByteObjectArray(final String data) { |
132 |
| - int byteArrayLength = 3 * data.length() / 4; |
133 |
| - |
134 |
| - if (data.endsWith("==")) { |
135 |
| - byteArrayLength -= 2; |
136 |
| - } else if (data.endsWith("=")) { |
137 |
| - byteArrayLength -= 1; |
138 |
| - } |
139 |
| - |
140 |
| - final Byte[] retArray = new Byte[byteArrayLength]; |
141 |
| - int byteDex = 0; |
142 |
| - int charDex = 0; |
143 |
| - |
144 |
| - for (; charDex < data.length(); charDex += 4) { |
145 |
| - // get 4 chars, convert to 3 bytes |
146 |
| - final int char1 = DECODE_64[(byte) data.charAt(charDex)]; |
147 |
| - final int char2 = DECODE_64[(byte) data.charAt(charDex + 1)]; |
148 |
| - final int char3 = DECODE_64[(byte) data.charAt(charDex + 2)]; |
149 |
| - final int char4 = DECODE_64[(byte) data.charAt(charDex + 3)]; |
150 |
| - |
151 |
| - if (char1 < 0 || char2 < 0 || char3 == -1 || char4 == -1) { |
152 |
| - // invalid character(-1), or bad padding (-2) |
153 |
| - throw new IllegalArgumentException( |
154 |
| - "The String is not a valid Base64-encoded string."); |
155 |
| - } |
156 |
| - |
157 |
| - int tVal = char1 << 18; |
158 |
| - tVal += char2 << 12; |
159 |
| - tVal += (char3 & 0xff) << 6; |
160 |
| - tVal += char4 & 0xff; |
161 |
| - |
162 |
| - if (char3 == -2) { |
163 |
| - // two "==" pad chars, check bits 12-24 |
164 |
| - tVal &= 0x00FFF000; |
165 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
166 |
| - } else if (char4 == -2) { |
167 |
| - // one pad char "=" , check bits 6-24. |
168 |
| - tVal &= 0x00FFFFC0; |
169 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
170 |
| - retArray[byteDex++] = (byte) (tVal >> 8 & 0xFF); |
171 |
| - |
172 |
| - } else { |
173 |
| - // No pads take all 3 bytes, bits 0-24 |
174 |
| - retArray[byteDex++] = (byte) (tVal >> 16 & 0xFF); |
175 |
| - retArray[byteDex++] = (byte) (tVal >> 8 & 0xFF); |
176 |
| - retArray[byteDex++] = (byte) (tVal & 0xFF); |
177 |
| - } |
178 |
| - } |
179 |
| - return retArray; |
| 32 | + return org.apache.commons.codec.binary.Base64.decodeBase64(data); |
180 | 33 | }
|
181 | 34 |
|
182 | 35 | /**
|
183 | 36 | * Encodes a byte array as a Base64 string.
|
184 |
| - * |
| 37 | + * |
185 | 38 | * @param data
|
186 | 39 | * the byte array to encode
|
187 | 40 | * @return the Base64-encoded string, as a <code>String</code> object
|
188 | 41 | */
|
189 | 42 | public static String encode(final byte[] data) {
|
190 |
| - final StringBuilder builder = new StringBuilder(); |
191 |
| - final int dataRemainder = data.length % 3; |
192 |
| - |
193 |
| - int j = 0; |
194 |
| - int n = 0; |
195 |
| - for (; j < data.length; j += 3) { |
196 |
| - |
197 |
| - if (j < data.length - dataRemainder) { |
198 |
| - n = ((data[j] & 0xFF) << 16) + ((data[j + 1] & 0xFF) << 8) |
199 |
| - + (data[j + 2] & 0xFF); |
200 |
| - } else { |
201 |
| - if (dataRemainder == 1) { |
202 |
| - n = (data[j] & 0xFF) << 16; |
203 |
| - } else if (dataRemainder == 2) { |
204 |
| - n = ((data[j] & 0xFF) << 16) + ((data[j + 1] & 0xFF) << 8); |
205 |
| - } |
206 |
| - } |
207 |
| - |
208 |
| - // Left here for readability |
209 |
| - // byte char1 = (byte) ((n >>> 18) & 0x3F); |
210 |
| - // byte char2 = (byte) ((n >>> 12) & 0x3F); |
211 |
| - // byte char3 = (byte) ((n >>> 6) & 0x3F); |
212 |
| - // byte char4 = (byte) (n & 0x3F); |
213 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 18) & 0x3F))); |
214 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 12) & 0x3F))); |
215 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 6) & 0x3F))); |
216 |
| - builder.append(BASE_64_CHARS.charAt((byte) (n & 0x3F))); |
217 |
| - } |
218 |
| - |
219 |
| - final int bLength = builder.length(); |
220 |
| - |
221 |
| - // append '=' to pad |
222 |
| - if (data.length % 3 == 1) { |
223 |
| - builder.replace(bLength - 2, bLength, "=="); |
224 |
| - } else if (data.length % 3 == 2) { |
225 |
| - builder.replace(bLength - 1, bLength, "="); |
226 |
| - } |
227 |
| - |
228 |
| - return builder.toString(); |
229 |
| - } |
230 |
| - |
231 |
| - /** |
232 |
| - * Encodes a byte array as a Base64 string. |
233 |
| - * |
234 |
| - * @param data |
235 |
| - * the byte array to encode |
236 |
| - * @return the Base64-encoded string, as a <code>String</code> object |
237 |
| - */ |
238 |
| - public static String encode(final Byte[] data) { |
239 |
| - final StringBuilder builder = new StringBuilder(); |
240 |
| - final int dataRemainder = data.length % 3; |
241 |
| - |
242 |
| - int j = 0; |
243 |
| - int n = 0; |
244 |
| - for (; j < data.length; j += 3) { |
245 |
| - |
246 |
| - if (j < data.length - dataRemainder) { |
247 |
| - n = ((data[j] & 0xFF) << 16) + ((data[j + 1] & 0xFF) << 8) |
248 |
| - + (data[j + 2] & 0xFF); |
249 |
| - } else { |
250 |
| - if (dataRemainder == 1) { |
251 |
| - n = (data[j] & 0xFF) << 16; |
252 |
| - } else if (dataRemainder == 2) { |
253 |
| - n = ((data[j] & 0xFF) << 16) + ((data[j + 1] & 0xFF) << 8); |
254 |
| - } |
255 |
| - } |
256 |
| - |
257 |
| - // Left here for readability |
258 |
| - // byte char1 = (byte) ((n >>> 18) & 0x3F); |
259 |
| - // byte char2 = (byte) ((n >>> 12) & 0x3F); |
260 |
| - // byte char3 = (byte) ((n >>> 6) & 0x3F); |
261 |
| - // byte char4 = (byte) (n & 0x3F); |
262 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 18) & 0x3F))); |
263 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 12) & 0x3F))); |
264 |
| - builder.append(BASE_64_CHARS.charAt((byte) ((n >>> 6) & 0x3F))); |
265 |
| - builder.append(BASE_64_CHARS.charAt((byte) (n & 0x3F))); |
266 |
| - } |
267 |
| - |
268 |
| - final int bLength = builder.length(); |
269 |
| - |
270 |
| - // append '=' to pad |
271 |
| - if (data.length % 3 == 1) { |
272 |
| - builder.replace(bLength - 2, bLength, "=="); |
273 |
| - } else if (data.length % 3 == 2) { |
274 |
| - builder.replace(bLength - 1, bLength, "="); |
275 |
| - } |
276 |
| - |
277 |
| - return builder.toString(); |
278 |
| - } |
279 |
| - |
280 |
| - /** |
281 |
| - * Determines whether the given string contains only Base64 characters. |
282 |
| - * |
283 |
| - * @param data |
284 |
| - * the string, as a <code>String</code> object, to validate |
285 |
| - * @return <code>true</code> if <code>data</code> is a valid Base64 string, |
286 |
| - * otherwise <code>false</code> |
287 |
| - */ |
288 |
| - public static boolean validateIsBase64String(final String data) { |
289 |
| - |
290 |
| - if (data == null || data.length() % 4 != 0) { |
291 |
| - return false; |
292 |
| - } |
293 |
| - |
294 |
| - for (int m = 0; m < data.length(); m++) { |
295 |
| - final byte charByte = (byte) data.charAt(m); |
296 |
| - |
297 |
| - // pad char detected |
298 |
| - if (DECODE_64[charByte] == -2) { |
299 |
| - if (m < data.length() - 2) { |
300 |
| - return false; |
301 |
| - } else if (m == data.length() - 2 |
302 |
| - && DECODE_64[(byte) data.charAt(m + 1)] != -2) { |
303 |
| - return false; |
304 |
| - } |
305 |
| - } |
306 |
| - |
307 |
| - if (charByte < 0 || DECODE_64[charByte] == -1) { |
308 |
| - return false; |
309 |
| - } |
310 |
| - } |
311 |
| - |
312 |
| - return true; |
| 43 | + return org.apache.commons.codec.binary.Base64.encodeBase64String(data); |
313 | 44 | }
|
314 | 45 |
|
315 | 46 | /**
|
|
0 commit comments