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 SIXBIT = 6; 51 static private final int FOURBYTE = 4; 52 53 54 static private final byte PAD = ( byte ) '='; 55 static private byte [] base64Alphabet = new byte[BASELENGTH]; 56 static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; 57 58 static { 59 60 for (int i = 0; i<BASELENGTH; i++ ) { 61 base64Alphabet[i] = -1; 62 } 63 for ( int i = 'Z'; i >= 'A'; i-- ) { 64 base64Alphabet[i] = (byte) (i-'A'); 65 } 66 for ( int i = 'z'; i>= 'a'; i--) { 67 base64Alphabet[i] = (byte) ( i-'a' + 26); 68 } 69 70 for ( int i = '9'; i >= '0'; i--) { 71 base64Alphabet[i] = (byte) (i-'0' + 52); 72 } 73 74 base64Alphabet['+'] = 62; 75 base64Alphabet['/'] = 63; 76 77 for (int i = 0; i<=25; i++ ) 78 lookUpBase64Alphabet[i] = (byte) ('A'+i ); 79 80 for (int i = 26, j = 0; i<=51; i++, j++ ) 81 lookUpBase64Alphabet[i] = (byte) ('a'+ j ); 82 83 for (int i = 52, j = 0; i<=61; i++, j++ ) 84 lookUpBase64Alphabet[i] = (byte) ('0' + j ); 85 86 } 87 88 89 static boolean isBase64( byte octect ) { 90 //shall we ignore white space? JEFF?? 91 return(octect == PAD || base64Alphabet[octect] != -1 ); 92 } 93 94 95 static boolean isArrayByteBase64( byte[] arrayOctect ) { 96 int length = arrayOctect.length; 97 if ( length == 0 ) 98 return false; 99 for ( int i=0; i < length; i++ ) { 100 if ( Base64.isBase64( arrayOctect[i] ) == false) 101 return false; 102 } 103 return true; 104 } 105 106 /** 107 * Encodes hex octects into Base64 108 * 109 * @param binaryData Array containing binaryData 110 * @return Encoded Base64 array 111 */ 112 public static byte[] encode( byte[] binaryData ) { 113 int lengthDataBits = binaryData.length*EIGHTBIT; 114 int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; 115 int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; 116 byte encodedData[] = null; 117 118 119 if ( fewerThan24bits != 0 ) //data not divisible by 24 bit 120 encodedData = new byte[ (numberTriplets + 1 )*4 ]; 121 else // 16 or 8 bit 122 encodedData = new byte[ numberTriplets*4 ]; 123 124 byte k=0, l=0, b1=0,b2=0,b3=0; 125 126 int encodedIndex = 0; 127 int dataIndex = 0; 128 int i = 0; 129 for ( i = 0; i<numberTriplets; i++ ) { 130 131 dataIndex = i*3; 132 b1 = binaryData[dataIndex]; 133 b2 = binaryData[dataIndex + 1]; 134 b3 = binaryData[dataIndex + 2]; 135 136 l = (byte)(b2 & 0x0f); 137 k = (byte)(b1 & 0x03); 138 139 encodedIndex = i*4; 140 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 141 encodedData[encodedIndex+1] = lookUpBase64Alphabet[(b2 >>4 ) | 142 ( k<<4 )]; 143 encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | 144 ( b3>>6)]; 145 encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ]; 146 } 147 148 // form integral number of 6-bit groups 149 dataIndex = i*3; 150 encodedIndex = i*4; 151 if (fewerThan24bits == EIGHTBIT ) { 152 b1 = binaryData[dataIndex]; 153 k = (byte) ( b1 &0x03 ); 154 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 155 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ]; 156 encodedData[encodedIndex + 2] = PAD; 157 encodedData[encodedIndex + 3] = PAD; 158 } else if ( fewerThan24bits == SIXTEENBIT ) { 159 160 b1 = binaryData[dataIndex]; 161 b2 = binaryData[dataIndex +1 ]; 162 l = ( byte ) ( b2 &0x0f ); 163 k = ( byte ) ( b1 &0x03 ); 164 encodedData[encodedIndex] = lookUpBase64Alphabet[ b1 >>2 ]; 165 encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ (b2 >>4 ) 166 | ( k<<4 )]; 167 encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ]; 168 encodedData[encodedIndex + 3] = PAD; 169 } 170 return encodedData; 171 } 172 173 174 /** 175 * Decodes Base64 data into octects 176 * 177 * @param binaryData Byte array containing Base64 data 178 * @return Array containind decoded data. 179 */ 180 public byte[] decode( byte[] base64Data ) { 181 int numberQuadruple = base64Data.length/FOURBYTE; 182 byte decodedData[] = null; 183 byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0; 184 185 // Throw away anything not in base64Data 186 // Adjust size 187 188 int encodedIndex = 0; 189 int dataIndex = 0; 190 decodedData = new byte[ numberQuadruple*3 + 1 ]; 191 192 for (int i = 0; i<numberQuadruple; i++ ) { 193 dataIndex = i*4; 194 marker0 = base64Data[dataIndex +2]; 195 marker1 = base64Data[dataIndex +3]; 196 197 b1 = base64Alphabet[base64Data[dataIndex]]; 198 b2 = base64Alphabet[base64Data[dataIndex +1]]; 199 200 if ( marker0 != PAD && marker1 != PAD ) { //No PAD e.g 3cQl 201 b3 = base64Alphabet[ marker0 ]; 202 b4 = base64Alphabet[ marker1 ]; 203 204 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 205 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 206 (b3>>2) & 0xf) ); 207 decodedData[encodedIndex+2] = (byte)( b3<<6 | b4 ); 208 } else if ( marker0 == PAD ) { //Two PAD e.g. 3c[Pad][Pad] 209 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; 210 decodedData[encodedIndex+1] = (byte)((b2 & 0xf)<<4 ); 211 decodedData[encodedIndex+2] = (byte) 0; 212 } else if ( marker1 == PAD ) { //One PAD e.g. 3cQ[Pad] 213 b3 = base64Alphabet[ marker0 ]; 214 215 decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ); 216 decodedData[encodedIndex+1] = (byte)(((b2 & 0xf)<<4 ) |( 217 (b3>>2) & 0xf) ); 218 decodedData[encodedIndex+2] = (byte)( b3<<6); 219 } 220 encodedIndex += 3; 221 } 222 return decodedData; 223 224 } 225 226 static final int base64[]= { 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, 64, 64, 64, 64, 64, 229 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 230 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 231 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 232 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 233 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 234 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 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 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 243 }; 244 245 public static String base64Decode( String orig ) { 246 char chars[]=orig.toCharArray(); 247 StringBuffer sb=new StringBuffer(); 248 int i=0; 249 250 int shift = 0; // # of excess bits stored in accum 251 int acc = 0; 252 253 for (i=0; i<chars.length; i++) { 254 int v = base64[ chars[i] & 0xFF ]; 255 256 if ( v >= 64 ) { 257 if( chars[i] != '=' ) 258 System.out.println("Wrong char in base64: " + chars[i]); 259 } else { 260 acc= ( acc << 6 ) | v; 261 shift += 6; 262 if ( shift >= 8 ) { 263 shift -= 8; 264 sb.append( (char) ((acc >> shift) & 0xff)); 265 } 266 } 267 } 268 return sb.toString(); 269 } 270 271 272 }