[njs] encodeURI() and encodeURIComponent() functions.

Igor Sysoev igor at sysoev.ru
Wed Aug 31 12:54:31 UTC 2016


details:   http://hg.nginx.org/njs/rev/d63ecb57f164
branches:  
changeset: 160:d63ecb57f164
user:      Igor Sysoev <igor at sysoev.ru>
date:      Tue Aug 30 12:02:31 2016 +0300
description:
encodeURI() and encodeURIComponent() functions.

diffstat:

 njs/njs_builtin.c        |   16 +++--
 njs/njs_generator.c      |    2 +
 njs/njs_lexer_keyword.c  |    2 +
 njs/njs_parser.c         |    2 +
 njs/njs_parser.h         |    2 +
 njs/njs_string.c         |  133 +++++++++++++++++++++++++++++++++++++++++++++++
 njs/njs_string.h         |    4 +
 njs/njs_vm.h             |   20 +++---
 njs/test/njs_unit_test.c |   12 ++++
 9 files changed, 178 insertions(+), 15 deletions(-)

diffs (309 lines):

diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_builtin.c
--- a/njs/njs_builtin.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_builtin.c	Tue Aug 30 12:02:31 2016 +0300
@@ -82,12 +82,14 @@ njs_builtin_objects_create(njs_vm_t *vm)
     };
 
     static const njs_object_init_t    *function_init[] = {
-        &njs_eval_function_init,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
+        &njs_eval_function_init,      /* eval               */
+        NULL,                         /* toString           */
+        NULL,                         /* isNaN              */
+        NULL,                         /* isFinite           */
+        NULL,                         /* parseInt           */
+        NULL,                         /* parseFloat         */
+        NULL,                         /* encodeURI          */
+        NULL,                         /* encodeURIComponent */
     };
 
     static const njs_function_init_t  native_functions[] = {
@@ -99,6 +101,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
         { njs_number_parse_int,
           { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
         { njs_number_parse_float,          { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_string_encode_uri,           { NJS_SKIP_ARG, NJS_STRING_ARG } },
+        { njs_string_encode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
     };
 
     static const njs_object_prop_t    null_proto_property = {
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_generator.c
--- a/njs/njs_generator.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_generator.c	Tue Aug 30 12:02:31 2016 +0300
@@ -300,6 +300,8 @@ njs_generator(njs_vm_t *vm, njs_parser_t
     case NJS_TOKEN_IS_FINITE:
     case NJS_TOKEN_PARSE_INT:
     case NJS_TOKEN_PARSE_FLOAT:
+    case NJS_TOKEN_ENCODE_URI:
+    case NJS_TOKEN_ENCODE_URI_COMPONENT:
         return njs_generate_builtin_object(vm, parser, node);
 
     case NJS_TOKEN_FUNCTION:
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_lexer_keyword.c	Tue Aug 30 12:02:31 2016 +0300
@@ -93,6 +93,8 @@ static const njs_keyword_t  njs_keywords
     { nxt_string("isFinite"),      NJS_TOKEN_IS_FINITE, 0 },
     { nxt_string("parseInt"),      NJS_TOKEN_PARSE_INT, 0 },
     { nxt_string("parseFloat"),    NJS_TOKEN_PARSE_FLOAT, 0 },
+    { nxt_string("encodeURI"),     NJS_TOKEN_ENCODE_URI, 0 },
+    { nxt_string("encodeURIComponent"),  NJS_TOKEN_ENCODE_URI_COMPONENT, 0 },
 
     /* Reserved words. */
 
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_parser.c
--- a/njs/njs_parser.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_parser.c	Tue Aug 30 12:02:31 2016 +0300
@@ -1671,6 +1671,8 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
     case NJS_TOKEN_IS_FINITE:
     case NJS_TOKEN_PARSE_INT:
     case NJS_TOKEN_PARSE_FLOAT:
+    case NJS_TOKEN_ENCODE_URI:
+    case NJS_TOKEN_ENCODE_URI_COMPONENT:
         return njs_parser_builtin_function(vm, parser, node);
 
     default:
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_parser.h
--- a/njs/njs_parser.h	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_parser.h	Tue Aug 30 12:02:31 2016 +0300
@@ -181,6 +181,8 @@ typedef enum {
     NJS_TOKEN_IS_FINITE,
     NJS_TOKEN_PARSE_INT,
     NJS_TOKEN_PARSE_FLOAT,
+    NJS_TOKEN_ENCODE_URI,
+    NJS_TOKEN_ENCODE_URI_COMPONENT,
 
     NJS_TOKEN_RESERVED,
 } njs_token_t;
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_string.c
--- a/njs/njs_string.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_string.c	Tue Aug 30 12:02:31 2016 +0300
@@ -45,6 +45,8 @@ static njs_ret_t njs_string_match_multip
     njs_regexp_pattern_t *pattern);
 static njs_ret_t njs_string_split_part_add(njs_vm_t *vm, njs_array_t *array,
     u_char *start, size_t size, nxt_uint_t utf8);
+static njs_ret_t njs_string_encode(njs_vm_t *vm, njs_value_t *value,
+    const uint32_t *escape);
 
 
 njs_ret_t
@@ -2105,6 +2107,137 @@ const njs_object_init_t  njs_string_prot
 };
 
 
+/*
+ * encodeURI(string)
+ */
+
+njs_ret_t
+njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+    njs_index_t unused)
+{
+    static const uint32_t  escape[] = {
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+
+                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+        0x50000025,  /* 0101 0000 0000 0000  0000 0000 0010 0101 */
+
+                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+        0x78000000,  /* 0111 1000 0000 0000  0000 0000 0000 0000 */
+
+                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+        0xb8000001,  /* 1011 1000 0000 0000  0000 0000 0000 0001 */
+
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+    };
+
+    if (nargs > 1) {
+        return njs_string_encode(vm, &args[1], escape);
+    }
+
+    vm->retval = njs_string_void;
+
+    return NXT_OK;
+}
+
+
+/*
+ * encodeURIComponent(string)
+ */
+
+njs_ret_t
+njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused)
+{
+    static const uint32_t  escape[] = {
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+
+                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+        0xfc00987d,  /* 1111 1100 0000 0000  1001 1000 0111 1101 */
+
+                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+        0x78000001,  /* 0111 1000 0000 0000  0000 0000 0000 0001 */
+
+                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+        0xb8000001,  /* 1011 1000 0000 0000  0000 0000 0000 0001 */
+
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff,  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+    };
+
+    if (nargs > 1) {
+        return njs_string_encode(vm, &args[1], escape);
+    }
+
+    vm->retval = njs_string_void;
+
+    return NXT_OK;
+}
+
+
+static njs_ret_t
+njs_string_encode(njs_vm_t *vm, njs_value_t *value, const uint32_t *escape)
+{
+    u_char               byte, *src, *dst;
+    size_t               n, size;
+    njs_string_prop_t    string;
+    static const u_char  hex[16] = "0123456789ABCDEF";
+
+    nxt_prefetch(escape);
+
+    (void) njs_string_prop(&string, value);
+
+    src = string.start;
+    n = 0;
+
+    for (size = string.size; size != 0; size--) {
+        byte = *src++;
+
+        if ((escape[byte >> 5] & ((uint32_t) 1 << (byte & 0x1f))) != 0) {
+            n += 2;
+        }
+    }
+
+    if (n == 0) {
+        /* GC: retain src. */
+        vm->retval = *value;
+        return NXT_OK;
+    }
+
+    size = string.size + n;
+
+    dst = njs_string_alloc(vm, &vm->retval, size, size);
+    if (nxt_slow_path(dst == NULL)) {
+        return NXT_ERROR;
+    }
+
+    size = string.size;
+    src = string.start;
+
+    do {
+        byte = *src++;
+
+        if ((escape[byte >> 5] & ((uint32_t) 1 << (byte & 0x1f))) != 0) {
+            *dst++ = '%';
+            *dst++ = hex[byte >> 4];
+            *dst++ = hex[byte & 0xf];
+
+        } else {
+            *dst++ = byte;
+        }
+
+        size--;
+
+    } while (size != 0);
+
+    return NXT_OK;
+}
+
+
 static nxt_int_t
 njs_values_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
 {
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_string.h
--- a/njs/njs_string.h	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_string.h	Tue Aug 30 12:02:31 2016 +0300
@@ -104,6 +104,10 @@ nxt_noinline uint32_t njs_string_index(n
 njs_ret_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
     const njs_value_t *src);
 double njs_string_to_number(njs_value_t *value, nxt_bool_t exact);
+njs_ret_t njs_string_encode_uri(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
+njs_ret_t njs_string_encode_uri_component(njs_vm_t *vm, njs_value_t *args,
+    nxt_uint_t nargs, njs_index_t unused);
 
 njs_index_t njs_value_index(njs_vm_t *vm, njs_parser_t *parser,
     const njs_value_t *src);
diff -r 7cce82b6b40b -r d63ecb57f164 njs/njs_vm.h
--- a/njs/njs_vm.h	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/njs_vm.h	Tue Aug 30 12:02:31 2016 +0300
@@ -668,7 +668,7 @@ typedef enum {
 
 
 enum njs_prototypes_e {
-    NJS_PROTOTYPE_OBJECT =     0,
+    NJS_PROTOTYPE_OBJECT = 0,
     NJS_PROTOTYPE_ARRAY,
     NJS_PROTOTYPE_BOOLEAN,
     NJS_PROTOTYPE_NUMBER,
@@ -698,19 +698,21 @@ enum njs_constructor_e {
 
 
 enum njs_object_e {
-    NJS_OBJECT_MATH =          0,
+    NJS_OBJECT_MATH = 0,
 #define NJS_OBJECT_MAX         (NJS_OBJECT_MATH + 1)
 };
 
 
 enum njs_function_e {
-    NJS_FUNCTION_EVAL =        0,
-    NJS_FUNCTION_TO_STRING =   1,
-    NJS_FUNCTION_IS_NAN =      2,
-    NJS_FUNCTION_IS_FINITE =   3,
-    NJS_FUNCTION_PARSE_INT =   4,
-    NJS_FUNCTION_PARSE_FLOAT = 5,
-#define NJS_FUNCTION_MAX       (NJS_FUNCTION_PARSE_FLOAT + 1)
+    NJS_FUNCTION_EVAL = 0,
+    NJS_FUNCTION_TO_STRING,
+    NJS_FUNCTION_IS_NAN,
+    NJS_FUNCTION_IS_FINITE,
+    NJS_FUNCTION_PARSE_INT,
+    NJS_FUNCTION_PARSE_FLOAT,
+    NJS_FUNCTION_STRING_ENCODE_URI,
+    NJS_FUNCTION_STRING_ENCODE_URI_COMPONENT,
+#define NJS_FUNCTION_MAX       (NJS_FUNCTION_STRING_ENCODE_URI_COMPONENT + 1)
 };
 
 
diff -r 7cce82b6b40b -r d63ecb57f164 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Tue Aug 16 19:13:41 2016 +0300
+++ b/njs/test/njs_unit_test.c	Tue Aug 30 12:02:31 2016 +0300
@@ -3297,6 +3297,18 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("'0123456789'.split('').reverse().join('')"),
       nxt_string("9876543210") },
 
+    { nxt_string("encodeURI()"),
+      nxt_string("undefined")},
+
+    { nxt_string("encodeURI('012абв')"),
+      nxt_string("012%D0%B0%D0%B1%D0%B2")},
+
+    { nxt_string("encodeURI('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"),
+      nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B@?%3E=%3C;:/.-,+*)('&%25$#%22!%20")},
+
+    { nxt_string("encodeURIComponent('~}|{`_^]\\\\[@?>=<;:/.-,+*)(\\\'&%$#\"! ')"),
+      nxt_string("~%7D%7C%7B%60_%5E%5D%5C%5B%40%3F%3E%3D%3C%3B%3A%2F.-%2C%2B*)('%26%25%24%23%22!%20")},
+
     /* Functions. */
 
     { nxt_string("return"),


More information about the nginx-devel mailing list