diff options
Diffstat (limited to 'src/base64.c')
-rw-r--r-- | src/base64.c | 110 |
1 files changed, 13 insertions, 97 deletions
diff --git a/src/base64.c b/src/base64.c index 0edf8a0f..0238afbb 100644 --- a/src/base64.c +++ b/src/base64.c @@ -14,11 +14,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "base64.h" - -#include "serd_internal.h" #include "string_utils.h" +#include "exess/exess.h" #include "serd/serd.h" #include <stdbool.h> @@ -26,103 +24,21 @@ #include <stdlib.h> #include <string.h> -/** - Base64 encoding table. - - @see <a href="http://tools.ietf.org/html/rfc3548#section-3">RFC3548 S3</a>. -*/ -static const uint8_t b64_map[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/** - Base64 decoding table. - - This is indexed by encoded characters and returns the numeric value used - for decoding, shifted up by 47 to be in the range of printable ASCII. - A '$' is a placeholder for characters not in the base64 alphabet. -*/ -static const char b64_unmap[] = - "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$m$$$ncdefghijkl$$$$$$" - "$/0123456789:;<=>?@ABCDEFGH$$$$$$IJKLMNOPQRSTUVWXYZ[\\]^_`ab$$$$" - "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" - "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"; - -/** Encode 3 raw bytes to 4 base64 characters. */ -static inline void -encode_chunk(uint8_t out[4], const uint8_t in[3], size_t n_in) -{ - out[0] = b64_map[in[0] >> 2]; - out[1] = b64_map[((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4)]; - - out[2] = (n_in > 1) ? (b64_map[((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6)]) - : (uint8_t)'='; - - out[3] = ((n_in > 2) ? b64_map[in[2] & 0x3F] : (uint8_t)'='); -} - -size_t -serd_base64_get_length(const size_t size, const bool wrap_lines) -{ - return (size + 2) / 3 * 4 + (wrap_lines * ((size - 1) / 57)); -} - -bool -serd_base64_encode(uint8_t* const str, - const void* const buf, - const size_t size, - const bool wrap_lines) -{ - bool has_newline = false; - for (size_t i = 0, j = 0; i < size; i += 3, j += 4) { - uint8_t in[4] = {0, 0, 0, 0}; - size_t n_in = MIN(3, size - i); - memcpy(in, (const uint8_t*)buf + i, n_in); - - if (wrap_lines && i > 0 && (i % 57) == 0) { - str[j++] = '\n'; - has_newline = true; - } - - encode_chunk(str + j, in, n_in); - } - - return has_newline; -} - -static inline uint8_t -unmap(const uint8_t in) -{ - return (uint8_t)(b64_unmap[in] - 47); -} - -/** Decode 4 base64 characters to 3 raw bytes. */ -static inline size_t -decode_chunk(const uint8_t in[4], uint8_t out[3]) -{ - out[0] = (uint8_t)(((unmap(in[0]) << 2)) | unmap(in[1]) >> 4); - out[1] = (uint8_t)(((unmap(in[1]) << 4) & 0xF0) | unmap(in[2]) >> 2); - out[2] = (uint8_t)(((unmap(in[2]) << 6) & 0xC0) | unmap(in[3])); - return 1 + (in[2] != '=') + ((in[2] != '=') && (in[3] != '=')); -} - void* serd_base64_decode(const char* str, size_t len, size_t* size) { - const uint8_t* const ustr = (const uint8_t*)str; - - void* buf = malloc((len * 3) / 4 + 2); - *size = 0; - for (size_t i = 0, j = 0; i < len; j += 3) { - uint8_t in[] = "===="; - size_t n_in = 0; - for (; i < len && n_in < 4; ++n_in) { - for (; i < len && !is_base64(ustr[i]); ++i) { - } // Skip junk - in[n_in] = ustr[i++]; - } - if (n_in > 1) { - *size += decode_chunk(in, (uint8_t*)buf + j); - } + const size_t max_size = exess_base64_decoded_size(len); + + void* const buf = malloc(max_size); + ExessBlob blob = {max_size, buf}; + const ExessResult r = exess_read_base64(&blob, str); + if (r.status) { + *size = 0; + free(buf); + return NULL; } + + *size = blob.size; + return buf; } |