eina: API for base64url decode.
authorSrivardhan Hebbar <sri.hebbar@samsung.com>
Wed, 16 Dec 2015 07:15:43 +0000 (16:15 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 16 Dec 2015 07:15:44 +0000 (16:15 +0900)
Summary:
eina_base64url_decode API.

Signed-off-by: Srivardhan Hebbar <sri.hebbar@samsung.com>
Reviewers: jpeg, cedric

Differential Revision: https://phab.enlightenment.org/D3434

src/lib/eina/eina_str.c

index 9fbd730..3a83d03 100644 (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;
+   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);
 }