package com.sap.runlet.operationaltransformation.test.util;
/**
* Implements a BASE64 encoder and decoder. Class <code>Base64</code> provides
* static encoding- and decoding-methods for describing binary data through
* printable characters. The implementation is compliant to RFC 1521.
*
* @copyright @version $Revision: #1 $.
* @author Stefan Kusterer, Last modified by $Author: d038253 $, Change list
* $Change: 156641 $.
*/
public class Base64 {
protected static final char[] CHAR_LOOKUP_ARRAY = {
/* 0 */'A', /* 1 */'B', /* 2 */'C', /* 3 */'D',
/* 4 */'E', /* 5 */'F', /* 6 */'G', /* 7 */'H',
/* 8 */'I', /* 9 */'J', /* 10 */'K', /* 11 */'L',
/* 12 */'M', /* 13 */'N', /* 14 */'O', /* 15 */'P',
/* 16 */'Q', /* 17 */'R', /* 18 */'S', /* 19 */'T',
/* 20 */'U', /* 21 */'V', /* 22 */'W', /* 23 */'X',
/* 24 */'Y', /* 25 */'Z',
/* 26 */'a', /* 27 */'b', /* 28 */'c', /* 29 */'d',
/* 30 */'e', /* 31 */'f', /* 32 */'g', /* 33 */'h',
/* 34 */'i', /* 35 */'j', /* 36 */'k', /* 37 */'l',
/* 38 */'m', /* 39 */'n', /* 40 */'o', /* 41 */'p',
/* 42 */'q', /* 43 */'r', /* 44 */'s', /* 45 */'t',
/* 46 */'u', /* 47 */'v', /* 48 */'w', /* 49 */'x',
/* 50 */'y', /* 51 */'z',
/* 52 */'0', /* 53 */'1', /* 54 */'2', /* 55 */'3',
/* 56 */'4', /* 57 */'5', /* 58 */'6', /* 59 */'7',
/* 60 */'8', /* 61 */'9',
/* 62 */'+', /* 63 */'/',
/* pad */'=' };
protected static final int[] VALUE_LOOKUP_ARRAY = new int[128];
static // Initializer
{
for ( char i = 0; i < VALUE_LOOKUP_ARRAY.length; i++ ) {
if ( CHAR_LOOKUP_ARRAY[0] <= i && i <= CHAR_LOOKUP_ARRAY[25] ) {
VALUE_LOOKUP_ARRAY[i] = ( i - CHAR_LOOKUP_ARRAY[0] );
} else if ( CHAR_LOOKUP_ARRAY[26] <= i && i <= CHAR_LOOKUP_ARRAY[51] ) {
VALUE_LOOKUP_ARRAY[i] = ( i - CHAR_LOOKUP_ARRAY[26] ) + 26;
} else if ( CHAR_LOOKUP_ARRAY[52] <= i && i <= CHAR_LOOKUP_ARRAY[61] ) {
VALUE_LOOKUP_ARRAY[i] = ( i - CHAR_LOOKUP_ARRAY[52] ) + 52;
} else if ( i == CHAR_LOOKUP_ARRAY[62] ) {
VALUE_LOOKUP_ARRAY[i] = 62;
} else if ( i == CHAR_LOOKUP_ARRAY[63] ) {
VALUE_LOOKUP_ARRAY[i] = 63;
} else if ( i == CHAR_LOOKUP_ARRAY[64] ) {
VALUE_LOOKUP_ARRAY[i] = -1;
} else {
VALUE_LOOKUP_ARRAY[i] = -2;
}
}
}
// do not allow to instantiate this class
protected Base64( ) {
// only static methods
}
public final static byte[] decode(String in) {
char[] c = new char[in.length()];
in.getChars(0, in.length(), c, 0);
return decode(c);
}
/**
* <code>decode</code> a given array of characters.
*
* @param in The input array of characters
* @return The array of bytes
*/
public final static byte[] decode( char[] in ) {
if ( in == null || in.length == 0 ) {
return new byte[0];
}
int index_in;
int index_out;
int helper_1 = 0;
int helper_2 = 0;
int mod = 0;
int in_length = in.length;
int chr;
// Determine number of used characters: Ignore linebreaks etc. and count
// trailing =-signes
for ( index_in = 0; index_in < in.length; index_in++ ) {
chr = in[index_in];
if ( chr >= 128 ) {
in_length--;
} else if (VALUE_LOOKUP_ARRAY[chr] < 0) {
in_length--;
}
}
// Allocate out-buffer
byte out[] = new byte[( in_length >>> 2 ) * 3 + ( ( in_length & 0x03 ) > 0 ? ( in_length & 0x03 ) - 1 : 0 )];
// Do the real decoding
for ( index_in = 0, index_out = 0; index_in < in.length && index_out < out.length; index_in++ ) {
chr = in[index_in];
if ( chr > 127 || VALUE_LOOKUP_ARRAY[chr] == -2 ) {
continue;
}
helper_1 = helper_2;
helper_2 = VALUE_LOOKUP_ARRAY[chr] > 0 ? VALUE_LOOKUP_ARRAY[chr] : 0;
switch ( mod ) {
case 0:
// no operation
break;
case 1:
out[index_out++] = (byte) ( ( helper_1 << 2 ) & 0xFC | ( helper_2 >>> 4 ) & 0x03 );
break;
case 2:
out[index_out++] = (byte) ( ( helper_1 << 4 ) & 0xF0 | ( helper_2 >>> 2 ) & 0x0F );
break;
case 3:
out[index_out++] = (byte) ( ( helper_1 << 6 ) & 0xC0 | helper_2 & 0x3F );
break;
}
mod = ( mod < 3 ? mod + 1 : 0 );
}
return out;
}
/**
* Add a charcter to an array of chars and insert linebreas if necessary
*/
private final static int writeToCharArray( char[] out, int idx, char chr ) {
out[idx++] = chr;
return idx;
}
/**
* <code>encode</code> a given array.
*
* @param in the input array of binary data
* @return The array of characters
*/
public final static String encode( byte[] in ) {
if ( in == null ) {
return null;
}
int index_in;
int index_out;
char chr;
// Allocate buffer for result: Consider chars for trailing =-signs
// and linebreaks.
char out[] = new char[( ( ( in.length + 2 ) / 3 ) << 2 )];
for ( index_in = 0, index_out = 0; index_in < in.length - 2; index_in += 3 ) {
// compute first byte: highest six bits of first byte
chr = CHAR_LOOKUP_ARRAY[( in[index_in] >>> 2 ) & 0x3F];
index_out = writeToCharArray( out, index_out, chr );
// compute second byte: lowest two bits of first byte
chr = CHAR_LOOKUP_ARRAY[( in[index_in] << 4 ) & 0x30 |
// and highest four bits of second byte
( in[index_in + 1] >>> 4 ) & 0x0F];
index_out = writeToCharArray( out, index_out, chr );
// compute third byte: lowest four bits of second byte
chr = CHAR_LOOKUP_ARRAY[( in[index_in + 1] << 2 ) & 0x3C |
// and higest two bits of third byte
( in[index_in + 2] >>> 6 ) & 0x03];
index_out = writeToCharArray( out, index_out, chr );
// compute fourth byte: lowest six bits of third byte
chr = CHAR_LOOKUP_ARRAY[in[index_in + 2] & 0x3F];
index_out = writeToCharArray( out, index_out, chr );
}
// take care of the last bytes (one or two)
if ( index_in < in.length ) {
chr = CHAR_LOOKUP_ARRAY[( in[index_in] >>> 2 ) & 0x3F];
index_out = writeToCharArray( out, index_out, chr );
if ( index_in < in.length - 1 ) {
// there are two remaining bytes
chr = CHAR_LOOKUP_ARRAY[( in[index_in] << 4 ) & 0x30 | ( in[index_in + 1] >>> 4 ) & 0x0F];
index_out = writeToCharArray( out, index_out, chr );
chr = CHAR_LOOKUP_ARRAY[( in[index_in + 1] << 2 ) & 0x3F];
index_out = writeToCharArray( out, index_out, chr );
} else {
// there is only one remaining byte
chr = CHAR_LOOKUP_ARRAY[( in[index_in] << 4 ) & 0x30];
index_out = writeToCharArray( out, index_out, chr );
}
}
// add padding =-signs if required
while ( index_out < out.length ) {
index_out = writeToCharArray( out, index_out, CHAR_LOOKUP_ARRAY[64] );
}
return new String(out);
}
}