1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.messaging.saaj.util; 27 28 29 // Cut & paste from tomcat 30 31 /** 32 * This class provides encode/decode for RFC 2045 Base64 as 33 * defined by RFC 2045, N. Freed and N. Borenstein. 34 * RFC 2045: Multipurpose Internet Mail Extensions (MIME) 35 * Part One: Format of Internet Message Bodies. Reference 36 * 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt 37 * This class is used by XML Schema binary format validation 38 * 39 * @author Jeffrey Rodriguez 40 * @version 41 */ 42 public final class Base64 { 43 44 45 static private final int BASELENGTH = 255; 46 static private final int LOOKUPLENGTH = 63; 47 static private final int TWENTYFOURBITGROUP = 24; 48 static private final int EIGHTBIT = 8; 49 static private final int SIXTEENBIT = 16; 50 static private final int FOURBYTE = 4; 51 52 53 static private final byte PAD = ( byte ) '='; 54 static private byte [] base64Alphabet = new byte[BASELENGTH]; 55 static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; 56 57 static { 58 59 for (int i = 0; i<BASELENGTH; i++ ) { 60 base64Alphabet[i] = -1; 61 } 62 for ( int i = 'Z'; i >= 'A'; i-- ) { 63 base64Alphabet[i] = (byte) (i-'A'); 64 } 65 for ( int i = 'z'; i>= 'a'; i--) { 66 base64Alphabet[i] = (byte) ( i-'a' + 26); 67 } 68 69 for ( int i = '9'; i >= '0'; i--) { 70 base64Alphabet[i] = (byte) (i-'0' + 52); 71 } 72 73 base64Alphabet['+'] = 62; 74 base64Alphabet['/'] = 63; 75 76 for (int i = 0; i<=25; i++ ) 77 lookUpBase64Alphabet[i] = (byte) ('A'+i ); 78 79 for (int i = 26, j = 0; i<=51; i++, j++ ) 80 lookUpBase64Alphabet[i] = (byte) ('a'+ j ); 81 82 for (int i = 52, j = 0; i<=61; i++, j++ ) 83 lookUpBase64Alphabet[i] = (byte) ('0' + j ); 84 85 } 86 87 88 static boolean isBase64( byte octect ) { 89 //shall we ignore white space? JEFF?? 90 return(octect == PAD || base64Alphabet[octect] != -1 ); 91 } 92 93 94 static boolean isArrayByteBase64( byte[] arrayOctect ) { 95 int length = arrayOctect.length; 96 if ( length == 0 ) 97 return false; 98 for ( int i=0; i < length; i++ ) { 99 if ( Base64.isBase64( arrayOctect[i] ) == false) 100 return false; 101 } 102 return true; 103 } 104 105 /** 106 * Encodes hex octects into Base64 107 * 108 * @param binaryData Array containing binaryData 109 * @return Encoded Base64 array 110 */ 111 public static byte[] encode( byte[] binaryData ) { 112 int lengthDataBits = binaryData.length*EIGHTBIT; 113 int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; 114 int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; 115 byte encodedData[] = null; 116 117 118 if ( fewerThan24bits != 0 ) //data not divisible by 24 bit 119 encodedData = new byte[ (numberTriplets + 1 )*4 ]; 120 else // 16 or 8 bit 121 encodedData = new byte[ numberTriplets*4 ]; 122 123 byte k=0, l=0, b1=0,b2=0,b3=0; 124 125 int encodedIndex = 0; 126 int dataIndex = 0; 127 int i = 0; 128 for ( i = 0; i<numberTriplets; i++ ) { 129 130 dataIndex = i*3; 131 b1 = binaryData[dataIndex]; 132 b2 = binaryData[dataIndex + 1]; 133 b3 = binaryData[dataIndex + 2]; 134 135 l = (byte)(b2 & 0x0f); 136 k = (byte)(b1 & 0x03); 137 138 encodedIndex = i*4; 139 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 140 encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | 141 ( k<<4 )]; 142 encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | 143 ( b3>>6)]; 144 encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; 145 } 146 147 // form integral number of 6-bit groups 148 dataIndex = i*3; 149 encodedIndex = i*4; 150 if (fewerThan24bits == EIGHTBIT ) { 151 b1 = binaryData[dataIndex]; 152 k = (byte) ( b1 &0x03 ); 153 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 154 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; 155 encodedData[encodedIndex + 2] = PAD; 156 encodedData[encodedIndex + 3] = PAD; 157 } else if ( fewerThan24bits == SIXTEENBIT ) { 158 159 b1 = binaryData[dataIndex]; 160 b2 = binaryData[dataIndex +1 ]; 161 l = ( byte ) ( b2 &0x0f ); 162 k = ( byte ) ( b1 &0x03 ); 163 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 164 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) 165 | ( k<<4 )]; 166 encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; 167 encodedData[encodedIndex + 3] = PAD; 168 } 169 return encodedData; 170 } 171 172 173 /** 174 * Decodes Base64 data into octects 175 * 176 * @param binaryData Byte array containing Base64 data 177 * @return Array containind decoded data. 178 */ 179 public byte[] decode( byte[] base64Data ) { 180 int numberQuadruple = base64Data.length/FOURBYTE; 181 byte decodedData[] = null; 182 byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; 183 184 // Throw away anything not in base64Data 185 // Adjust size 186 187 int encodedIndex = 0; 188 int dataIndex = 0; 189 decodedData = new byte[ numberQuadruple*3 + 1 ]; 190 191 for (int i = 0; i<numberQuadruple; i++ ) { 192 dataIndex = i*4; 193 marker0 = base64Data[dataIndex +2]; 194 marker1 = base64Data[dataIndex +3]; 195 196 b1 = base64Alphabet[base64Data[dataIndex]]; 197 b2 = base64Alphabet[base64Data[dataIndex +1]]; 198 199 if ( marker0 != PAD && marker1 != PAD ) { //No PAD e.g 3cQl 200 b3 = base64Alphabet[ marker0 ]; 201 b4 = base64Alphabet[ marker1 ]; 202 203 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 204 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 205 (b3>>2) & 0xf) ); 206 decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); 207 } else if ( marker0 == PAD ) { //Two PAD e.g. 3c[Pad][Pad] 208 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 209 decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); 210 decodedData[encodedIndex+2] = (byte) 0; 211 } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] 212 b3 = base64Alphabet[ marker0 ]; 213 214 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); 215 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 216 (b3>>2) & 0xf) ); 217 decodedData[encodedIndex+2] = (byte)( b3<<6); 218 } 219 encodedIndex += 3; 220 } 221 return decodedData; 222 223 } 224 225 static final int base64[]= { 226 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 227 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 228 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 229 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 230 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 231 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 232 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 233 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 234 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 235 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 236 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 237 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 238 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 239 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 240 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 241 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 242 }; 243 244 public static String base64Decode( String orig ) { 245 char chars[]=orig.toCharArray(); 246 StringBuilder sb=new StringBuilder(); 247 int i=0; 248 249 int shift = 0; // # of excess bits stored in accum 250 int acc = 0; 251 252 for (i=0; i<chars.length; i++) { 253 int v = base64[ chars[i] & 0xFF ]; 254 255 if ( v >= 64 ) { 256 if( chars[i] != '=' ) 257 System.out.println("Wrong char in base64: " + chars[i]); 258 } else { 259 acc= ( acc << 6 ) | v; 260 shift += 6; 261 if ( shift >= 8 ) { 262 shift -= 8; 263 sb.append( (char) ((acc >> shift) & 0xff)); 264 } 265 } 266 } 267 return sb.toString(); 268 } 269 270 271 }