protected final static byte[] decodeInternal(byte[] base64Data) throws Base64DecodingException {
// remove white spaces
int len = removeWhiteSpace(base64Data);
if (len%FOURBYTE != 0) {
throw new Base64DecodingException("decoding.divisible.four");
//should be divisible by four
}
int numberQuadruple = (len/FOURBYTE );
if (numberQuadruple == 0)
return new byte[0];
byte decodedData[] = null;
byte b1=0,b2=0,b3=0, b4=0;
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
//decodedData = new byte[ (numberQuadruple)*3];
dataIndex=(numberQuadruple-1)*4;
encodedIndex=(numberQuadruple-1)*3;
//first last bits.
b1 = base64Alphabet[base64Data[dataIndex++]];
b2 = base64Alphabet[base64Data[dataIndex++]];
if ((b1==-1) || (b2==-1)) {
throw new Base64DecodingException("decoding.general");//if found "no data" just return null
}
byte d3,d4;
b3 = base64Alphabet[d3=base64Data[dataIndex++]];
b4 = base64Alphabet[d4=base64Data[dataIndex++]];
if ((b3==-1 ) || (b4==-1) ) {
//Check if they are PAD characters
if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad]
if ((b2 & 0xf) != 0)//last 4 bits should be zero
throw new Base64DecodingException("decoding.general");
decodedData = new byte[ encodedIndex + 1 ];
decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
} else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad]
if ((b3 & 0x3 ) != 0)//last 2 bits should be zero
throw new Base64DecodingException("decoding.general");
decodedData = new byte[ encodedIndex + 2 ];
decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 );
decodedData[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
} else {
throw new Base64DecodingException("decoding.general");//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
}
} else {
//No PAD e.g 3cQl
decodedData = new byte[encodedIndex+3];
decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );
}
encodedIndex=0;
dataIndex=0;
//the begin
for (i=numberQuadruple-1; i>0; i--) {
b1 = base64Alphabet[base64Data[dataIndex++]];
b2 = base64Alphabet[base64Data[dataIndex++]];
b3 = base64Alphabet[base64Data[dataIndex++]];
b4 = base64Alphabet[base64Data[dataIndex++]];
if ( (b1==-1) ||
(b2==-1) ||
(b3==-1) ||
(b4==-1) ) {
throw new Base64DecodingException("decoding.general");//if found "no data" just return null
}
decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ;
decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
decodedData[encodedIndex++] = (byte)( b3<<6 | b4 );