1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/Base64.java,v 1.6 2003/02/07 14:38:01 jsdever Exp $
3 * $Revision: 1.6 $
4 * $Date: 2003/02/07 14:38:01 $
5 *
6 * ====================================================================
7 *
8 * The Apache Software License, Version 1.1
9 *
10 * Copyright (c) 1999-2003 The Apache Software Foundation. All rights
11 * reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. The end-user documentation included with the redistribution, if
26 * any, must include the following acknowlegement:
27 * "This product includes software developed by the
28 * Apache Software Foundation (http://www.apache.org/)."
29 * Alternately, this acknowlegement may appear in the software itself,
30 * if and wherever such third-party acknowlegements normally appear.
31 *
32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33 * Foundation" must not be used to endorse or promote products derived
34 * from this software without prior written permission. For written
35 * permission, please contact apache@apache.org.
36 *
37 * 5. Products derived from this software may not be called "Apache"
38 * nor may "Apache" appear in their names without prior written
39 * permission of the Apache Group.
40 *
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This software consists of voluntary contributions made by many
56 * individuals on behalf of the Apache Software Foundation. For more
57 * information on the Apache Software Foundation, please see
58 * <http://www.apache.org/>.
59 *
60 * [Additional notices, if required by prior licensing conditions]
61 *
62 */
63
64 package org.apache.commons.httpclient.util;
65
66 import org.apache.commons.httpclient.HttpConstants;
67
68 /***
69 * Base64 encoder and decoder.
70 * <p>
71 * This class provides encoding/decoding methods for the Base64 encoding as
72 * defined by RFC 2045, N. Freed and N. Borenstein. RFC 2045: Multipurpose
73 * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies.
74 * Reference 1996. Available at:
75 * <a href="http://www.ietf.org/rfc/rfc2045.txt">http://www.ietf.org/rfc/rfc2045.txt</a>
76 * </p>
77 *
78 * @deprecated The commons-codec Base64 class will be used in HttpClient 2.1
79 * @author Jeffrey Rodriguez
80 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
81 * @version $Revision: 1.6 $ $Date: 2003/02/07 14:38:01 $
82 *
83 */
84 public final class Base64 {
85
86 /*** */
87 private static final int BASELENGTH = 255;
88
89 /*** */
90 private static final int LOOKUPLENGTH = 64;
91
92 /*** */
93 private static final int TWENTYFOURBITGROUP = 24;
94
95 /*** */
96 private static final int EIGHTBIT = 8;
97
98 /*** */
99 private static final int SIXTEENBIT = 16;
100
101 /*** */
102 private static final int SIXBIT = 6;
103
104 /*** */
105 private static final int FOURBYTE = 4;
106
107 /*** The sign bit as an int */
108 private static final int SIGN = -128;
109
110 /*** The padding character */
111 private static final byte PAD = (byte) '=';
112
113 /*** The alphabet */
114 private static final byte [] BASE64_ALPHABET = new byte[BASELENGTH];
115
116 /*** The lookup alphabet */
117 private static final byte [] LOOKUP_BASE64_ALPHABET = new byte[LOOKUPLENGTH];
118
119 static {
120
121 for (int i = 0; i < BASELENGTH; i++) {
122 BASE64_ALPHABET[i] = -1;
123 }
124 for (int i = 'Z'; i >= 'A'; i--) {
125 BASE64_ALPHABET[i] = (byte) (i - 'A');
126 }
127 for (int i = 'z'; i >= 'a'; i--) {
128 BASE64_ALPHABET[i] = (byte) (i - 'a' + 26);
129 }
130
131 for (int i = '9'; i >= '0'; i--) {
132 BASE64_ALPHABET[i] = (byte) (i - '0' + 52);
133 }
134
135 BASE64_ALPHABET['+'] = 62;
136 BASE64_ALPHABET['/'] = 63;
137
138 for (int i = 0; i <= 25; i++) {
139 LOOKUP_BASE64_ALPHABET[i] = (byte) ('A' + i);
140 }
141
142 for (int i = 26, j = 0; i <= 51; i++, j++) {
143 LOOKUP_BASE64_ALPHABET[i] = (byte) ('a' + j);
144 }
145
146 for (int i = 52, j = 0; i <= 61; i++, j++) {
147 LOOKUP_BASE64_ALPHABET[i] = (byte) ('0' + j);
148 }
149 LOOKUP_BASE64_ALPHABET[62] = (byte) '+';
150 LOOKUP_BASE64_ALPHABET[63] = (byte) '/';
151
152 }
153
154 /***
155 * Create an instance.
156 */
157 private Base64() {
158 // the constructor is intentionally private
159 }
160
161 /***
162 * Return true if the specified string is base64 encoded.
163 * @param isValidString The string to test.
164 * @return boolean True if the string is base64.
165 */
166 public static boolean isBase64(String isValidString) {
167 return isArrayByteBase64(HttpConstants.getAsciiBytes(isValidString));
168 }
169
170
171 /***
172 * Return true if the specified octect is base64
173 * @param octect The octet to test.
174 * @return boolean True if the octect is base64.
175 */
176 static boolean isBase64(byte octect) {
177 // Should we ignore white space?
178 return (octect == PAD || BASE64_ALPHABET[octect] != -1);
179 }
180
181 /***
182 * Return true if the specified byte array is base64
183 * @param arrayOctect The array to test.
184 * @return boolean true if the specified byte array is base64
185 */
186 public static boolean isArrayByteBase64(byte[] arrayOctect) {
187 int length = arrayOctect.length;
188 if (length == 0) {
189 return true;
190 }
191 for (int i = 0; i < length; i++) {
192 if (!Base64.isBase64(arrayOctect[i])) {
193 return false;
194 }
195 }
196 return true;
197 }
198
199 /***
200 * Encodes hex octects into Base64
201 *
202 * @param binaryData Array containing binaryData
203 * @return Base64-encoded array
204 */
205 public static byte[] encode(byte[] binaryData) {
206
207 int lengthDataBits = binaryData.length * EIGHTBIT;
208 int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
209 int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
210 byte encodedData[] = null;
211
212
213 if (fewerThan24bits != 0) { //data not divisible by 24 bit
214 encodedData = new byte[(numberTriplets + 1) * 4];
215 } else { // 16 or 8 bit
216 encodedData = new byte[numberTriplets * 4];
217 }
218
219 byte k = 0;
220 byte l = 0;
221 byte b1 = 0;
222 byte b2 = 0;
223 byte b3 = 0;
224 int encodedIndex = 0;
225 int dataIndex = 0;
226 int i = 0;
227 for (i = 0; i < numberTriplets; i++) {
228
229 dataIndex = i * 3;
230 b1 = binaryData[dataIndex];
231 b2 = binaryData[dataIndex + 1];
232 b3 = binaryData[dataIndex + 2];
233
234 l = (byte) (b2 & 0x0f);
235 k = (byte) (b1 & 0x03);
236
237 encodedIndex = i * 4;
238 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
239 : (byte) ((b1) >> 2 ^ 0xc0);
240
241 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
242 : (byte) ((b2) >> 4 ^ 0xf0);
243 byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
244 : (byte) ((b3) >> 6 ^ 0xfc);
245
246 encodedData[encodedIndex] = LOOKUP_BASE64_ALPHABET[val1];
247 encodedData[encodedIndex + 1] = LOOKUP_BASE64_ALPHABET[val2
248 | (k << 4)];
249 encodedData[encodedIndex + 2] = LOOKUP_BASE64_ALPHABET[(l << 2)
250 | val3];
251 encodedData[encodedIndex + 3] = LOOKUP_BASE64_ALPHABET[b3 & 0x3f];
252 }
253
254 // form integral number of 6-bit groups
255 dataIndex = i * 3;
256 encodedIndex = i * 4;
257 if (fewerThan24bits == EIGHTBIT) {
258 b1 = binaryData[dataIndex];
259 k = (byte) (b1 & 0x03);
260 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
261 : (byte) ((b1) >> 2 ^ 0xc0);
262 encodedData[encodedIndex] = LOOKUP_BASE64_ALPHABET[val1];
263 encodedData[encodedIndex + 1] = LOOKUP_BASE64_ALPHABET[k << 4];
264 encodedData[encodedIndex + 2] = PAD;
265 encodedData[encodedIndex + 3] = PAD;
266 } else if (fewerThan24bits == SIXTEENBIT) {
267 b1 = binaryData[dataIndex];
268 b2 = binaryData[dataIndex + 1];
269 l = (byte) (b2 & 0x0f);
270 k = (byte) (b1 & 0x03);
271
272 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
273 : (byte) ((b1) >> 2 ^ 0xc0);
274 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
275 : (byte) ((b2) >> 4 ^ 0xf0);
276
277 encodedData[encodedIndex] = LOOKUP_BASE64_ALPHABET[val1];
278 encodedData[encodedIndex + 1] = LOOKUP_BASE64_ALPHABET[val2
279 | (k << 4)];
280 encodedData[encodedIndex + 2] = LOOKUP_BASE64_ALPHABET[l << 2];
281 encodedData[encodedIndex + 3] = PAD;
282 }
283 return encodedData;
284 }
285
286
287 /***
288 * Decodes Base64 data into octects
289 *
290 * @param base64Data byte array containing Base64 data
291 * @return Array containing decoded data.
292 */
293 public static byte[] decode(byte[] base64Data) {
294 // Should we throw away anything not in base64Data ?
295
296 // handle the edge case, so we don't have to worry about it later
297 if (base64Data.length == 0) {
298 return new byte[0];
299 }
300
301 int numberQuadruple = base64Data.length / FOURBYTE;
302 byte decodedData[] = null;
303 byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
304
305 int encodedIndex = 0;
306 int dataIndex = 0;
307 {
308 // this block sizes the output array properly - rlw
309 int lastData = base64Data.length;
310 // ignore the '=' padding
311 while (base64Data[lastData - 1] == PAD) {
312 if (--lastData == 0) { return new byte[0]; }
313 }
314 decodedData = new byte[lastData - numberQuadruple];
315 }
316
317 for (int i = 0; i < numberQuadruple; i++) {
318 dataIndex = i * 4;
319 marker0 = base64Data[dataIndex + 2];
320 marker1 = base64Data[dataIndex + 3];
321
322 b1 = BASE64_ALPHABET[base64Data[dataIndex]];
323 b2 = BASE64_ALPHABET[base64Data[dataIndex + 1]];
324
325 if (marker0 != PAD && marker1 != PAD) { //No PAD e.g 3cQl
326 b3 = BASE64_ALPHABET[marker0];
327 b4 = BASE64_ALPHABET[marker1];
328
329 decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
330 decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4)
331 | ((b3 >> 2) & 0xf));
332 decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
333 } else if (marker0 == PAD) { //Two PAD e.g. 3c[Pad][Pad]
334 decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4) ;
335 } else if (marker1 == PAD) { //One PAD e.g. 3cQ[Pad]
336 b3 = BASE64_ALPHABET[marker0];
337 decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
338 decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4)
339 | ((b3 >> 2) & 0xf));
340 }
341 encodedIndex += 3;
342 }
343 return decodedData;
344 }
345 }
This page was automatically generated by Maven