From 8b12c22369300992d27d9e42f59f363c969a5471 Mon Sep 17 00:00:00 2001 From: Allanis Date: Thu, 23 May 2013 17:01:08 +0100 Subject: [PATCH] [Add] Start of base64 encode/decode routines. Not quite working yet. --- src/base64.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/base64.h | 5 +++ 2 files changed, 110 insertions(+) create mode 100644 src/base64.c create mode 100644 src/base64.h diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..e039db5 --- /dev/null +++ b/src/base64.c @@ -0,0 +1,105 @@ +#include +#include +#include + +// Encode table. +static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu \ + vwxyz0123456789+/"; +// Decode table. +static const char cd64[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW \ + $$$$$$XYZ[\\]^_'abcdefghijklmnopq"; + +// Encode src of sz length storing the new length in len. +char* base64_encode(int* len, char* src, size_t sz) { + char* r; + size_t i, c; + uint32_t n; + uint8_t ch[4], pad; + + // Create r. + c = sz * 4 / 3 + sz % 3; + c += c / 76; + (*len) = c; + r = malloc((*len) * sizeof(char)); + + // Setup padding. + pad = sz % 3; + + // Time to do the bulk of the work. + i = 0; + for(c = 0; c < sz; c += 3) { + // Specification wants newline after every 76 characters. + if((c > 0) && ((c / 3 * 4) % 76 == 0)) + r[i++] = '\n'; + + // n is 24 bits. + n = (src[c] << 16) + + (c+1> 18) & 63; + ch[1] = (n >> 12) & 63; + ch[2] = (n >> 6) & 63; + ch[3] = n & 63; + + r[i++] = cb64[ch[0]]; + r[i++] = cb64[ch[1]]; + r[i++] = cb64[ch[2]]; + r[i++] = cb64[ch[3]]; + } + + for(c = 0; c < pad; c++) + r[i++] = '='; + r[i] = '\0'; + + return r; +} + +inline int dec_valid(char inp) { + if((inp < 43) || (inp > 122) || cd64[(int)inp-43] == '$') + return 0; + return 1; +} + +inline char dec_ch(char inp) { + return cd64[(int)inp-43] - 61; +} + +char* base64_decode(int* len, char* src, size_t sz) { + char* r, *dat; + size_t c, i, j; + uint32_t n; + + // Allocate r. + c = sz * 3 / 4; + r = malloc(c * sizeof(char)); + + // Create a clean version of the text. + dat = malloc(sz * sizeof(char)); + j = 0; + for(i = 0; i < sz; i++) { + if(src[i] == '=') + dat[j++] = '\0'; + else if(dec_valid(src[i])) + dat[j++] = src[i]; + } + + // Fill r. + i = 0; + for(c = 0; c < j; c += 4) { + n = dec_ch(dat[c+0]) << 18; + n = dec_ch(dat[c+1]) << 12; + n = dec_ch(dat[c+2]) << 6; + n = dec_ch(dat[c+3]) << 0; + + r[i++] = (n >> 16) & 0xFF; + r[i++] = (n >> 8) & 0xFF; + r[i++] = (n >> 0) & 0xFF; + + } + + (*len) = i; + return r; +} + diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..44c7747 --- /dev/null +++ b/src/base64.h @@ -0,0 +1,5 @@ +#pragma once + +char* base64_encode(int* len, char* src, size_t sz); +char* base64_decode(int* len, char* src, size_t sz); +