Pages

Tuesday, 9 November 2021

BASE64 C source code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static char map[] = {
'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',
'+','/',
};

// BASE64 code
static char code(int i)
{
if(i<0 || i>63){
return '=';
}
return map[i];
}

static int code_point(char code)
{
int i;
if(code == '=') return 0;
for(i=0; i<64; i++){
if(code == map[i]){
return i;
}
}
return -1;
}

// return 1 for big endian, while -1 for little endian
// tranlate 3 bytes to 4 base64 bytes
static void encode_block(unsigned char in[3], char out[4])
{
int codePoint[4];
codePoint[0] = in[0] >> 2;
codePoint[1] = ((in[0] & 0x03) << 4) | (in[1]>>4);
codePoint[2] = ((in[1] & 0x0F) << 2) | (in[2]>>6);
codePoint[3] = in[2] & 0x3F;
int i=0;
for(i=0; i<4; i++){
out[i] = code(codePoint[i]);
}
}

// return the bytes of decoded data
static int decode_block(char in[4], unsigned char out[3])
{
int n = 3;
if(in[3] == '=') {
n--;
}
if(in[2]== '=') {
n--;
}

int i;
char cp[4]; // code point
for(i=0; i<4;i++){
cp[i] = code_point(in[i]);
}

out[0] = (cp[0]<<2) | (cp[1]>>4);
out[1] = (cp[1]<<4) | (cp[2]>>2);
out[2] = (cp[2]<<6) | cp[3];
return n;
}

// return the number of bytes needed to hold the base64 encoded result
int base64_size(int input_size)
{
return 4*(input_size + (3-input_size%3)%3 )/3;
}

// main interface
void base64(char* bytes, int size,  char* encoded)
{
int i=0;
for(i=0; i<size/3; i++){
encode_block(bytes+i*3, encoded+i*4);
}
// padding if the size is not multiple times of 3
if(size%3 == 1){
unsigned char d[4]={bytes[i*3], 0, 0};
encode_block(d, encoded+i*4);
encoded[i*4 + 2] = '=';
encoded[i*4 + 3] = '=';
}else if(size%3==2){
unsigned char d[4]={bytes[i*3], bytes[i*3+1], 0};
encode_block(d, encoded+i*4);
encoded[i*4 + 3] = '=';
}
}

void  b64_file(FILE* infile, FILE* outfile)
{
unsigned char buf[3];
char out[4];
if(infile == NULL){
infile = stdin;
}
if(outfile == NULL){
outfile = stdout;
}
while(feof(infile) == 0){
int n = fread(buf, 1, 3, infile);
if(n>0){
base64(buf, n, out);
fwrite(out, 1, 4, outfile) ;
}
}
}

void b64_decode_file(FILE* infile, FILE* outfile)
{
unsigned char buf[4];
char out[3];
if(infile == NULL){
infile = stdin;
}
if(outfile == NULL){
outfile = stdout;
}
while(feof(infile) == 0){
int n = fread(buf, 1, 4, infile);
if(n==4){
int len = decode_block(buf, out);
fwrite(out, 1, len, outfile) ;
}else{
exit(1);
}
}
}
void usage()
{
printf("Examples:\n");
printf("\tb64 -h\n");
printf("\techo 'ABC' | b64\n");
printf("\techo 'ABC' | b64 -d\n");
}

int main(int argc, char** argv)
{
if(argc>1){
   if(!strcmp("-d",argv[1])){
b64_decode_file(NULL, NULL);
   }else{
  usage();
   }
}else{
b64_file(NULL, NULL);
}
return 0;
}

No comments:

Post a Comment