From 1243b24f9b2967433e0a00d36c58117afe21d56b Mon Sep 17 00:00:00 2001 From: Srivardhan Hebbar Date: Wed, 16 Dec 2015 16:15:43 +0900 Subject: [PATCH] eina: API for base64url decode. Summary: eina_base64url_decode API. Signed-off-by: Srivardhan Hebbar Reviewers: jpeg, cedric Differential Revision: https://phab.enlightenment.org/D3434 --- src/lib/eina/eina_str.c | 155 +++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/src/lib/eina/eina_str.c b/src/lib/eina/eina_str.c index 9fbd730..3a83d03 100644 --- a/src/lib/eina/eina_str.c +++ b/src/lib/eina/eina_str.c @@ -301,9 +301,12 @@ eina_str_split_full_helper(const char *str, return str_array; } -static inline Eina_Bool is_base64(unsigned char c) +static inline Eina_Bool is_base64_char(unsigned char c, Eina_Bool is_base64url) { - return (isalnum(c) || (c == '+') || (c == '/')); + if (is_base64url) + return (isalnum(c) || (c == '-') || (c == '_')); + else + return (isalnum(c) || (c == '+') || (c == '/')); } static char * @@ -366,6 +369,83 @@ eina_str_base64_encode_common(const unsigned char *src, unsigned int len, Eina_B return dest; } +static +unsigned char *eina_str_base64_decode_common(const char * src, int *decoded_str_len, Eina_Bool is_base64url_decode) +{ + unsigned char inarr[4], outarr[3]; + int i = 0, j = 0, k = 0, l = 0; + int len; + unsigned char *dest; + const char *base64_table; + + if (!src) + goto error; + + len = strlen(src); + /* The encoded string length should be a multiple of 4. Else it is not a + * valid encoded string. + */ + if (!is_base64url_decode && (len % 4)) + goto error; + + /* This is the max size the destination string can have. + */ + dest = (unsigned char *)malloc(sizeof(unsigned char) * ((len * 3 / 4) + 1)); + if (!dest) + goto error; + + if (is_base64url_decode) + base64_table = base64_table_url; + else + base64_table = base64_table_normal; + + while (len-- && (src[k] != '=') && is_base64_char(src[k], is_base64url_decode)) + { + inarr[i++] = src[k++]; + if (i == 4) + { + for (i = 0; i <4; i++) + inarr[i] = strchr(base64_table,(int) inarr[i]) - base64_table; + + outarr[0] = (inarr[0] << 2) + ((inarr[1] & 0x30) >> 4); + outarr[1] = ((inarr[1] & 0xf) << 4) + ((inarr[2] & 0x3c) >> 2); + outarr[2] = ((inarr[2] & 0x3) << 6) + inarr[3]; + + for (i = 0; (i < 3); i++) + dest[l++] = outarr[i]; + i = 0; + } + } + + if (i) + { + for (j = i; j <4; j++) + inarr[j] = 0; + + for (j = 0; j <4; j++) + inarr[j] = strchr(base64_table, (int) inarr[j]) - base64_table; + + outarr[0] = (inarr[0] << 2) + ((inarr[1] & 0x30) >> 4); + outarr[1] = ((inarr[1] & 0xf) << 4) + ((inarr[2] & 0x3c) >> 2); + outarr[2] = ((inarr[2] & 0x3) << 6) + inarr[3]; + + for (j = 0; (j < i - 1); j++) + dest[l++] = outarr[j]; + } + + /* This is to prevent the applications from crashing. */ + dest[l] = '\0'; + + if (decoded_str_len) + *decoded_str_len = l; + return dest; + +error: + if (decoded_str_len) + *decoded_str_len = 0; + return NULL; +} + /** * @endcond */ @@ -810,70 +890,11 @@ eina_str_base64url_encode(const unsigned char *src, unsigned int len) EAPI unsigned char *eina_str_base64_decode(const char * src, int *decoded_str_len) { - unsigned char inarr[4], outarr[3]; - int i = 0, j = 0, k = 0, l = 0; - int len; - unsigned char *dest; - - if (!src) - goto error; - - len = strlen(src); - /* The encoded string length should be a multiple of 4. Else it is not a - * valid encoded string. - */ - if (len % 4) - goto error; - - /* This is the max size the destination string can have. - */ - dest = (unsigned char *)malloc(sizeof(unsigned char) * ((len * 3 / 4) + 1)); - if (!dest) - goto error; - - while (len-- && ( src[k] != '=') && is_base64(src[k])) - { - inarr[i++] = src[k++]; - if (i ==4) - { - for (i = 0; i <4; i++) - inarr[i] = strchr(base64_table_normal,(int) inarr[i]) - base64_table_normal; - - outarr[0] = (inarr[0] << 2) + ((inarr[1] & 0x30) >> 4); - outarr[1] = ((inarr[1] & 0xf) << 4) + ((inarr[2] & 0x3c) >> 2); - outarr[2] = ((inarr[2] & 0x3) << 6) + inarr[3]; - - for (i = 0; (i < 3); i++) - dest[l++] = outarr[i]; - i = 0; - } - } - - if (i) - { - for (j = i; j <4; j++) - inarr[j] = 0; - - for (j = 0; j <4; j++) - inarr[j] = strchr(base64_table_normal, (int) inarr[j]) - base64_table_normal; - - outarr[0] = (inarr[0] << 2) + ((inarr[1] & 0x30) >> 4); - outarr[1] = ((inarr[1] & 0xf) << 4) + ((inarr[2] & 0x3c) >> 2); - outarr[2] = ((inarr[2] & 0x3) << 6) + inarr[3]; - - for (j = 0; (j < i - 1); j++) - dest[l++] = outarr[j]; - } - - /* This is to prevent the applications from crashing. */ - dest[l] = '\0'; - - if (decoded_str_len) - *decoded_str_len = l; - return dest; + return eina_str_base64_decode_common(src, decoded_str_len, EINA_FALSE); +} -error: - if (decoded_str_len) - *decoded_str_len = 0; - return NULL; +EAPI +unsigned char *eina_str_base64url_decode(const char * src, int *decoded_str_len) +{ + return eina_str_base64_decode_common(src, decoded_str_len, EINA_TRUE); } -- 2.7.4