if (len == -1) {
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)) {
//if found "no data" just return null
throw new Base64DecodingException("decoding.general");
}
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 {
//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
throw new Base64DecodingException("decoding.general");
}
} 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)) {
//if found "no data" just return null
throw new Base64DecodingException("decoding.general");
}
decodedData[encodedIndex++] = (byte)(b1 << 2 | b2 >> 4) ;
decodedData[encodedIndex++] = (byte)(((b2 & 0xf) << 4) |((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte)(b3 << 6 | b4 );