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 }