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