From: Nick Porter Date: Mon, 29 Mar 2021 14:22:01 +0000 (+0100) Subject: v4: Define arguments for %(length: ) xlat (#4037) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7692ab6cd59420c1a8403ec6fec2e94e89f55aa9;p=thirdparty%2Ffreeradius-server.git v4: Define arguments for %(length: ) xlat (#4037) * Define arguments for %(length: ) xlat * Update tests that use %(length: ) xlat * Update docs for %(length: ) xlat * Make xlat_fmt_aprint() reflect original call syntax * Make xlat_print reflect original call syntax --- diff --git a/doc/antora/modules/reference/pages/xlat/builtin.adoc b/doc/antora/modules/reference/pages/xlat/builtin.adoc index 3f25ea83644..f4912202b96 100644 --- a/doc/antora/modules/reference/pages/xlat/builtin.adoc +++ b/doc/antora/modules/reference/pages/xlat/builtin.adoc @@ -6,7 +6,7 @@ which operate on inputs, and produce an output. == Attribute Manipulation -=== %{length: ... } +=== %(length: ... ) The `length` expansion returns the size of the input as an integer. When the input is a string, then the output is identical to the @@ -27,8 +27,8 @@ update control { } update reply { - &Reply-Message := "The length of %{control.Tmp-String-0} is %{length:&control.Tmp-String-0}" - &Reply-Message += "The length of %{control.Framed-IP-Address} is %{length:&control.Framed-IP-Address}" + &Reply-Message := "The length of %{control.Tmp-String-0} is %(length:&control.Tmp-String-0)" + &Reply-Message += "The length of %{control.Framed-IP-Address} is %(length:&control.Framed-IP-Address)" } ---- diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index 356b7f1302c..ffe64276e03 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -1870,12 +1870,17 @@ static xlat_action_t xlat_func_join(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } +static xlat_arg_parser_t const xlat_func_length_args[] = { + { .single = true, .variadic = true, .type = FR_TYPE_VOID }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** Return the on-the-wire size of the boxes in bytes * * Example: @verbatim -"%{length:foobar}" == 6 -"%{length:%{bin:0102030005060708}}" == 8 +"%(length:foobar)" == 6 +"%(length:%{bin:0102030005060708})" == 8 @endverbatim * * @see #xlat_func_strlen @@ -1887,12 +1892,9 @@ static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED void *xlat_thread_inst, fr_value_box_list_t *in) { - fr_value_box_t *vb; - fr_dcursor_t cursor; + fr_value_box_t *vb = NULL; - for (vb = fr_dcursor_talloc_init(&cursor, in, fr_value_box_t); - vb; - vb = fr_dcursor_next(&cursor)) { + while ((vb = fr_dlist_next(in, vb))) { fr_value_box_t *my; MEM(my = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL, false)); @@ -3103,6 +3105,7 @@ do { \ XLAT_REGISTER_ARGS("hmacsha1", xlat_func_hmac_sha1, xlat_hmac_args); XLAT_REGISTER_ARGS("integer", xlat_func_integer, xlat_func_integer_args); XLAT_REGISTER_ARGS("join", xlat_func_join, xlat_func_join_args); + XLAT_REGISTER_ARGS("length", xlat_func_length, xlat_func_length_args); XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, xlat_func_next_time_args); XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, xlat_func_pairs_args); XLAT_REGISTER_ARGS("lpad", xlat_func_lpad, xlat_func_pad_args); @@ -3119,7 +3122,6 @@ do { \ XLAT_REGISTER_MONO("base64decode", xlat_func_base64_decode, xlat_func_base64_decode_arg); XLAT_REGISTER_MONO("bin", xlat_func_bin, xlat_func_bin_arg); XLAT_REGISTER_MONO("hex", xlat_func_hex, xlat_func_hex_arg); - xlat_register(NULL, "length", xlat_func_length, false); XLAT_REGISTER_MONO("map", xlat_func_map, xlat_func_map_arg); XLAT_REGISTER_MONO("md4", xlat_func_md4, xlat_func_md4_arg); XLAT_REGISTER_MONO("md5", xlat_func_md5, xlat_func_md5_arg); diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index fc8771649a1..7945478f9d9 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -123,29 +123,43 @@ static char *xlat_fmt_aprint(TALLOC_CTX *ctx, xlat_exp_t const *node) xlat_exp_t const *child = node->child; char *out, *n_out; TALLOC_CTX *pool; + char open = '{', close = '}'; + bool first_done = false; - if (!child) return talloc_asprintf(ctx, "%%{%s:}", node->call.func->name); + if (node->call.func->input_type == XLAT_INPUT_ARGS) { + open = '('; + close = ')'; + } + if (!child) return talloc_asprintf(ctx, "%%%c%s:%c", open, node->call.func->name, close); - out = talloc_asprintf(ctx, "%%{%s:", node->call.func->name); + out = talloc_asprintf(ctx, "%%%c%s:", open, node->call.func->name); pool = talloc_pool(NULL, 128); /* Size of a single child (probably ok...) */ do { char *child_str; child_str = xlat_fmt_aprint(pool, child); if (child_str) { - n_out = talloc_buffer_append_buffer(ctx, out, child_str); - if (!n_out) { - talloc_free(out); - talloc_free(pool); - return NULL; + if ((first_done) && (node->call.func->input_type == XLAT_INPUT_ARGS)) { + n_out = talloc_strdup_append_buffer(out, " "); + if (!n_out) { + child_error: + talloc_free(out); + talloc_free(pool); + return NULL; + } + out = n_out; } + + n_out = talloc_buffer_append_buffer(ctx, out, child_str); + if (!n_out) goto child_error; out = n_out; + first_done = true; } talloc_free_children(pool); /* Clear pool contents */ } while ((child = child->next)); talloc_free(pool); - n_out = talloc_strdup_append_buffer(out, "}"); + n_out = talloc_strndup_append_buffer(out, &close, 1); if (!n_out) { talloc_free(out); return NULL; diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 483145a2840..92372381643 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -1174,6 +1174,7 @@ ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_t const *head, fr_sbuff_escape_rule ssize_t slen; size_t at_in = fr_sbuff_used_total(out); xlat_exp_t const *node = head; + char close; if (!node) return 0; @@ -1198,7 +1199,13 @@ ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_t const *head, fr_sbuff_escape_rule break; } - FR_SBUFF_IN_STRCPY_LITERAL_RETURN(out, "%{"); + if ((node->type == XLAT_FUNC) && (node->call.func->input_type == XLAT_INPUT_ARGS)) { + FR_SBUFF_IN_STRCPY_LITERAL_RETURN(out, "%("); + close = ')'; + } else { + FR_SBUFF_IN_STRCPY_LITERAL_RETURN(out, "%{"); + close = '}'; + } switch (node->type) { case XLAT_ATTRIBUTE: slen = tmpl_attr_print(out, node->attr, TMPL_ATTR_REF_PREFIX_NO); @@ -1259,7 +1266,7 @@ ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_t const *head, fr_sbuff_escape_rule fr_assert_fail(NULL); break; } - FR_SBUFF_IN_CHAR_RETURN(out, '}'); + FR_SBUFF_IN_CHAR_RETURN(out, close); next: node = node->next; } diff --git a/src/tests/keywords/escape-sequences b/src/tests/keywords/escape-sequences index 6a73bc30e9d..ffb8a0e7f4c 100644 --- a/src/tests/keywords/escape-sequences +++ b/src/tests/keywords/escape-sequences @@ -17,11 +17,11 @@ update request { } -if ("%{length:%{Tmp-String-0}}" != 39) { +if ("%(length:%{Tmp-String-0})" != 39) { test_fail } -if ("%{length:%{Tmp-String-1}}" != 42) { +if ("%(length:%{Tmp-String-1})" != 42) { test_fail } diff --git a/src/tests/keywords/length b/src/tests/keywords/length index b3570c74203..157c2de0a07 100644 --- a/src/tests/keywords/length +++ b/src/tests/keywords/length @@ -21,7 +21,7 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' } update request { - &Tmp-Integer-0 := "%{length:%{Tmp-String-0}}" + &Tmp-Integer-0 := "%(length:%{Tmp-String-0})" } if (&Tmp-Integer-0 != 260) { @@ -29,14 +29,14 @@ if (&Tmp-Integer-0 != 260) { } update request { - &Tmp-Integer-0 := "%{length:%{Tmp-String-2}}" - &Tmp-Integer-1 := "%{length:%{Tmp-Octets-0}}" - &Tmp-Integer-2 := "%{length:%{Tmp-IP-Address-0}}" - &Tmp-Integer-4 := "%{length:%{Tmp-Integer-0}}" - &Tmp-Integer-6 := "%{length:%{Tmp-Cast-Ifid}}" - &Tmp-Integer-7 := "%{length:%{Tmp-Cast-IPv6Addr}}" - &Tmp-Integer-8 := "%{length:%{Tmp-Cast-IPv6Prefix}}" - &Tmp-Integer-9 := "%{length:%{Tmp-Cast-Byte}}" + &Tmp-Integer-0 := "%(length:%{Tmp-String-2})" + &Tmp-Integer-1 := "%(length:%{Tmp-Octets-0})" + &Tmp-Integer-2 := "%(length:%{Tmp-IP-Address-0})" + &Tmp-Integer-4 := "%(length:%{Tmp-Integer-0})" + &Tmp-Integer-6 := "%(length:%{Tmp-Cast-Ifid})" + &Tmp-Integer-7 := "%(length:%{Tmp-Cast-IPv6Addr})" + &Tmp-Integer-8 := "%(length:%{Tmp-Cast-IPv6Prefix})" + &Tmp-Integer-9 := "%(length:%{Tmp-Cast-Byte})" } # String - bin 0x39383730 @@ -81,10 +81,10 @@ if (&Tmp-Integer-9 != 1) { } update request { - &Tmp-Integer-0 := "%{length:%{Tmp-Cast-Short}}" - &Tmp-Integer-1 := "%{length:%{Tmp-Cast-Ether}}" - &Tmp-Integer-2 := "%{length:%{Tmp-Cast-Integer64}}" - &Tmp-Integer-3 := "%{length:%{Tmp-Cast-IPv4Prefix}}" + &Tmp-Integer-0 := "%(length:%{Tmp-Cast-Short})" + &Tmp-Integer-1 := "%(length:%{Tmp-Cast-Ether})" + &Tmp-Integer-2 := "%(length:%{Tmp-Cast-Integer64})" + &Tmp-Integer-3 := "%(length:%{Tmp-Cast-IPv4Prefix})" } # short - bin 0x373b diff --git a/src/tests/keywords/randstr b/src/tests/keywords/randstr index 175b72652b6..090bb15d819 100644 --- a/src/tests/keywords/randstr +++ b/src/tests/keywords/randstr @@ -42,7 +42,7 @@ if (&Tmp-String-4 != "") { # # Check repetition of binary output # -if ("%{length:%{Tmp-String-5}}" != 10) { +if ("%(length:%{Tmp-String-5})" != 10) { test_fail } diff --git a/src/tests/keywords/truncation b/src/tests/keywords/truncation index bdcff618b08..45b58528150 100644 --- a/src/tests/keywords/truncation +++ b/src/tests/keywords/truncation @@ -76,7 +76,7 @@ a02f4a3ab98d75992d68a15d393387fe9ef01041569570ad6fe884764e55567311bcacfcffae7655 # Actual length of octet string is 4083 bytes update request { - &Tmp-Integer-0 := "%{length:%{Tmp-Octets-0}}" + &Tmp-Integer-0 := "%(length:%{Tmp-Octets-0})" } if (&Tmp-Integer-0 != 4083) { @@ -92,7 +92,7 @@ update request { &Tmp-String-0 := "%{1}" } -if ("%{length:%{Tmp-String-0}}" != 8166) { +if ("%(length:%{Tmp-String-0})" != 8166) { test_fail } diff --git a/src/tests/keywords/xlat-sub b/src/tests/keywords/xlat-sub index 61a9e325745..5b8db068d04 100644 --- a/src/tests/keywords/xlat-sub +++ b/src/tests/keywords/xlat-sub @@ -82,7 +82,7 @@ if ("%(sub:%{Tmp-String-0} /z/ b)" != 'aaa') { # # Check that newlines really are newlines -if ("%{length:%{Tmp-String-1}}" != 3) { +if ("%(length:%{Tmp-String-1})" != 3) { test_fail } diff --git a/src/tests/modules/cache_rbtree/cache-bin.unlang b/src/tests/modules/cache_rbtree/cache-bin.unlang index abe5d3eb007..9136bacf8e1 100644 --- a/src/tests/modules/cache_rbtree/cache-bin.unlang +++ b/src/tests/modules/cache_rbtree/cache-bin.unlang @@ -60,7 +60,7 @@ else { test_fail } -if ("%{length:%{Tmp-String-1}}" == 11) { +if ("%(length:%{Tmp-String-1})" == 11) { test_pass } else { @@ -91,7 +91,7 @@ else { test_fail } -if ("%{length:%{Tmp-String-1}}" == 7) { +if ("%(length:%{Tmp-String-1})" == 7) { test_pass } else { @@ -159,7 +159,7 @@ else { test_fail } -if ("%{length:%{Tmp-String-1}}" == 11) { +if ("%(length:%{Tmp-String-1})" == 11) { test_pass } else { @@ -190,7 +190,7 @@ else { test_fail } -if ("%{length:%{Tmp-String-1}}" == 7) { +if ("%(length:%{Tmp-String-1})" == 7) { test_pass } else { diff --git a/src/tests/unit/xlat/base.txt b/src/tests/unit/xlat/base.txt index 9fc7358d898..bb2b790b78b 100644 --- a/src/tests/unit/xlat/base.txt +++ b/src/tests/unit/xlat/base.txt @@ -132,13 +132,13 @@ match \"%{reply.Vendor-Specific.3GPP.IMSI[2]}\" xlat /([A-Z0-9\\-]*)_%{Calling-Station-Id}/ match /([A-Z0-9\\-]*)_%{Calling-Station-Id}/ -xlat %{length} -match %{length} +xlat %(length:) +match %(length:) -xlat %{length: +xlat %(length: match ERROR offset 9: Missing closing brace -xlat %{length:1 + 2 +xlat %(length:1 + 2 match ERROR offset 14: Missing closing brace xlat \"%t\tfoo\"