#include <stdlib.h>
#include <string.h>
static unsigned char table [] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9', '+', '/' };
unsigned char* xar_to_base64(const unsigned char* input, size_t len)
{
unsigned char b6;
unsigned char count = 0;
int i=0;
unsigned char* output;
int outsize = (((float)len)*4/3)+5;
output = malloc(outsize);
if( !output )
return NULL;
while(1) {
if( i >= len ) {
output[count++] = '\n';
output[count++] = '\0';
return output;
}
b6 = input[i];
b6 >>= 2;
output[count++] = table[b6];
b6 = input[i++];
b6 &= 0x03;
b6 <<= 4;
if( i >= len ) {
output[count++] = table[b6];
output[count++] = '=';
output[count++] = '=';
output[count++] = '\n';
output[count++] = '\0';
return output;
}
b6 |= input[i] >> 4;
output[count++] = table[b6];
b6 = input[i++] & 0x0F;
b6 <<= 2;
if( i >= len ) {
output[count++] = table[b6];
output[count++] = '=';
output[count++] = '\n';
output[count++] = '\0';
return output;
}
b6 |= input[i] >> 6;
output[count++] = table[b6];
b6 = input[i++] & 0x3F;
output[count++] = table[b6];
}
}
#ifdef _BTEST_
int main(int argc, char* argv[]) {
unsigned char* enc = benc(argv[1], strlen(argv[1]));
printf("%s", enc);
printf("%s\n", bdec(enc, strlen(enc)));
}
#endif
typedef enum _B64CommandCodes {
B64_NullTerminator = -3,
B64_PaddingCharacter = -2,
B64_IgnorableCharacter = -1
} B64CommandCodes;
static char b64revtb[256] = {
-3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
typedef enum _B64CodecErrorCodes {
B64_noError = 0,
B64_decodeError = 1,
B64_bufferOverrun = 2
} B64CodecErrorCodes;
#define B64_INPUT_BLOCK_OFFSET ((inputIndex - 1 - ignorableCharacterCount) % 4)
static unsigned int raw_base64_decode(
const unsigned char *input, unsigned char *output, size_t inLengthToDecode,
size_t *outputDecodedLength)
{
int currentBase64Value;
unsigned int inputIndex = 0;
unsigned int ignorableCharacterCount = 0;
unsigned int i;
unsigned char decodedBuffer[3];
unsigned char currentInputBlockPaddingCharacterCount = 0;
size_t *decodedCharacterCount;
size_t dummyValue;
if (outputDecodedLength == NULL) {
decodedCharacterCount = &dummyValue;
} else {
decodedCharacterCount = outputDecodedLength;
}
*decodedCharacterCount = 0;
while ( (inputIndex <= inLengthToDecode) &&
(currentInputBlockPaddingCharacterCount == 0) )
{
currentBase64Value = b64revtb[input[inputIndex]];
inputIndex++;
switch (currentBase64Value) {
case B64_NullTerminator:
if (B64_INPUT_BLOCK_OFFSET != 0) return B64_decodeError;
if (currentInputBlockPaddingCharacterCount > 0) {
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
}
return B64_noError;
case B64_PaddingCharacter:
if (B64_INPUT_BLOCK_OFFSET < 2) {
return B64_decodeError;
} else if (B64_INPUT_BLOCK_OFFSET == 2) {
if (input[inputIndex] != '=') return B64_decodeError;
decodedBuffer[2] = 0;
currentInputBlockPaddingCharacterCount = 2;
break;
} else {
currentInputBlockPaddingCharacterCount = 1;
break;
}
return B64_noError;
case B64_IgnorableCharacter:
ignorableCharacterCount++;
break;
default:
switch (B64_INPUT_BLOCK_OFFSET) {
case 0:
decodedBuffer[0] = currentBase64Value << 2;
break;
case 1:
decodedBuffer[0] |= (currentBase64Value >> 4);
decodedBuffer[1] = currentBase64Value << 4;
break;
case 2:
decodedBuffer[1] |= (currentBase64Value >> 2);
decodedBuffer[2] = currentBase64Value << 6;
break;
case 3:
decodedBuffer[2] |= currentBase64Value;
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
break;
}
break;
}
}
if (inputIndex > inLengthToDecode) return B64_bufferOverrun;
for (i = 0; i < (3 - currentInputBlockPaddingCharacterCount); i++) {
*output++ = decodedBuffer[i];
(*decodedCharacterCount)++;
}
return B64_noError;
}
unsigned char* xar_from_base64(const unsigned char* input, size_t inputLength, size_t *outputLength)
{
int err;
unsigned char *output;
output = malloc(3 * (inputLength / 4 + 1));
if (output == NULL) return NULL;
err = raw_base64_decode(input, output, inputLength, outputLength);
if (err != B64_noError) {
free(output);
return NULL;
}
return output;
}