]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
start of %func()
authorAlan T. DeKok <aland@freeradius.org>
Mon, 25 Sep 2023 21:40:05 +0000 (17:40 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 26 Sep 2023 12:51:09 +0000 (08:51 -0400)
src/bin/unit_test_attribute.c
src/lib/server/tmpl.h
src/lib/unlang/xlat_tokenize.c
src/tests/unit/xlat/func.txt [new file with mode: 0644]

index b31a3d55e8a3d9bb49d800f183a0659d15cb25d4..74a5d76e95788626521b441c2ff7b90955466418 100644 (file)
@@ -2257,6 +2257,49 @@ static size_t command_max_buffer_size(command_result_t *result, command_file_ctx
        RETURN_OK(snprintf(data, COMMAND_OUTPUT_MAX, "%ld", size));
 }
 
+/** Set or clear migration flags.
+ *
+ */
+static size_t command_migrate(command_result_t *result, command_file_ctx_t *cc,
+                             UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
+{
+       char *p;
+       bool *out;
+
+       fr_skip_whitespace(in);
+       p = in;
+
+       if (strncmp(p, "xlat_new_functions", sizeof("xlat_new_functions") - 1) == 0) {
+               p += sizeof("xlat_new_functions") - 1;
+               out = &cc->tmpl_rules.xlat.new_functions;
+
+       } else {
+               fr_strerror_const("Unknown migration flag");
+               RETURN_PARSE_ERROR(0);
+       }
+
+       fr_skip_whitespace(p);
+       if (*p != '=') {
+               fr_strerror_const("Missing '=' after flag");
+               RETURN_PARSE_ERROR(0);
+       }
+       p++;
+
+       fr_skip_whitespace(p);
+       if ((strcmp(p, "yes") == 0) || (strcmp(p, "true") == 0) || (strcmp(p, "1") == 0)) {
+               *out = true;
+
+       } else if ((strcmp(p, "no") == 0) || (strcmp(p, "false") == 0) || (strcmp(p, "0") == 0)) {
+               *out = false;
+
+       } else {
+               fr_strerror_const("Invalid value for flag");
+               RETURN_PARSE_ERROR(0);
+       }
+
+       RETURN_OK(0);
+}
+
 /** Skip the test file if we're missing a particular feature
  *
  */
@@ -2649,6 +2692,7 @@ static size_t command_xlat_normalise(command_result_t *result, command_file_ctx_
                                                .list_def = request_attr_request,
                                                .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
                                        },
+                                       .xlat = cc->tmpl_rules.xlat,
                                });
        if (dec_len <= 0) {
                fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
@@ -2930,6 +2974,11 @@ static fr_table_ptr_sorted_t     commands[] = {
                                        .usage = "max-buffer-size[ <intger>]",
                                        .description = "Limit the maximum temporary buffer space available for any command which uses it"
                                }},
+       { L("migrate "),        &(command_entry_t){
+                                       .func = command_migrate,
+                                       .usage = "migrate <flag>=<value>",
+                                       .description = "Set migration flag"
+                               }},
        { L("need-feature "),   &(command_entry_t){
                                        .func = command_need_feature,
                                        .usage = "need-feature <feature>",
index 4d00e544b669b6de3665dccb4bb132c1ab791f39..fea8a0d121fe571b08b8b3bc0371d93edbfbf6b7 100644 (file)
@@ -328,6 +328,7 @@ struct tmpl_attr_rules_s {
 struct tmpl_xlat_rules_s {
        fr_event_list_t         *runtime_el;            //!< The eventlist to use for runtime instantiation
                                                        ///< of xlats.
+       bool                    new_functions;          //!< new function syntax
 };
 
 /** Optional arguments passed to vp_tmpl functions
index 4f558439b4d670a8de326a1dd362da074ce510f3..1c48c3c5e7f73096a420fc06f8f7f5ab81994ce3 100644 (file)
@@ -258,6 +258,12 @@ int xlat_validate_function_mono(xlat_exp_t *node)
        return 0;
 }
 
+static bool const func_chars[UINT8_MAX + 1] = {
+       SBUFF_CHAR_CLASS_ALPHA_NUM,
+       ['.'] = true, ['-'] = true, ['_'] = true,
+};
+
+
 /** Parse an xlat function and its child argument
  *
  * Parses a function call string in the format
@@ -279,11 +285,6 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head,
         *      Special characters, spaces, etc. cannot be
         *      module names.
         */
-       static bool const       func_chars[UINT8_MAX + 1] = {
-                                       SBUFF_CHAR_CLASS_ALPHA_NUM,
-                                       ['.'] = true, ['-'] = true, ['_'] = true,
-                               };
-
        XLAT_DEBUG("FUNC-MONO <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
 
        /*
@@ -541,11 +542,6 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
         *      Special characters, spaces, etc. cannot be
         *      module names.
         */
-       static bool const       func_chars[UINT8_MAX + 1] = {
-                                       SBUFF_CHAR_CLASS_ALPHA_NUM,
-                                       ['.'] = true, ['-'] = true, ['_'] = true,
-                               };
-
        XLAT_DEBUG("FUNC-ARGS <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
 
        /*
@@ -1006,6 +1002,74 @@ static int xlat_tokenize_string(xlat_exp_head_t *head,
                        if (slen == 0) TALLOC_FREE(node); /* Free the empty node */
 
                        if (xlat_tokenize_function_args(head, in, t_rules) < 0) goto error;
+                       continue;
+               }               
+
+               /*
+                *      More migration hacks: allow %foo(...)
+                */
+               if (t_rules->xlat.new_functions && fr_sbuff_next_if_char(in, '%')) {
+                       fr_sbuff_marker_t m_s;
+
+                       fr_sbuff_marker(&m_s, in);
+                       fr_sbuff_adv_past_allowed(in, SIZE_MAX, func_chars, NULL);
+
+                       /*
+                        *      Special-case: %% is just %
+                        */
+                       if ((fr_sbuff_diff(in, &m_s) == 0) && fr_sbuff_next_if_char(in, '%')) {
+                               goto one_letter;
+                       }
+
+                       if (fr_sbuff_diff(in, &m_s) == 1) {
+                               if (!fr_sbuff_next_if_char(in, '(')) {
+                                       fr_strerror_const("Missing '('");
+                                       goto error;
+                               }
+
+                               if (!fr_sbuff_next_if_char(in, ')')) {
+                                       fr_strerror_const("Missing ')'");
+                                       goto error;
+                               }
+
+                       one_letter:
+                               fr_sbuff_marker_release(&m_s);
+
+                               XLAT_DEBUG("ONE-LETTER <-- %pV",
+                                          fr_box_strvalue_len(str, talloc_array_length(str) - 1));
+
+                               if (slen == 0) {
+                                       talloc_free_children(node);     /* re-use empty nodes */
+                               } else {
+                                       node = xlat_exp_alloc_null(head);
+                               }
+
+                               xlat_exp_set_type(node, XLAT_ONE_LETTER);
+                               xlat_exp_set_name(node, fr_sbuff_current(&m_s), 1);
+
+#ifdef STATIC_ANALYZER
+                               if (!node->fmt) goto error;
+#endif
+
+                               /*
+                                *      %% is pure.  Everything else is not.
+                                */
+                               node->flags.pure = (node->fmt[0] == '%');
+
+                               xlat_exp_insert_tail(head, node);
+                               continue;
+                       }
+
+                       if (!fr_sbuff_next_if_char(in, '(')) {
+                               fr_strerror_const("Missing '('");
+                               goto error;
+                       }
+
+                       /*
+                        *      The next bit is not finished.
+                        */
+                       fr_assert(0);
+
                        continue;
                }
 
diff --git a/src/tests/unit/xlat/func.txt b/src/tests/unit/xlat/func.txt
new file mode 100644 (file)
index 0000000..5d311ee
--- /dev/null
@@ -0,0 +1,18 @@
+#
+#  This file tests the new parser for the xlat functions.
+#
+proto-dictionary radius
+
+migrate xlat_new_functions = yes
+
+#
+#  Input is new.  Output is old.
+#
+xlat %Y()
+match %Y
+
+#xlat %md5(foo)
+#match foo
+
+count
+match 4