Gitweb links:

...log 
http://git.netsurf-browser.org/libnsutils.git/shortlog/b7199a77aca01f85a3359737cd4e6c73c29bd82a
...commit 
http://git.netsurf-browser.org/libnsutils.git/commit/b7199a77aca01f85a3359737cd4e6c73c29bd82a
...tree 
http://git.netsurf-browser.org/libnsutils.git/tree/b7199a77aca01f85a3359737cd4e6c73c29bd82a

The branch, master has been updated
       via  b7199a77aca01f85a3359737cd4e6c73c29bd82a (commit)
      from  28a80ecdf8588afe5ee521acf3ba48d81aae7373 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/libnsutils.git/commit/?id=b7199a77aca01f85a3359737cd4e6c73c29bd82a
commit b7199a77aca01f85a3359737cd4e6c73c29bd82a
Author: Vincent Sanders <[email protected]>
Commit: Vincent Sanders <[email protected]>

    extend base64 api with url safe versions

diff --git a/include/nsutils/base64.h b/include/nsutils/base64.h
index 2baeec6..6dba643 100644
--- a/include/nsutils/base64.h
+++ b/include/nsutils/base64.h
@@ -36,6 +36,23 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input,
                                  size_t *output_length);
 
 /**
+ * Base 64 encode data.
+ *
+ * allocate a buffer and encode source data into it using the base64 URL safe
+ *   encoding.
+ *
+ * \param input The source data to encode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+nsuerror nsu_base64_encode_alloc_url(const uint8_t *input,
+                                     size_t input_length,
+                                     uint8_t **output,
+                                     size_t *output_length);
+
+/**
  * Base 64 decode data.
  *
  * allocate a buffer and decode source data into it using the Base64 encoding.
@@ -50,5 +67,22 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
                                  size_t input_length,
                                  uint8_t **output,
                                  size_t *output_length);
- 
+
+/**
+ * Base 64 decode data.
+ *
+ * Allocate a buffer and decode source data into it using the Base64 URL safe
+ *   encoding.
+ *
+ * \param input The source data to decode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+nsuerror nsu_base64_decode_alloc_url(const uint8_t *input,
+                                     size_t input_length,
+                                     uint8_t **output,
+                                     size_t *output_length);
+
 #endif
diff --git a/src/base64.c b/src/base64.c
index c11364f..79909ea 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -21,22 +21,112 @@
 
 #include "nsutils/base64.h"
 
-static uint8_t decoding_table[256];
-static uint8_t encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
-                                '4', '5', '6', '7', '8', '9', '+', '/'};
+static const uint8_t b64_decoding_table[256] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  0 -  7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  8 -  F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */
+    0xff, 0xff, 0xff,   62, 0xff, 0xff, 0xff,   63, /* 28 - 2F */
+      52,   53,   54,   55,   56,   57,   58,   59, /* 30 - 37 */
+      60,   61, 0xff, 0xff, 0xff,   64, 0xff, 0xff, /* 38 - 3F */
+    0xff,    0,    1,    2,    3,    4,    5,    6, /* 40 - 47 */
+       7,    8,    9,   10,   11,   12,   13,   14, /* 48 - 4F */
+      15,   16,   17,   18,   19,   20,   21,   22, /* 50 - 57 */
+      23,   24,   25, 0xff, 0xff, 0xff, 0xff, 0xff, /* 58 - 5F */
+    0xff,   26,   27,   28,   29,   30,   31,   32, /* 60 - 67 */
+      33,   34,   35,   36,   37,   38,   39,   40, /* 68 - 6F */
+      41,   42,   43,   44,   45,   46,   47,   48, /* 70 - 77 */
+      49,   50,   51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */
+};
+static const uint8_t b64_encoding_table[] = {
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '0', '1', '2', '3',
+    '4', '5', '6', '7', '8', '9', '+', '/'};
+static const uint8_t b64url_decoding_table[256] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  0 -  7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  8 -  F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */
+    0xff, 0xff, 0xff, 0xff, 0xff,   62, 0xff, 0xff, /* 28 - 2F */
+      52,   53,   54,   55,   56,   57,   58,   59, /* 30 - 37 */
+      60,   61, 0xff, 0xff, 0xff,   64, 0xff, 0xff, /* 38 - 3F */
+    0xff,    0,    1,    2,    3,    4,    5,    6, /* 40 - 47 */
+       7,    8,    9,   10,   11,   12,   13,   14, /* 48 - 4F */
+      15,   16,   17,   18,   19,   20,   21,   22, /* 50 - 57 */
+      23,   24,   25, 0xff, 0xff, 0xff, 0xff,   63, /* 58 - 5F */
+    0xff,   26,   27,   28,   29,   30,   31,   32, /* 60 - 67 */
+      33,   34,   35,   36,   37,   38,   39,   40, /* 68 - 6F */
+      41,   42,   43,   44,   45,   46,   47,   48, /* 70 - 77 */
+      49,   50,   51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */
+};
+static const uint8_t b64url_encoding_table[] = {
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '0', '1', '2', '3',
+    '4', '5', '6', '7', '8', '9', '-', '_'};
 static unsigned int mod_table[] = {0, 2, 1};
 
-/* exported interface documented in nsutils/base64.h */
-nsuerror nsu_base64_encode_alloc(const uint8_t *input,
-                            size_t input_length,
-                            uint8_t **output,
-                            size_t *output_length)
+
+/**
+ * Base 64 encode data using a given encoding table.
+ *
+ * allocate a buffer and encode source data into it using the Base64 encoding.
+ *
+ * \param input The source data to encode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+static nsuerror
+table_encode_alloc(const uint8_t *encoding_table,
+                   const uint8_t *input,
+                   size_t input_length,
+                   uint8_t **output,
+                   size_t *output_length)
 {
         uint8_t *encoded;
         size_t encoded_len;
@@ -74,14 +164,62 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input,
         return NSUERROR_OK;
 }
 
+/*
+ * standard base64 encoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_encode_alloc(const uint8_t *input,
+                        size_t input_length,
+                        uint8_t **output,
+                        size_t *output_length)
+{
+        return table_encode_alloc(b64_encoding_table,
+                                  input,
+                                  input_length,
+                                  output,
+                                  output_length);
+}
 
-/* exported interface documented in nsutils/base64.h */
-nsuerror nsu_base64_decode_alloc(const uint8_t *input,
+/*
+ * url base64 encoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_encode_alloc_url(const uint8_t *input,
                             size_t input_length,
                             uint8_t **output,
                             size_t *output_length)
 {
-        static bool decode_initialised = false;
+        return table_encode_alloc(b64url_encoding_table,
+                                  input,
+                                  input_length,
+                                  output,
+                                  output_length);
+}
+
+
+/**
+ * Base 64 decode data with a given decoding table.
+ *
+ * Allocate a buffer and decode source data into it using the Base64 decoding
+ * table.
+ *
+ * \param input The source data to decode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+static nsuerror
+base64_decode_alloc(const uint8_t *decoding_table,
+                    const uint8_t *input,
+                    size_t input_length,
+                    uint8_t **output,
+                    size_t *output_length)
+{
         uint8_t *decoded;
         size_t decoded_len;
         size_t idx;
@@ -89,15 +227,6 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
         uint8_t sextet[4];
         int sextet_idx;
 
-        if (!decode_initialised) {
-                memset(decoding_table, 0xff, sizeof(decoding_table));
-                for (idx = 0; idx < 64; idx++) {
-                        decoding_table[encoding_table[idx]] = idx;
-                }
-                decoding_table['='] = 64;
-                decode_initialised = true;
-        }
-
         decoded_len = ((input_length + 3) / 4) * 3;
         if (input[input_length - 1] == '=') (decoded_len)--;
         if (input[input_length - 2] == '=') (decoded_len)--;
@@ -179,3 +308,41 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
 
         return NSUERROR_OK;
 }
+
+
+/*
+ * standard base64 decoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_decode_alloc(const uint8_t *input,
+                        size_t input_length,
+                        uint8_t **output,
+                        size_t *output_length)
+{
+        return base64_decode_alloc(b64_decoding_table,
+                                   input,
+                                   input_length,
+                                   output,
+                                   output_length);
+}
+
+
+/*
+ * standard base64 decoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_decode_alloc_url(const uint8_t *input,
+                            size_t input_length,
+                            uint8_t **output,
+                            size_t *output_length)
+{
+        return base64_decode_alloc(b64url_decoding_table,
+                                   input,
+                                   input_length,
+                                   output,
+                                   output_length);
+}
diff --git a/test/base64.c b/test/base64.c
index 7b09205..5cb8a7c 100644
--- a/test/base64.c
+++ b/test/base64.c
@@ -16,37 +16,65 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include <nsutils/base64.h>
 
 int main(int argc, char**argv)
 {
-    uint8_t *buffer;
-    size_t buffer_len=0;
-    uint8_t *output;
-    size_t output_len;
-
-    if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) {
-        return 1;
-    }
-    
-    if (argc == 1) {
-        /* encode */
-        nsu_base64_encode_alloc(buffer, buffer_len, &output, &output_len);
-    } else if ((argv[1][0] == '-') && (argv[1][1] == 'd')) {
-        /* decode */
-        nsu_base64_decode_alloc(buffer, buffer_len, &output, &output_len);
-    } else {
-        fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
-        return 1;
-    }
-
-    if (output != NULL) {
-        printf("%.*s", (int)output_len, output);
-        free(output);
-    }
-
-    free(buffer);
-
-    return 0;
+        uint8_t *buffer;
+        size_t buffer_len=0;
+        uint8_t *output;
+        size_t output_len;
+        int opt;
+        int decode = 0;
+        int url = 0;
+
+
+        while ((opt = getopt(argc, argv, "du")) != -1) {
+                switch (opt) {
+                case 'd':
+                        decode = 1;
+                        break;
+                case 'u':
+                        url = 1;
+                        break;
+
+                default: /* '?' */
+                        fprintf(stderr, "Usage: %s [-d] [-u]\n", argv[0]);
+                        exit(EXIT_FAILURE);
+
+                }
+        }
+
+        if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) {
+                return 1;
+        }
+
+
+        if (decode) {
+                /* decode */
+                if (url) {
+                        nsu_base64_decode_alloc_url(buffer, buffer_len, 
&output, &output_len);
+                } else {
+
+                        nsu_base64_decode_alloc(buffer, buffer_len, &output, 
&output_len);
+                }
+        } else {
+                /* encode */
+                if (url) {
+                        nsu_base64_encode_alloc_url(buffer, buffer_len, 
&output, &output_len);
+                } else {
+                        nsu_base64_encode_alloc(buffer, buffer_len, &output, 
&output_len);
+                }
+        }
+
+        if (output != NULL) {
+                printf("%.*s", (int)output_len, output);
+                free(output);
+        }
+
+        free(buffer);
+
+        return 0;
 }
diff --git a/test/runtest.sh b/test/runtest.sh
index efcb79f..9f02e1c 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -5,30 +5,70 @@ b64enctst()
 {
     ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 )
     if [ "${ENC}" != "${2}" ];then
-        echo "Base64 encode error ${ENC} != ${2}"
+        echo "Base64 encode error '${ENC}' != '${2}'"
        exit 2
-    fi 
+    fi
 }
 
 b64dectst()
 {
     DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d )
     if [ "${DEC}" != "$2" ];then
-        echo "Base64 decode error ${DEC} != $2"
+        echo "Base64 decode error '${DEC}' != '$2'"
        exit 3
-    fi 
+    fi
 }
 
-b64enctst 'f' 'Zg=='
-b64enctst 'fo' 'Zm8='
-b64enctst 'foo' 'Zm9v'
-b64enctst 'foob' 'Zm9vYg=='
-b64enctst 'fooba' 'Zm9vYmE='
+b64urlenctst()
+{
+    ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 -u )
+    if [ "${ENC}" != "${2}" ];then
+        echo "Base64 url encode error '${ENC}' != '${2}'"
+       exit 2
+    fi
+}
+
+b64urldectst()
+{
+    DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d -u )
+    if [ "${DEC}" != "$2" ];then
+        echo "Base64 url decode error '${DEC}' != '$2'"
+       exit 3
+    fi
+}
+
+b64enctst      'f' 'Zg=='
+b64enctst     'fo' 'Zm8='
+b64enctst    'foo' 'Zm9v'
+b64enctst    '  >' 'ICA+'
+b64enctst    '  ?' 'ICA/'
+b64enctst   'foob' 'Zm9vYg=='
+b64enctst  'fooba' 'Zm9vYmE='
 b64enctst 'foobar' 'Zm9vYmFy'
 
-b64dectst 'Zg==' 'f'
-b64dectst 'Zm8=' 'fo'
-b64dectst 'Zm9v' 'foo'
+b64dectst     'Zg==' 'f'
+b64dectst     'Zm8=' 'fo'
+b64dectst     'Zm9v' 'foo'
+b64dectst     'ICA+' '  >'
+b64dectst     'ICA/' '  ?'
 b64dectst 'Zm9vYg==' 'foob'
 b64dectst 'Zm9vYmE=' 'fooba'
 b64dectst 'Zm9vYmFy' 'foobar'
+
+b64urlenctst      'f' 'Zg=='
+b64urlenctst     'fo' 'Zm8='
+b64urlenctst    'foo' 'Zm9v'
+b64urlenctst    '  >' 'ICA-'
+b64urlenctst    '  ?' 'ICA_'
+b64urlenctst   'foob' 'Zm9vYg=='
+b64urlenctst  'fooba' 'Zm9vYmE='
+b64urlenctst 'foobar' 'Zm9vYmFy'
+
+b64urldectst     'Zg==' 'f'
+b64urldectst     'Zm8=' 'fo'
+b64urldectst     'Zm9v' 'foo'
+b64urldectst     'ICA-' '  >'
+b64urldectst     'ICA_' '  ?'
+b64urldectst 'Zm9vYg==' 'foob'
+b64urldectst 'Zm9vYmE=' 'fooba'
+b64urldectst 'Zm9vYmFy' 'foobar'


-----------------------------------------------------------------------

Summary of changes:
 include/nsutils/base64.h |   36 +++++++-
 src/base64.c             |  219 ++++++++++++++++++++++++++++++++++++++++------
 test/base64.c            |   84 ++++++++++++------
 test/runtest.sh          |   64 +++++++++++---
 4 files changed, 336 insertions(+), 67 deletions(-)

diff --git a/include/nsutils/base64.h b/include/nsutils/base64.h
index 2baeec6..6dba643 100644
--- a/include/nsutils/base64.h
+++ b/include/nsutils/base64.h
@@ -36,6 +36,23 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input,
                                  size_t *output_length);
 
 /**
+ * Base 64 encode data.
+ *
+ * allocate a buffer and encode source data into it using the base64 URL safe
+ *   encoding.
+ *
+ * \param input The source data to encode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+nsuerror nsu_base64_encode_alloc_url(const uint8_t *input,
+                                     size_t input_length,
+                                     uint8_t **output,
+                                     size_t *output_length);
+
+/**
  * Base 64 decode data.
  *
  * allocate a buffer and decode source data into it using the Base64 encoding.
@@ -50,5 +67,22 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
                                  size_t input_length,
                                  uint8_t **output,
                                  size_t *output_length);
- 
+
+/**
+ * Base 64 decode data.
+ *
+ * Allocate a buffer and decode source data into it using the Base64 URL safe
+ *   encoding.
+ *
+ * \param input The source data to decode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+nsuerror nsu_base64_decode_alloc_url(const uint8_t *input,
+                                     size_t input_length,
+                                     uint8_t **output,
+                                     size_t *output_length);
+
 #endif
diff --git a/src/base64.c b/src/base64.c
index c11364f..79909ea 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -21,22 +21,112 @@
 
 #include "nsutils/base64.h"
 
-static uint8_t decoding_table[256];
-static uint8_t encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
-                                '4', '5', '6', '7', '8', '9', '+', '/'};
+static const uint8_t b64_decoding_table[256] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  0 -  7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  8 -  F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */
+    0xff, 0xff, 0xff,   62, 0xff, 0xff, 0xff,   63, /* 28 - 2F */
+      52,   53,   54,   55,   56,   57,   58,   59, /* 30 - 37 */
+      60,   61, 0xff, 0xff, 0xff,   64, 0xff, 0xff, /* 38 - 3F */
+    0xff,    0,    1,    2,    3,    4,    5,    6, /* 40 - 47 */
+       7,    8,    9,   10,   11,   12,   13,   14, /* 48 - 4F */
+      15,   16,   17,   18,   19,   20,   21,   22, /* 50 - 57 */
+      23,   24,   25, 0xff, 0xff, 0xff, 0xff, 0xff, /* 58 - 5F */
+    0xff,   26,   27,   28,   29,   30,   31,   32, /* 60 - 67 */
+      33,   34,   35,   36,   37,   38,   39,   40, /* 68 - 6F */
+      41,   42,   43,   44,   45,   46,   47,   48, /* 70 - 77 */
+      49,   50,   51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */
+};
+static const uint8_t b64_encoding_table[] = {
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '0', '1', '2', '3',
+    '4', '5', '6', '7', '8', '9', '+', '/'};
+static const uint8_t b64url_decoding_table[256] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  0 -  7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*  8 -  F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 10 - 17 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 18 - 1F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 20 - 27 */
+    0xff, 0xff, 0xff, 0xff, 0xff,   62, 0xff, 0xff, /* 28 - 2F */
+      52,   53,   54,   55,   56,   57,   58,   59, /* 30 - 37 */
+      60,   61, 0xff, 0xff, 0xff,   64, 0xff, 0xff, /* 38 - 3F */
+    0xff,    0,    1,    2,    3,    4,    5,    6, /* 40 - 47 */
+       7,    8,    9,   10,   11,   12,   13,   14, /* 48 - 4F */
+      15,   16,   17,   18,   19,   20,   21,   22, /* 50 - 57 */
+      23,   24,   25, 0xff, 0xff, 0xff, 0xff,   63, /* 58 - 5F */
+    0xff,   26,   27,   28,   29,   30,   31,   32, /* 60 - 67 */
+      33,   34,   35,   36,   37,   38,   39,   40, /* 68 - 6F */
+      41,   42,   43,   44,   45,   46,   47,   48, /* 70 - 77 */
+      49,   50,   51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 78 - 7F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 - 87 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88 - 8F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 90 - 97 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 98 - 9F */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A0 - A7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* A8 - AF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B0 - B7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* B8 - BF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C0 - C7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* C8 - CF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D0 - D7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* D8 - DF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E0 - E7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* E8 - EF */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F0 - F7 */
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* F8 - FF */
+};
+static const uint8_t b64url_encoding_table[] = {
+    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+    'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '0', '1', '2', '3',
+    '4', '5', '6', '7', '8', '9', '-', '_'};
 static unsigned int mod_table[] = {0, 2, 1};
 
-/* exported interface documented in nsutils/base64.h */
-nsuerror nsu_base64_encode_alloc(const uint8_t *input,
-                            size_t input_length,
-                            uint8_t **output,
-                            size_t *output_length)
+
+/**
+ * Base 64 encode data using a given encoding table.
+ *
+ * allocate a buffer and encode source data into it using the Base64 encoding.
+ *
+ * \param input The source data to encode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+static nsuerror
+table_encode_alloc(const uint8_t *encoding_table,
+                   const uint8_t *input,
+                   size_t input_length,
+                   uint8_t **output,
+                   size_t *output_length)
 {
         uint8_t *encoded;
         size_t encoded_len;
@@ -74,14 +164,62 @@ nsuerror nsu_base64_encode_alloc(const uint8_t *input,
         return NSUERROR_OK;
 }
 
+/*
+ * standard base64 encoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_encode_alloc(const uint8_t *input,
+                        size_t input_length,
+                        uint8_t **output,
+                        size_t *output_length)
+{
+        return table_encode_alloc(b64_encoding_table,
+                                  input,
+                                  input_length,
+                                  output,
+                                  output_length);
+}
 
-/* exported interface documented in nsutils/base64.h */
-nsuerror nsu_base64_decode_alloc(const uint8_t *input,
+/*
+ * url base64 encoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_encode_alloc_url(const uint8_t *input,
                             size_t input_length,
                             uint8_t **output,
                             size_t *output_length)
 {
-        static bool decode_initialised = false;
+        return table_encode_alloc(b64url_encoding_table,
+                                  input,
+                                  input_length,
+                                  output,
+                                  output_length);
+}
+
+
+/**
+ * Base 64 decode data with a given decoding table.
+ *
+ * Allocate a buffer and decode source data into it using the Base64 decoding
+ * table.
+ *
+ * \param input The source data to decode.
+ * \param input_length The length of the source data.
+ * \param output The buffer to recive data into, the caller must free.
+ * \param output_length The length of data placed in \a output
+ * \return NSERROR_OK on success and \a output updated else error code.
+ */
+static nsuerror
+base64_decode_alloc(const uint8_t *decoding_table,
+                    const uint8_t *input,
+                    size_t input_length,
+                    uint8_t **output,
+                    size_t *output_length)
+{
         uint8_t *decoded;
         size_t decoded_len;
         size_t idx;
@@ -89,15 +227,6 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
         uint8_t sextet[4];
         int sextet_idx;
 
-        if (!decode_initialised) {
-                memset(decoding_table, 0xff, sizeof(decoding_table));
-                for (idx = 0; idx < 64; idx++) {
-                        decoding_table[encoding_table[idx]] = idx;
-                }
-                decoding_table['='] = 64;
-                decode_initialised = true;
-        }
-
         decoded_len = ((input_length + 3) / 4) * 3;
         if (input[input_length - 1] == '=') (decoded_len)--;
         if (input[input_length - 2] == '=') (decoded_len)--;
@@ -179,3 +308,41 @@ nsuerror nsu_base64_decode_alloc(const uint8_t *input,
 
         return NSUERROR_OK;
 }
+
+
+/*
+ * standard base64 decoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_decode_alloc(const uint8_t *input,
+                        size_t input_length,
+                        uint8_t **output,
+                        size_t *output_length)
+{
+        return base64_decode_alloc(b64_decoding_table,
+                                   input,
+                                   input_length,
+                                   output,
+                                   output_length);
+}
+
+
+/*
+ * standard base64 decoding
+ *
+ * exported interface documented in nsutils/base64.h
+ */
+nsuerror
+nsu_base64_decode_alloc_url(const uint8_t *input,
+                            size_t input_length,
+                            uint8_t **output,
+                            size_t *output_length)
+{
+        return base64_decode_alloc(b64url_decoding_table,
+                                   input,
+                                   input_length,
+                                   output,
+                                   output_length);
+}
diff --git a/test/base64.c b/test/base64.c
index 7b09205..5cb8a7c 100644
--- a/test/base64.c
+++ b/test/base64.c
@@ -16,37 +16,65 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include <nsutils/base64.h>
 
 int main(int argc, char**argv)
 {
-    uint8_t *buffer;
-    size_t buffer_len=0;
-    uint8_t *output;
-    size_t output_len;
-
-    if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) {
-        return 1;
-    }
-    
-    if (argc == 1) {
-        /* encode */
-        nsu_base64_encode_alloc(buffer, buffer_len, &output, &output_len);
-    } else if ((argv[1][0] == '-') && (argv[1][1] == 'd')) {
-        /* decode */
-        nsu_base64_decode_alloc(buffer, buffer_len, &output, &output_len);
-    } else {
-        fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
-        return 1;
-    }
-
-    if (output != NULL) {
-        printf("%.*s", (int)output_len, output);
-        free(output);
-    }
-
-    free(buffer);
-
-    return 0;
+        uint8_t *buffer;
+        size_t buffer_len=0;
+        uint8_t *output;
+        size_t output_len;
+        int opt;
+        int decode = 0;
+        int url = 0;
+
+
+        while ((opt = getopt(argc, argv, "du")) != -1) {
+                switch (opt) {
+                case 'd':
+                        decode = 1;
+                        break;
+                case 'u':
+                        url = 1;
+                        break;
+
+                default: /* '?' */
+                        fprintf(stderr, "Usage: %s [-d] [-u]\n", argv[0]);
+                        exit(EXIT_FAILURE);
+
+                }
+        }
+
+        if (scanf("%1024mc%n", &buffer, (int *)&buffer_len) < 1) {
+                return 1;
+        }
+
+
+        if (decode) {
+                /* decode */
+                if (url) {
+                        nsu_base64_decode_alloc_url(buffer, buffer_len, 
&output, &output_len);
+                } else {
+
+                        nsu_base64_decode_alloc(buffer, buffer_len, &output, 
&output_len);
+                }
+        } else {
+                /* encode */
+                if (url) {
+                        nsu_base64_encode_alloc_url(buffer, buffer_len, 
&output, &output_len);
+                } else {
+                        nsu_base64_encode_alloc(buffer, buffer_len, &output, 
&output_len);
+                }
+        }
+
+        if (output != NULL) {
+                printf("%.*s", (int)output_len, output);
+                free(output);
+        }
+
+        free(buffer);
+
+        return 0;
 }
diff --git a/test/runtest.sh b/test/runtest.sh
index efcb79f..9f02e1c 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -5,30 +5,70 @@ b64enctst()
 {
     ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 )
     if [ "${ENC}" != "${2}" ];then
-        echo "Base64 encode error ${ENC} != ${2}"
+        echo "Base64 encode error '${ENC}' != '${2}'"
        exit 2
-    fi 
+    fi
 }
 
 b64dectst()
 {
     DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d )
     if [ "${DEC}" != "$2" ];then
-        echo "Base64 decode error ${DEC} != $2"
+        echo "Base64 decode error '${DEC}' != '$2'"
        exit 3
-    fi 
+    fi
 }
 
-b64enctst 'f' 'Zg=='
-b64enctst 'fo' 'Zm8='
-b64enctst 'foo' 'Zm9v'
-b64enctst 'foob' 'Zm9vYg=='
-b64enctst 'fooba' 'Zm9vYmE='
+b64urlenctst()
+{
+    ENC=$(echo -n "${1}" | ${TEST_PATH}/test_base64 -u )
+    if [ "${ENC}" != "${2}" ];then
+        echo "Base64 url encode error '${ENC}' != '${2}'"
+       exit 2
+    fi
+}
+
+b64urldectst()
+{
+    DEC=$(echo -n "$1" | ${TEST_PATH}/test_base64 -d -u )
+    if [ "${DEC}" != "$2" ];then
+        echo "Base64 url decode error '${DEC}' != '$2'"
+       exit 3
+    fi
+}
+
+b64enctst      'f' 'Zg=='
+b64enctst     'fo' 'Zm8='
+b64enctst    'foo' 'Zm9v'
+b64enctst    '  >' 'ICA+'
+b64enctst    '  ?' 'ICA/'
+b64enctst   'foob' 'Zm9vYg=='
+b64enctst  'fooba' 'Zm9vYmE='
 b64enctst 'foobar' 'Zm9vYmFy'
 
-b64dectst 'Zg==' 'f'
-b64dectst 'Zm8=' 'fo'
-b64dectst 'Zm9v' 'foo'
+b64dectst     'Zg==' 'f'
+b64dectst     'Zm8=' 'fo'
+b64dectst     'Zm9v' 'foo'
+b64dectst     'ICA+' '  >'
+b64dectst     'ICA/' '  ?'
 b64dectst 'Zm9vYg==' 'foob'
 b64dectst 'Zm9vYmE=' 'fooba'
 b64dectst 'Zm9vYmFy' 'foobar'
+
+b64urlenctst      'f' 'Zg=='
+b64urlenctst     'fo' 'Zm8='
+b64urlenctst    'foo' 'Zm9v'
+b64urlenctst    '  >' 'ICA-'
+b64urlenctst    '  ?' 'ICA_'
+b64urlenctst   'foob' 'Zm9vYg=='
+b64urlenctst  'fooba' 'Zm9vYmE='
+b64urlenctst 'foobar' 'Zm9vYmFy'
+
+b64urldectst     'Zg==' 'f'
+b64urldectst     'Zm8=' 'fo'
+b64urldectst     'Zm9v' 'foo'
+b64urldectst     'ICA-' '  >'
+b64urldectst     'ICA_' '  ?'
+b64urldectst 'Zm9vYg==' 'foob'
+b64urldectst 'Zm9vYmE=' 'fooba'
+b64urldectst 'Zm9vYmFy' 'foobar'


-- 
NetSurf generalised utility library

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to