001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: /*
021: * $Id: Base64.java,v 1.2 2007/07/16 16:41:25 ofung Exp $
022: * $Revision: 1.2 $
023: * $Date: 2007/07/16 16:41:25 $
024: */
025:
026: /*
027: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
028: *
029: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
030: *
031: * The contents of this file are subject to the terms of either the GNU
032: * General Public License Version 2 only ("GPL") or the Common Development
033: * and Distribution License("CDDL") (collectively, the "License"). You
034: * may not use this file except in compliance with the License. You can obtain
035: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
036: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
037: * language governing permissions and limitations under the License.
038: *
039: * When distributing the software, include this License Header Notice in each
040: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
041: * Sun designates this particular file as subject to the "Classpath" exception
042: * as provided by Sun in the GPL Version 2 section of the License file that
043: * accompanied this code. If applicable, add the following below the License
044: * Header, with the fields enclosed by brackets [] replaced by your own
045: * identifying information: "Portions Copyrighted [year]
046: * [name of copyright owner]"
047: *
048: * Contributor(s):
049: *
050: * If you wish your version of this file to be governed by only the CDDL or
051: * only the GPL Version 2, indicate your decision by adding "[Contributor]
052: * elects to include this software in this distribution under the [CDDL or GPL
053: * Version 2] license." If you don't indicate a single choice of license, a
054: * recipient has the option to distribute your version of this file under
055: * either the CDDL, the GPL Version 2 or to extend the choice of license to
056: * its licensees as provided above. However, if you add GPL Version 2 code
057: * and therefore, elected the GPL Version 2 license, then the option applies
058: * only if the new code is made subject to such option by the copyright
059: * holder.
060: */
061: package com.sun.xml.messaging.saaj.util;
062:
063: // Cut & paste from tomcat
064:
065: /**
066: * This class provides encode/decode for RFC 2045 Base64 as
067: * defined by RFC 2045, N. Freed and N. Borenstein.
068: * RFC 2045: Multipurpose Internet Mail Extensions (MIME)
069: * Part One: Format of Internet Message Bodies. Reference
070: * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
071: * This class is used by XML Schema binary format validation
072: *
073: * @author Jeffrey Rodriguez
074: * @version $Revision: 1.2 $ $Date: 2007/07/16 16:41:25 $
075: */
076: public final class Base64 {
077:
078: static private final int BASELENGTH = 255;
079: static private final int LOOKUPLENGTH = 63;
080: static private final int TWENTYFOURBITGROUP = 24;
081: static private final int EIGHTBIT = 8;
082: static private final int SIXTEENBIT = 16;
083: static private final int SIXBIT = 6;
084: static private final int FOURBYTE = 4;
085:
086: static private final byte PAD = (byte) '=';
087: static private byte[] base64Alphabet = new byte[BASELENGTH];
088: static private byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
089:
090: static {
091:
092: for (int i = 0; i < BASELENGTH; i++) {
093: base64Alphabet[i] = -1;
094: }
095: for (int i = 'Z'; i >= 'A'; i--) {
096: base64Alphabet[i] = (byte) (i - 'A');
097: }
098: for (int i = 'z'; i >= 'a'; i--) {
099: base64Alphabet[i] = (byte) (i - 'a' + 26);
100: }
101:
102: for (int i = '9'; i >= '0'; i--) {
103: base64Alphabet[i] = (byte) (i - '0' + 52);
104: }
105:
106: base64Alphabet['+'] = 62;
107: base64Alphabet['/'] = 63;
108:
109: for (int i = 0; i <= 25; i++)
110: lookUpBase64Alphabet[i] = (byte) ('A' + i);
111:
112: for (int i = 26, j = 0; i <= 51; i++, j++)
113: lookUpBase64Alphabet[i] = (byte) ('a' + j);
114:
115: for (int i = 52, j = 0; i <= 61; i++, j++)
116: lookUpBase64Alphabet[i] = (byte) ('0' + j);
117:
118: }
119:
120: static boolean isBase64(byte octect) {
121: //shall we ignore white space? JEFF??
122: return (octect == PAD || base64Alphabet[octect] != -1);
123: }
124:
125: static boolean isArrayByteBase64(byte[] arrayOctect) {
126: int length = arrayOctect.length;
127: if (length == 0)
128: return false;
129: for (int i = 0; i < length; i++) {
130: if (Base64.isBase64(arrayOctect[i]) == false)
131: return false;
132: }
133: return true;
134: }
135:
136: /**
137: * Encodes hex octects into Base64
138: *
139: * @param binaryData Array containing binaryData
140: * @return Encoded Base64 array
141: */
142: public static byte[] encode(byte[] binaryData) {
143: int lengthDataBits = binaryData.length * EIGHTBIT;
144: int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
145: int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
146: byte encodedData[] = null;
147:
148: if (fewerThan24bits != 0) //data not divisible by 24 bit
149: encodedData = new byte[(numberTriplets + 1) * 4];
150: else
151: // 16 or 8 bit
152: encodedData = new byte[numberTriplets * 4];
153:
154: byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
155:
156: int encodedIndex = 0;
157: int dataIndex = 0;
158: int i = 0;
159: for (i = 0; i < numberTriplets; i++) {
160:
161: dataIndex = i * 3;
162: b1 = binaryData[dataIndex];
163: b2 = binaryData[dataIndex + 1];
164: b3 = binaryData[dataIndex + 2];
165:
166: l = (byte) (b2 & 0x0f);
167: k = (byte) (b1 & 0x03);
168:
169: encodedIndex = i * 4;
170: encodedData[encodedIndex] = lookUpBase64Alphabet[b1 >> 2];
171: encodedData[encodedIndex + 1] = lookUpBase64Alphabet[(b2 >> 4)
172: | (k << 4)];
173: encodedData[encodedIndex + 2] = lookUpBase64Alphabet[(l << 2)
174: | (b3 >> 6)];
175: encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
176: }
177:
178: // form integral number of 6-bit groups
179: dataIndex = i * 3;
180: encodedIndex = i * 4;
181: if (fewerThan24bits == EIGHTBIT) {
182: b1 = binaryData[dataIndex];
183: k = (byte) (b1 & 0x03);
184: encodedData[encodedIndex] = lookUpBase64Alphabet[b1 >> 2];
185: encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
186: encodedData[encodedIndex + 2] = PAD;
187: encodedData[encodedIndex + 3] = PAD;
188: } else if (fewerThan24bits == SIXTEENBIT) {
189:
190: b1 = binaryData[dataIndex];
191: b2 = binaryData[dataIndex + 1];
192: l = (byte) (b2 & 0x0f);
193: k = (byte) (b1 & 0x03);
194: encodedData[encodedIndex] = lookUpBase64Alphabet[b1 >> 2];
195: encodedData[encodedIndex + 1] = lookUpBase64Alphabet[(b2 >> 4)
196: | (k << 4)];
197: encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
198: encodedData[encodedIndex + 3] = PAD;
199: }
200: return encodedData;
201: }
202:
203: /**
204: * Decodes Base64 data into octects
205: *
206: * @param binaryData Byte array containing Base64 data
207: * @return Array containind decoded data.
208: */
209: public byte[] decode(byte[] base64Data) {
210: int numberQuadruple = base64Data.length / FOURBYTE;
211: byte decodedData[] = null;
212: byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
213:
214: // Throw away anything not in base64Data
215: // Adjust size
216:
217: int encodedIndex = 0;
218: int dataIndex = 0;
219: decodedData = new byte[numberQuadruple * 3 + 1];
220:
221: for (int i = 0; i < numberQuadruple; i++) {
222: dataIndex = i * 4;
223: marker0 = base64Data[dataIndex + 2];
224: marker1 = base64Data[dataIndex + 3];
225:
226: b1 = base64Alphabet[base64Data[dataIndex]];
227: b2 = base64Alphabet[base64Data[dataIndex + 1]];
228:
229: if (marker0 != PAD && marker1 != PAD) { //No PAD e.g 3cQl
230: b3 = base64Alphabet[marker0];
231: b4 = base64Alphabet[marker1];
232:
233: decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
234: decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
235: decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
236: } else if (marker0 == PAD) { //Two PAD e.g. 3c[Pad][Pad]
237: decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
238: decodedData[encodedIndex + 1] = (byte) ((b2 & 0xf) << 4);
239: decodedData[encodedIndex + 2] = (byte) 0;
240: } else if (marker1 == PAD) { //One PAD e.g. 3cQ[Pad]
241: b3 = base64Alphabet[marker0];
242:
243: decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
244: decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
245: decodedData[encodedIndex + 2] = (byte) (b3 << 6);
246: }
247: encodedIndex += 3;
248: }
249: return decodedData;
250:
251: }
252:
253: static final int base64[] = { 64, 64, 64, 64, 64, 64, 64, 64, 64,
254: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
255: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
256: 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57,
257: 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4,
258: 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
259: 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29,
260: 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
261: 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64,
262: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
263: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
264: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
265: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
266: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
267: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
268: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
269: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
270: 64, 64, 64, 64, 64 };
271:
272: public static String base64Decode(String orig) {
273: char chars[] = orig.toCharArray();
274: StringBuffer sb = new StringBuffer();
275: int i = 0;
276:
277: int shift = 0; // # of excess bits stored in accum
278: int acc = 0;
279:
280: for (i = 0; i < chars.length; i++) {
281: int v = base64[chars[i] & 0xFF];
282:
283: if (v >= 64) {
284: if (chars[i] != '=')
285: System.out.println("Wrong char in base64: "
286: + chars[i]);
287: } else {
288: acc = (acc << 6) | v;
289: shift += 6;
290: if (shift >= 8) {
291: shift -= 8;
292: sb.append((char) ((acc >> shift) & 0xff));
293: }
294: }
295: }
296: return sb.toString();
297: }
298:
299: }
|