blob: 2779d6e3d965ee505441bc0a00f30ac5570322ba [file] [log] [blame]
/*
* Copyright 2009 Alin Dreghiciu.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zest.api.util;
/**
* Base64Encoder.
*/
public final class Base64Encoder
{
/**
* Utility class. ment to be used via static methods.
*/
private Base64Encoder()
{
// utility class
}
/**
* Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
*
* @param s String to encode.
*
* @return encoded string.
*/
public static String encode( String s, boolean includePadding )
{
byte[] sBytes = s.getBytes();
sBytes = encode( sBytes, includePadding );
s = new String( sBytes );
return s;
}
/**
* Decodes a base 64 String into a String.
*
* @param s String to decode.
*
* @return encoded string.
*
* @throws java.lang.IllegalArgumentException
* _ If the given byte array was not valid base64 encoding.
*/
public static String decode( String s )
throws IllegalArgumentException
{
s = s.replaceAll( "\n", "" );
s = s.replaceAll( "\r", "" );
byte[] sBytes = s.getBytes();
sBytes = decode( sBytes );
s = new String( sBytes );
return s;
}
private static final byte[] ALPHASET =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".getBytes();
private static final int I6O2 = 255 - 3;
private static final int O6I2 = 3;
private static final int I4O4 = 255 - 15;
private static final int O4I4 = 15;
private static final int I2O6 = 255 - 63;
private static final int O2I6 = 63;
/**
* Encodes a byte array into a base 64 byte array.
*
* @param dData byte array to encode.
*
* @return encoded byte array.
*/
public static byte[] encode( byte[] dData, boolean includePadding )
{
if( dData == null )
{
throw new IllegalArgumentException( "Cannot encode null" );
}
byte[] eData = new byte[ ( ( dData.length + 2 ) / 3 ) * 4 ];
int eIndex = 0;
for( int i = 0; i < dData.length; i += 3 )
{
int d1;
int d2 = 0;
int d3 = 0;
int e1;
int e2;
int e3;
int e4;
int pad = 0;
d1 = dData[ i ];
if( ( i + 1 ) < dData.length )
{
d2 = dData[ i + 1 ];
if( ( i + 2 ) < dData.length )
{
d3 = dData[ i + 2 ];
}
else
{
pad = 1;
}
}
else
{
pad = 2;
}
e1 = ALPHASET[ ( d1 & I6O2 ) >> 2 ];
e2 = ALPHASET[ ( d1 & O6I2 ) << 4 | ( d2 & I4O4 ) >> 4 ];
e3 = ALPHASET[ ( d2 & O4I4 ) << 2 | ( d3 & I2O6 ) >> 6 ];
e4 = ALPHASET[ ( d3 & O2I6 ) ];
eData[ eIndex++ ] = (byte) e1;
eData[ eIndex++ ] = (byte) e2;
eData[ eIndex++ ] = ( pad < 2 ) ? (byte) e3 : (byte) '=';
eData[ eIndex++ ] = ( pad < 1 ) ? (byte) e4 : (byte) '=';
if( pad > 0 && !includePadding )
{
byte[] neweData = new byte[ eData.length - pad ];
System.arraycopy( eData, 0, neweData, 0, eIndex - pad );
eData = neweData;
}
}
return eData;
}
private final static int[] CODES = new int[ 256 ];
static
{
for( int i = 0; i < CODES.length; i++ )
{
CODES[ i ] = 64;
}
for( int i = 0; i < ALPHASET.length; i++ )
{
CODES[ ALPHASET[ i ] ] = i;
}
}
/**
* Decodes a base64 byte array into a byte array.
* <p>
*
* @param eData byte array to decode.
*
* @return decoded byte array.
*
* @throws java.lang.IllegalArgumentException
* thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
*/
public static byte[] decode( byte[] eData )
{
if( eData == null )
{
throw new IllegalArgumentException( "Cannot decode null" );
}
byte[] cleanEData = eData.clone();
int cleanELength = 0;
for( byte anEData : eData )
{
if( anEData < 256 && CODES[ anEData ] < 64 )
{
cleanEData[ cleanELength++ ] = anEData;
}
}
int dLength = ( cleanELength / 4 ) * 3;
switch( cleanELength % 4 )
{
case 3:
dLength += 2;
break;
case 2:
dLength++;
break;
}
byte[] dData = new byte[ dLength ];
int dIndex = 0;
for( int i = 0; i < eData.length; i += 4 )
{
if( ( i + 3 ) > eData.length )
{
throw new IllegalArgumentException(
"byte array is not a valid base64 encoding"
);
}
int e1 = CODES[ cleanEData[ i ] ];
int e2 = CODES[ cleanEData[ i + 1 ] ];
int e3 = CODES[ cleanEData[ i + 2 ] ];
int e4 = CODES[ cleanEData[ i + 3 ] ];
dData[ dIndex++ ] = (byte) ( ( e1 << 2 ) | ( e2 >> 4 ) );
if( dIndex < dData.length )
{
dData[ dIndex++ ] = (byte) ( ( e2 << 4 ) | ( e3 >> 2 ) );
}
if( dIndex < dData.length )
{
dData[ dIndex++ ] = (byte) ( ( e3 << 6 ) | ( e4 ) );
}
}
return dData;
}
}