eina: API for base64url decode.

Summary:
eina_base64url_decode API.

Signed-off-by: Srivardhan Hebbar <sri.hebbar@samsung.com>

Reviewers: jpeg, cedric

Differential Revision: https://phab.enlightenment.org/D3434
This commit is contained in:
Srivardhan Hebbar 2015-12-16 16:15:43 +09:00 committed by Jean-Philippe Andre
parent 9f99213723
commit 1243b24f9b
1 changed files with 89 additions and 68 deletions

View File

@ -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;
error:
if (decoded_str_len)
*decoded_str_len = 0;
return NULL;
return eina_str_base64_decode_common(src, decoded_str_len, EINA_FALSE);
}
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);
}