aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.messaging.saaj.util; aoqi@0: aoqi@0: aoqi@0: // Cut & paste from tomcat aoqi@0: aoqi@0: /** aoqi@0: * This class provides encode/decode for RFC 2045 Base64 as aoqi@0: * defined by RFC 2045, N. Freed and N. Borenstein. aoqi@0: * RFC 2045: Multipurpose Internet Mail Extensions (MIME) aoqi@0: * Part One: Format of Internet Message Bodies. Reference aoqi@0: * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt aoqi@0: * This class is used by XML Schema binary format validation aoqi@0: * aoqi@0: * @author Jeffrey Rodriguez aoqi@0: * @version aoqi@0: */ aoqi@0: public final class Base64 { aoqi@0: aoqi@0: aoqi@0: static private final int BASELENGTH = 255; aoqi@0: static private final int LOOKUPLENGTH = 63; aoqi@0: static private final int TWENTYFOURBITGROUP = 24; aoqi@0: static private final int EIGHTBIT = 8; aoqi@0: static private final int SIXTEENBIT = 16; aoqi@0: static private final int SIXBIT = 6; aoqi@0: static private final int FOURBYTE = 4; aoqi@0: aoqi@0: aoqi@0: static private final byte PAD = ( byte ) '='; aoqi@0: static private byte [] base64Alphabet = new byte[BASELENGTH]; aoqi@0: static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; aoqi@0: aoqi@0: static { aoqi@0: aoqi@0: for (int i = 0; i= 'A'; i-- ) { aoqi@0: base64Alphabet[i] = (byte) (i-'A'); aoqi@0: } aoqi@0: for ( int i = 'z'; i>= 'a'; i--) { aoqi@0: base64Alphabet[i] = (byte) ( i-'a' + 26); aoqi@0: } aoqi@0: aoqi@0: for ( int i = '9'; i >= '0'; i--) { aoqi@0: base64Alphabet[i] = (byte) (i-'0' + 52); aoqi@0: } aoqi@0: aoqi@0: base64Alphabet['+'] = 62; aoqi@0: base64Alphabet['/'] = 63; aoqi@0: aoqi@0: for (int i = 0; i<=25; i++ ) aoqi@0: lookUpBase64Alphabet[i] = (byte) ('A'+i ); aoqi@0: aoqi@0: for (int i = 26, j = 0; i<=51; i++, j++ ) aoqi@0: lookUpBase64Alphabet[i] = (byte) ('a'+ j ); aoqi@0: aoqi@0: for (int i = 52, j = 0; i<=61; i++, j++ ) aoqi@0: lookUpBase64Alphabet[i] = (byte) ('0' + j ); aoqi@0: aoqi@0: } aoqi@0: aoqi@0: aoqi@0: static boolean isBase64( byte octect ) { aoqi@0: //shall we ignore white space? JEFF?? aoqi@0: return(octect == PAD || base64Alphabet[octect] != -1 ); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: static boolean isArrayByteBase64( byte[] arrayOctect ) { aoqi@0: int length = arrayOctect.length; aoqi@0: if ( length == 0 ) aoqi@0: return false; aoqi@0: for ( int i=0; i < length; i++ ) { aoqi@0: if ( Base64.isBase64( arrayOctect[i] ) == false) aoqi@0: return false; aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Encodes hex octects into Base64 aoqi@0: * aoqi@0: * @param binaryData Array containing binaryData aoqi@0: * @return Encoded Base64 array aoqi@0: */ aoqi@0: public static byte[] encode( byte[] binaryData ) { aoqi@0: int lengthDataBits = binaryData.length*EIGHTBIT; aoqi@0: int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; aoqi@0: int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; aoqi@0: byte encodedData[] = null; aoqi@0: aoqi@0: aoqi@0: if ( fewerThan24bits != 0 ) //data not divisible by 24 bit aoqi@0: encodedData = new byte[ (numberTriplets + 1 )*4 ]; aoqi@0: else // 16 or 8 bit aoqi@0: encodedData = new byte[ numberTriplets*4 ]; aoqi@0: aoqi@0: byte k=0, l=0, b1=0,b2=0,b3=0; aoqi@0: aoqi@0: int encodedIndex = 0; aoqi@0: int dataIndex = 0; aoqi@0: int i = 0; aoqi@0: for ( i = 0; i>2 ]; aoqi@0: encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | aoqi@0: ( k<<4 )]; aoqi@0: encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | aoqi@0: ( b3>>6)]; aoqi@0: encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; aoqi@0: } aoqi@0: aoqi@0: // form integral number of 6-bit groups aoqi@0: dataIndex = i*3; aoqi@0: encodedIndex = i*4; aoqi@0: if (fewerThan24bits == EIGHTBIT ) { aoqi@0: b1 = binaryData[dataIndex]; aoqi@0: k = (byte) ( b1 &0x03 ); aoqi@0: encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; aoqi@0: encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; aoqi@0: encodedData[encodedIndex + 2] = PAD; aoqi@0: encodedData[encodedIndex + 3] = PAD; aoqi@0: } else if ( fewerThan24bits == SIXTEENBIT ) { aoqi@0: aoqi@0: b1 = binaryData[dataIndex]; aoqi@0: b2 = binaryData[dataIndex +1 ]; aoqi@0: l = ( byte ) ( b2 &0x0f ); aoqi@0: k = ( byte ) ( b1 &0x03 ); aoqi@0: encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; aoqi@0: encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) aoqi@0: | ( k<<4 )]; aoqi@0: encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; aoqi@0: encodedData[encodedIndex + 3] = PAD; aoqi@0: } aoqi@0: return encodedData; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Decodes Base64 data into octects aoqi@0: * aoqi@0: * @param binaryData Byte array containing Base64 data aoqi@0: * @return Array containind decoded data. aoqi@0: */ aoqi@0: public byte[] decode( byte[] base64Data ) { aoqi@0: int numberQuadruple = base64Data.length/FOURBYTE; aoqi@0: byte decodedData[] = null; aoqi@0: byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; aoqi@0: aoqi@0: // Throw away anything not in base64Data aoqi@0: // Adjust size aoqi@0: aoqi@0: int encodedIndex = 0; aoqi@0: int dataIndex = 0; aoqi@0: decodedData = new byte[ numberQuadruple*3 + 1 ]; aoqi@0: aoqi@0: for (int i = 0; i>4 ) ; aoqi@0: decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( aoqi@0: (b3>>2) & 0xf) ); aoqi@0: decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); aoqi@0: } else if ( marker0 == PAD ) { //Two PAD e.g. 3c[Pad][Pad] aoqi@0: decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; aoqi@0: decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); aoqi@0: decodedData[encodedIndex+2] = (byte) 0; aoqi@0: } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] aoqi@0: b3 = base64Alphabet[ marker0 ]; aoqi@0: aoqi@0: decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); aoqi@0: decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( aoqi@0: (b3>>2) & 0xf) ); aoqi@0: decodedData[encodedIndex+2] = (byte)( b3<<6); aoqi@0: } aoqi@0: encodedIndex += 3; aoqi@0: } aoqi@0: return decodedData; aoqi@0: aoqi@0: } aoqi@0: aoqi@0: static final int base64[]= { aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, aoqi@0: 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, aoqi@0: 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, aoqi@0: 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, aoqi@0: 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, aoqi@0: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 aoqi@0: }; aoqi@0: aoqi@0: public static String base64Decode( String orig ) { aoqi@0: char chars[]=orig.toCharArray(); aoqi@0: StringBuffer sb=new StringBuffer(); aoqi@0: int i=0; aoqi@0: aoqi@0: int shift = 0; // # of excess bits stored in accum aoqi@0: int acc = 0; aoqi@0: aoqi@0: for (i=0; i= 64 ) { aoqi@0: if( chars[i] != '=' ) aoqi@0: System.out.println("Wrong char in base64: " + chars[i]); aoqi@0: } else { aoqi@0: acc= ( acc << 6 ) | v; aoqi@0: shift += 6; aoqi@0: if ( shift >= 8 ) { aoqi@0: shift -= 8; aoqi@0: sb.append( (char) ((acc >> shift) & 0xff)); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return sb.toString(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: }