Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 955 → Rev 956

/sun/backpath/trunk/src/ak/backpath/Base64.java
0,0 → 1,243
package ak.backpath;
 
/**
* Special version for packpath (ak) -
* symbols +/ replaced with .* to produce correct URL-parts;
* no end padding, most methods are deleted.
*
* Original author Robert Harder (rob@iharder.net)
*/
class Base64
{
private final static byte[] ALPHABET =
{
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
(byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
(byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
(byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
(byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
(byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
(byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'.', (byte)'*'
};
 
/**
* Translates a Base64 value to either its 6-bit reconstruction value
* or a negative number indicating some other meaning.
**/
private final static byte[] DECODABET =
{
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,63,-9,-9,-9,62,-9,
52,53,54,55,56,57,58,59,60,61,-9,-9,-9,-9,-9,-9,
-9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,-9,-9,-9,-9,-9,
-9,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,-9,-9,-9,-9,-9
};
 
private Base64(){}
 
private static byte[] encode3to4(byte[] destination, byte[] source, int numSigBytes)
{
// 1 2 3
// 01234567890123456789012345678901 Bit position
// --------000000001111111122222222 Array position from threeBytes
// --------| || || || | Six bit groups to index ALPHABET
// >>18 >>12 >> 6 >> 0 Right shift necessary
// 0x3f 0x3f 0x3f Additional AND
 
// Create buffer with zero-padding if there are only one or two
// significant bytes passed in the array.
// We have to shift left 24 in order to flush out the 1's that appear
// when Java treats a value as negative that is cast from a byte to an int.
int inBuff = ( numSigBytes > 0 ? ((source[ 0 ] << 24) >>> 8) : 0 )
| ( numSigBytes > 1 ? ((source[ 1 ] << 24) >>> 16) : 0 )
| ( numSigBytes > 2 ? ((source[ 2 ] << 24) >>> 24) : 0 );
 
switch( numSigBytes )
{
case 3:
destination[ 0 ] = ALPHABET[ (inBuff >>> 18) ];
destination[ 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
destination[ 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
destination[ 3 ] = ALPHABET[ (inBuff ) & 0x3f ];
return destination;
 
case 2:
destination[ 0 ] = ALPHABET[ (inBuff >>> 18) ];
destination[ 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
destination[ 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ];
return destination;
 
case 1:
destination[ 0 ] = ALPHABET[ (inBuff >>> 18) ];
destination[ 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ];
return destination;
 
default:
return destination;
}
}
 
private static int decode4to3( byte[] source, int srcOffset, byte[] destination, int destOffset, int length )
{
// Example: Dk==
if( length == 2 )
{
int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
| ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 );
 
destination[ destOffset ] = (byte)( outBuff >>> 16 );
return 1;
}
 
// Example: DkL=
else if( length == 3 )
{
int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
| ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
| ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 );
 
destination[ destOffset ] = (byte)( outBuff >>> 16 );
destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 );
return 2;
}
 
// Example: DkLE
else
{
try{
int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 )
| ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 )
| ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6)
| ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) );
 
 
destination[ destOffset ] = (byte)( outBuff >> 16 );
destination[ destOffset + 1 ] = (byte)( outBuff >> 8 );
destination[ destOffset + 2 ] = (byte)( outBuff );
 
return 3;
}catch( Exception e){
return -1;
}
}
}
 
static class InputStream extends java.io.FilterInputStream
{
private int position = -1;
private byte[] buffer = new byte[ 3 ];
private byte[] b4 = new byte[4];
private int numSigBytes;
 
public InputStream( java.io.InputStream in)
{
super( in );
}
 
public int read() throws java.io.IOException
{
// Do we need to get data?
if( position < 0 )
{
int i = 0;
for( ; i < 4; i++ )
{
int b = in.read();
if( b < 0 ) break;
b4[i] = (byte)b;
}
 
if( i == 0 ) return -1;
 
numSigBytes = decode4to3( b4, 0, buffer, 0, i );
position = 0;
}
 
// Got data?
if( position >= 0 )
{
if( position >= numSigBytes )
return -1;
 
int b = buffer[ position++ ];
 
if( position >= 3 )
position = -1;
 
return b & 0xFF;
}
else
{
throw new java.io.IOException( "Error in Base64 code reading stream." );
}
}
 
public int read( byte[] dest, int off, int len ) throws java.io.IOException
{
int i;
int b;
for( i = 0; i < len; i++ )
{
b = read();
 
if( b >= 0 )
dest[off + i] = (byte)b;
else if( i == 0 )
return -1;
else
break;
}
return i;
}
 
}
 
static class OutputStream extends java.io.FilterOutputStream
{
private int position = 0;
private byte[] buffer = new byte[ 3 ];
private byte[] b4 = new byte[4];
 
public OutputStream( java.io.OutputStream out)
{
super( out );
}
 
public void write(int theByte) throws java.io.IOException
{
buffer[ position++ ] = (byte)theByte;
if( position >= 3 ) // Enough to encode.
{
out.write( encode3to4( b4, buffer, 3 ) );
position = 0;
}
}
 
public void write( byte[] theBytes, int off, int len ) throws java.io.IOException
{
for( int i = 0; i < len; i++ )
{
write( theBytes[ off + i ] );
}
}
 
public void close() throws java.io.IOException
{
if( position > 0 )
{
out.write( encode3to4( b4, buffer, position ), 0, position+1 );
position = 0;
}
 
super.close();
buffer = null;
out = null;
}
}
}