All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.opensagres.xdocreport.core.utils.Base64Utility Maven / Gradle / Ivy

/**
 * Copyright (C) 2011-2012 The XDocReport Team 
 *
 * All rights reserved.
 *
 * Permission is hereby granted, free  of charge, to any person obtaining
 * a  copy  of this  software  and  associated  documentation files  (the
 * "Software"), to  deal in  the Software without  restriction, including
 * without limitation  the rights to  use, copy, modify,  merge, publish,
 * distribute,  sublicense, and/or sell  copies of  the Software,  and to
 * permit persons to whom the Software  is furnished to do so, subject to
 * the following conditions:
 *
 * The  above  copyright  notice  and  this permission  notice  shall  be
 * included in all copies or substantial portions of the Software.
 *
 * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
 * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
 * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package fr.opensagres.xdocreport.core.utils;

/**
 * Base64Utility - this static class provides useful base64 
 *                 encoding utilities.
 * 

* @author Darach Ennis * @author Craig Ryan */ // Java imports import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.util.logging.Logger; import fr.opensagres.xdocreport.core.io.IOUtils; import fr.opensagres.xdocreport.core.logging.LogUtils; /** * This class converts to/from base64. The alternative conversions include: encode: byte[] into String byte[] into * char[] byte[] into OutStream byte[] into Writer decode: char[] into byte[] String into byte[] char[] into OutStream * String into OutStream */ public final class Base64Utility { private static final Logger LOG = LogUtils.getLogger( Base64Utility.class ); // base 64 character set // private static final char[] BCS = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; // base 64 wadding private static final char PAD = '='; // size of base 64 decode table private static final int BDTSIZE = 128; // base 64 decode table private static final byte[] BDT = new byte[128]; private static final int PAD_SIZE0 = 1; private static final int PAD_SIZE4 = 2; private static final int PAD_SIZE8 = 3; // class static intializer for building decode table static { for ( int i = 0; i < BDTSIZE; i++ ) { BDT[i] = Byte.MAX_VALUE; } for ( int i = 0; i < BCS.length; i++ ) { BDT[BCS[i]] = (byte) i; } } private Base64Utility() { // utility class, never constructed } /** * The decode_chunk routine decodes a chunk of data into its native encoding. base64 encodes each 3 * octets of data into 4 characters from a limited 64 character set. The 3 octets are joined to form 24 bits which * are then split into 4 x 6bit values. Each 6 bit value is then used as an index into the 64 character table of * base64 chars. If the total data length is not a 3 octet multiple the '=' char is used as padding for the final 4 * char group, either 1 octet + '==' or 2 octets + '='. * * @param id The input data to be processed * @param o The offset from which to begin processing * @param l The length (bound) at which processing is to end * @return The decoded data * @exception Base64Exception Thrown is processing fails due to formatting exceptions in the encoded data */ public static byte[] decodeChunk( char[] id, int o, int l ) throws Base64Exception { // Keep it simple - must be >= 4. Unpadded // base64 data contain < 3 octets is invalid. // if ( ( l - o ) < 4 ) { return null; } char[] ib = new char[4]; int ibcount = 0; // cryan. Calc the num of octets. Each 4 chars of base64 chars // (representing 24 bits) encodes 3 octets. // int octetCount = 3 * ( l / 4 ); // Final 4 chars may contain 3 octets or padded to contain // 1 or 2 octets. // if ( id[l - 1] == PAD ) { // TT== means last 4 chars encode 8 bits (ie subtract 2) // TTT= means last 4 chars encode 16 bits (ie subtract 1) octetCount -= ( id[l - 2] == PAD ) ? 2 : 1; } byte[] ob = new byte[octetCount]; int obcount = 0; for ( int i = o; i < o + l && i < id.length; i++ ) { if ( id[i] == PAD || id[i] < BDT.length && BDT[id[i]] != Byte.MAX_VALUE ) { ib[ibcount++] = id[i]; // Decode each 4 char sequence. // if ( ibcount == ib.length ) { ibcount = 0; obcount += processEncodeme( ib, ob, obcount ); } } } if ( obcount != ob.length ) { byte[] tmp = new byte[obcount]; System.arraycopy( ob, 0, tmp, 0, obcount ); ob = tmp; } return ob; } public static byte[] decode( String id ) throws Base64Exception { try { char[] cd = id.toCharArray(); return decodeChunk( cd, 0, cd.length ); } catch ( Exception e ) { LOG.warning( "Invalid base64 encoded string : " + id ); throw new Base64Exception( "Runtime exception in Base64Utility.decode() during output", e ); } } public static void decode( char[] id, int o, int l, OutputStream ostream ) throws Base64Exception { try { ostream.write( decodeChunk( id, o, l ) ); } catch ( Exception e ) { LOG.warning( "Invalid base64 encoded string : " + new String( id ) ); throw new Base64Exception( "Runtime exception in Base64Utility.decode() during output", e ); } } public static void decode( String id, OutputStream ostream ) throws Base64Exception { try { char[] cd = id.toCharArray(); ostream.write( decodeChunk( cd, 0, cd.length ) ); } catch ( IOException ioe ) { throw new Base64Exception( "decode() to outstream raised IOException", ioe ); } catch ( Exception e ) { LOG.warning( "Invalid base64 encoded string : " + id ); throw new Base64Exception( "Runtime exception in Base64Utility.decode() during output", e ); } } public static String encode( InputStream in ) throws IOException { byte[] bytes = IOUtils.toByteArray( in ); String encoded = Base64Utility.encode( bytes ); return encoded; } // Returns base64 representation of specified byte array. // public static String encode( byte[] id ) { char[] cd = encodeChunk( id, 0, id.length ); return new String( cd, 0, cd.length ); } // Returns base64 representation of specified byte array. // public static char[] encodeChunk( byte[] id, int o, int l ) { if ( l <= 0 ) { return null; } char[] out; // If not a multiple of 3 octets then a final padded 4 char // slot is needed. // if ( ( l - o ) % 3 == 0 ) { out = new char[l / 3 * 4]; } else { out = new char[l / 3 * 4 + 4]; } int rindex = o; int windex = 0; int rest = l - o; while ( rest >= 3 ) { int i = ( ( id[rindex] & 0xff ) << 16 ) + ( ( id[rindex + 1] & 0xff ) << 8 ) + ( id[rindex + 2] & 0xff ); out[windex++] = BCS[i >> 18]; out[windex++] = BCS[( i >> 12 ) & 0x3f]; out[windex++] = BCS[( i >> 6 ) & 0x3f]; out[windex++] = BCS[i & 0x3f]; rindex += 3; rest -= 3; } if ( rest == 1 ) { int i = id[rindex] & 0xff; out[windex++] = BCS[i >> 2]; out[windex++] = BCS[( i << 4 ) & 0x3f]; out[windex++] = PAD; out[windex++] = PAD; } else if ( rest == 2 ) { int i = ( ( id[rindex] & 0xff ) << 8 ) + ( id[rindex + 1] & 0xff ); out[windex++] = BCS[i >> 10]; out[windex++] = BCS[( i >> 4 ) & 0x3f]; out[windex++] = BCS[( i << 2 ) & 0x3f]; out[windex++] = PAD; } return out; } // // Outputs base64 representation of the specified byte array // to a byte stream. // public static void encodeChunk( byte[] id, int o, int l, OutputStream ostream ) throws Base64Exception { try { ostream.write( new String( encodeChunk( id, o, l ) ).getBytes() ); } catch ( IOException e ) { throw new Base64Exception( "encode() to outstream raised IOException", e ); } } // Outputs base64 representation of the specified byte // array to a character stream. // public static void encode( byte[] id, int o, int l, Writer writer ) throws Base64Exception { try { writer.write( encodeChunk( id, o, l ) ); } catch ( IOException e ) { throw new Base64Exception( "encode() to Writer raised exception", e ); } } // ---- Private static methods -------------------------------------- /** * The process routine processes an atomic base64 unit of encoding (encodeme) into its native encoding. * This class is used by decode routines to do the grunt work of decoding base64 encoded information * * @param ib Input character buffer of encoded bytes * @param ob Output byte buffer of decoded bytes * @param p Pointer to the encodeme of interest * @return The decoded encodeme * @exception Base64Exception Thrown is processing fails due to formatting exceptions in the encoded data */ private static int processEncodeme( char[] ib, byte[] ob, int p ) throws Base64Exception { int spad = PAD_SIZE8; if ( ib[3] == PAD ) { spad = PAD_SIZE4; } if ( ib[2] == PAD ) { spad = PAD_SIZE0; } int b0 = BDT[ib[0]]; int b1 = BDT[ib[1]]; int b2 = BDT[ib[2]]; int b3 = BDT[ib[3]]; switch ( spad ) { case PAD_SIZE0: ob[p] = (byte) ( b0 << 2 & 0xfc | b1 >> 4 & 0x3 ); return PAD_SIZE0; case PAD_SIZE4: ob[p++] = (byte) ( b0 << 2 & 0xfc | b1 >> 4 & 0x3 ); ob[p] = (byte) ( b1 << 4 & 0xf0 | b2 >> 2 & 0xf ); return PAD_SIZE4; case PAD_SIZE8: ob[p++] = (byte) ( b0 << 2 & 0xfc | b1 >> 4 & 0x3 ); ob[p++] = (byte) ( b1 << 4 & 0xf0 | b2 >> 2 & 0xf ); ob[p] = (byte) ( b2 << 6 & 0xc0 | b3 & 0x3f ); return PAD_SIZE8; default: // We should never get here throw new IllegalStateException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy