diff --git a/src/addagent/b64.c b/src/addagent/b64.c index de5d03304..e5d91acd7 100644 --- a/src/addagent/b64.c +++ b/src/addagent/b64.c @@ -24,202 +24,102 @@ #include #include #include - -#define TRUE 1 -#define FALSE 0 +#include // For using bool instead of int for boolean functions /* Prototypes */ -static int is_base64(char c); -static char encode(unsigned char u); -static unsigned char decode(char c); +static bool is_base64(char c); +static char encode_char(unsigned char u); +static unsigned char decode_char(char c); -/* Global variables */ +/* Global functions */ char *decode_base64(const char *src); -char *encode_base64(int size, char *src); - - -/* Base64 encode and return size data in 'src'. The caller must free the - * returned string. - * Returns encoded string otherwise NULL - */ -char *encode_base64(int size, char *src) -{ - int i; - char *out, *p; - - if (!src) { - return NULL; - } - - if (!size) { - size = strlen((char *)src); - } - - out = (char *)calloc(sizeof(char), size * 4 / 3 + 4); - if (!out) { - return NULL; - } - - p = out; +char *encode_base64(int size, const char *src); + +/* Encode a character into Base64 */ +static char encode_char(unsigned char u) { + if (u < 26) return 'A' + u; + if (u < 52) return 'a' + (u - 26); + if (u < 62) return '0' + (u - 52); + return (u == 62) ? '+' : '/'; +} - for (i = 0; i < size; i += 3) { - unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0; +/* Decode a Base64 character */ +static unsigned char decode_char(char c) { + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + return (c == '+') ? 62 : 63; +} - b1 = src[i]; +/* Check if a character is a valid Base64 character */ +static bool is_base64(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || (c == '+') || + (c == '/') || (c == '='); +} - if (i + 1 < size) { - b2 = src[i + 1]; - } +/* Encode data to Base64 */ +char *encode_base64(int size, const char *src) { + if (!src) return NULL; - if (i + 2 < size) { - b3 = src[i + 2]; - } + if (size == 0) size = strlen(src); - b4 = b1 >> 2; - b5 = ((b1 & 0x3) << 4) | (b2 >> 4); - b6 = ((b2 & 0xf) << 2) | (b3 >> 6); - b7 = b3 & 0x3f; + int out_size = (size + 2) / 3 * 4 + 1; // +1 for null terminator + char *out = (char *)calloc(out_size, sizeof(char)); + if (!out) return NULL; - *p++ = encode(b4); - *p++ = encode(b5); + char *p = out; - if (i + 1 < size) { - *p++ = encode(b6); - } else { - *p++ = '='; - } + for (int i = 0; i < size; i += 3) { + unsigned char b1 = src[i]; + unsigned char b2 = (i + 1 < size) ? src[i + 1] : 0; + unsigned char b3 = (i + 2 < size) ? src[i + 2] : 0; - if (i + 2 < size) { - *p++ = encode(b7); - } else { - *p++ = '='; - } + *p++ = encode_char(b1 >> 2); + *p++ = encode_char(((b1 & 0x3) << 4) | (b2 >> 4)); + *p++ = (i + 1 < size) ? encode_char(((b2 & 0xf) << 2) | (b3 >> 6)) : '='; + *p++ = (i + 2 < size) ? encode_char(b3 & 0x3f) : '='; } return out; } -/* Decode the base64 encoded string 'src' into the memory pointed to by - * 'dest'. The dest buffer is NUL terminated. - * Returns NULL in case of error - */ -char *decode_base64(const char *src) -{ - if (src && *src) { - char *dest; - unsigned char *p; - int k, l = strlen(src) + 1; - unsigned char *buf; - - /* The size of the dest will always be less than the source */ - dest = (char *)calloc(sizeof(char), l + 13); - if (!dest) { - return (NULL); - } - - p = (unsigned char *)dest; - - buf = (unsigned char *) malloc(l); - if (!buf) { - free(dest); - return (NULL); - } - - /* Ignore non base64 chars as per the POSIX standard */ - for (k = 0, l = 0; src[k]; k++) { - if (is_base64(src[k])) { - buf[l++] = src[k]; - } - } - - for (k = 0; k < l; k += 4) { - char c1 = 'A', c2 = 'A', c3 = 'A', c4 = 'A'; - unsigned char b1 = 0, b2 = 0, b3 = 0, b4 = 0; - - c1 = buf[k]; - - if (k + 1 < l) { - c2 = buf[k + 1]; - } - - if (k + 2 < l) { - c3 = buf[k + 2]; - } - - if (k + 3 < l) { - c4 = buf[k + 3]; - } - - b1 = decode(c1); - b2 = decode(c2); - b3 = decode(c3); - b4 = decode(c4); +/* Decode Base64 encoded string */ +char *decode_base64(const char *src) { + if (!src || !*src) return NULL; - *p++ = ((b1 << 2) | (b2 >> 4) ); + int len = strlen(src); + int out_len = len * 3 / 4; + char *dest = (char *)calloc(out_len + 1, sizeof(char)); // +1 for null terminator + if (!dest) return NULL; - if (c3 != '=') { - *p++ = (((b2 & 0xf) << 4) | (b3 >> 2) ); - } - - if (c4 != '=') { - *p++ = (((b3 & 0x3) << 6) | b4 ); - } + unsigned char *buf = (unsigned char *)malloc(len); + if (!buf) { + free(dest); + return NULL; + } + // Ignore non-Base64 characters + int l = 0; + for (int k = 0; k < len; k++) { + if (is_base64(src[k])) { + buf[l++] = src[k]; } - - free(buf); - - return (dest); } - return (NULL); -} -static char encode(unsigned char u) -{ - if (u < 26) { - return 'A' + u; - } - if (u < 52) { - return 'a' + (u - 26); - } - if (u < 62) { - return '0' + (u - 52); - } - if (u == 62) { - return '+'; - } + unsigned char *p = (unsigned char *)dest; - return '/'; -} + for (int k = 0; k < l; k += 4) { + unsigned char b1 = decode_char(buf[k]); + unsigned char b2 = decode_char((k + 1 < l) ? buf[k + 1] : 'A'); + unsigned char b3 = decode_char((k + 2 < l) ? buf[k + 2] : 'A'); + unsigned char b4 = decode_char((k + 3 < l) ? buf[k + 3] : 'A'); -/* Decode a base64 character */ -static unsigned char decode(char c) -{ - if (c >= 'A' && c <= 'Z') { - return (c - 'A'); - } - if (c >= 'a' && c <= 'z') { - return (c - 'a' + 26); - } - if (c >= '0' && c <= '9') { - return (c - '0' + 52); + *p++ = (b1 << 2) | (b2 >> 4); + if (buf[k + 2] != '=') *p++ = ((b2 & 0xf) << 4) | (b3 >> 2); + if (buf[k + 3] != '=') *p++ = ((b3 & 0x3) << 6) | b4; } - if (c == '+') { - return 62; - } - - return 63; -} -/* Returns TRUE if 'c' is a valid base64 character, otherwise FALSE */ -static int is_base64(char c) -{ - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || (c == '+') || - (c == '/') || (c == '=')) { - - return TRUE; - } - return FALSE; + free(buf); + return dest; } -