/** Base64 encode/decode implementation. * @file */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "elinks.h" #include "util/base64.h" #include "util/error.h" #include "util/memory.h" static unsigned char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char * base64_encode(char *in) { assert(in && *in); if_assert_failed return NULL; return base64_encode_bin(in, strlen(in), NULL); } char * base64_encode_bin(char *in, int inlen, int *outlen) { char *out; char *outstr; assert(in && *in); if_assert_failed return NULL; out = outstr = (char *)mem_alloc((inlen / 3) * 4 + 4 + 1); if (!out) return NULL; while (inlen >= 3) { *out++ = base64_chars[ *in >> 2 ]; *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ]; *out++ = base64_chars[ (*(in + 1) << 2 | *(in + 2) >> 6) & 63 ]; *out++ = base64_chars[ *(in + 2) & 63 ]; inlen -= 3; in += 3; } if (inlen == 1) { *out++ = base64_chars[ *in >> 2 ]; *out++ = base64_chars[ *in << 4 & 63 ]; *out++ = '='; *out++ = '='; } if (inlen == 2) { *out++ = base64_chars[ *in >> 2 ]; *out++ = base64_chars[ (*in << 4 | *(in + 1) >> 4) & 63 ]; *out++ = base64_chars[ (*(in + 1) << 2) & 63 ]; *out++ = '='; } *out = 0; if (outlen) *outlen = out-outstr; return outstr; } char * base64_decode(const char *in) { assert(in && *in); if_assert_failed return NULL; return base64_decode_bin(in, strlen(in), NULL); } /** Decode a Base64 string. * @param in Input Base64 string * @param inlen Length of @a in, in bytes * @param[out] outlen Length of decoded string * * @returns the string decoded (must be freed by the caller) * or NULL if an error occurred (syntax error or out of memory) */ char * base64_decode_bin(const char *in, int inlen, int *outlen) { static unsigned char is_base64_char[256]; /* static to force initialization at zero */ static unsigned char decode[256]; char *out; char *outstr; int count = 0; unsigned int bits = 0; static int once = 0; assert(in && *in); if_assert_failed return NULL; outstr = out = (char *)mem_alloc(inlen / 4 * 3 + 1); if (!outstr) return NULL; if (!once) { int i = sizeof(base64_chars) - 1; while (i >= 0) { is_base64_char[base64_chars[i]] = 1; decode[base64_chars[i]] = i; i--; } once = 1; } while (*in) { if (*in == '=') break; if (!is_base64_char[(unsigned char)*in]) goto decode_error; bits += decode[(unsigned char)*in]; count++; if (count == 4) { *out++ = bits >> 16; *out++ = (bits >> 8) & 0xff; *out++ = bits & 0xff; bits = 0; count = 0; } else { bits <<= 6; } ++in; } if (!*in) { if (count) goto decode_error; } else { /* '=' */ switch (count) { case 1: goto decode_error; break; case 2: *out++ = bits >> 10; break; case 3: *out++ = bits >> 16; *out++ = (bits >> 8) & 0xff; break; } } *out = 0; if (outlen) *outlen = out-outstr; return outstr; decode_error: mem_free(outstr); return NULL; }