From: Arran Cudbard-Bell Date: Mon, 25 Oct 2021 17:53:01 +0000 (-0400) Subject: Move tmpl parse rules to value.c X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f7ae771766049ec4901705de366943fa52b98d7;p=thirdparty%2Ffreeradius-server.git Move tmpl parse rules to value.c --- diff --git a/src/lib/server/cf_parse.c b/src/lib/server/cf_parse.c index 609585e3c38..9906522911d 100644 --- a/src/lib/server/cf_parse.c +++ b/src/lib/server/cf_parse.c @@ -244,7 +244,7 @@ int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM } slen = tmpl_afrom_substr(cp, &vpt, &sbuff, cp->rhs_quote, - tmpl_parse_rules_unquoted[cp->rhs_quote], + value_parse_rules_unquoted[cp->rhs_quote], &rules); if (!vpt) goto tmpl_error; diff --git a/src/lib/server/cond_tokenize.c b/src/lib/server/cond_tokenize.c index 3542c19f452..8e4448b0637 100644 --- a/src/lib/server/cond_tokenize.c +++ b/src/lib/server/cond_tokenize.c @@ -1008,7 +1008,7 @@ static ssize_t cond_tokenize_operand(fr_cond_t *c, tmpl_t **out, #ifdef HAVE_REGEX case T_SOLIDUS_QUOTED_STRING: #endif - p_rules = tmpl_parse_rules_quoted[type]; + p_rules = value_parse_rules_quoted[type]; break; #ifndef HAVE_REGEX case T_SOLIDUS_QUOTED_STRING: diff --git a/src/lib/server/map.c b/src/lib/server/map.c index 9fc79561588..84f7093110d 100644 --- a/src/lib/server/map.c +++ b/src/lib/server/map.c @@ -127,7 +127,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp, slen = tmpl_afrom_substr(ctx, &map->lhs, &FR_SBUFF_IN(attr, talloc_array_length(attr) - 1), type, - tmpl_parse_rules_unquoted[type], /* We're not searching for quotes */ + value_parse_rules_unquoted[type], /* We're not searching for quotes */ lhs_rules); if (slen <= 0) { char *spaces, *text; @@ -167,7 +167,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp, slen = tmpl_afrom_substr(map, &map->rhs, &FR_SBUFF_IN(value, strlen(value)), type, - tmpl_parse_rules_unquoted[type], /* We're not searching for quotes */ + value_parse_rules_unquoted[type], /* We're not searching for quotes */ rhs_rules); if (slen < 0) { marker_subject = value; @@ -281,10 +281,10 @@ fr_sbuff_parse_rules_t const map_parse_rules_bareword_quoted = { fr_sbuff_parse_rules_t const *map_parse_rules_quoted[T_TOKEN_LAST] = { [T_BARE_WORD] = &map_parse_rules_bareword_quoted, - [T_DOUBLE_QUOTED_STRING] = &tmpl_parse_rules_double_quoted, - [T_SINGLE_QUOTED_STRING] = &tmpl_parse_rules_single_quoted, - [T_SOLIDUS_QUOTED_STRING] = &tmpl_parse_rules_solidus_quoted, - [T_BACK_QUOTED_STRING] = &tmpl_parse_rules_backtick_quoted + [T_DOUBLE_QUOTED_STRING] = &value_parse_rules_double_quoted, + [T_SINGLE_QUOTED_STRING] = &value_parse_rules_single_quoted, + [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_quoted, + [T_BACK_QUOTED_STRING] = &value_parse_rules_backtick_quoted }; /** Parse sbuff into (which may contain refs) to map_t. @@ -350,7 +350,7 @@ ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuf case T_BACK_QUOTED_STRING: case T_SINGLE_QUOTED_STRING: slen = tmpl_afrom_substr(map, &map->lhs, &our_in, token, - tmpl_parse_rules_quoted[token], lhs_rules); + value_parse_rules_quoted[token], lhs_rules); break; default: @@ -542,11 +542,11 @@ parse_rhs: case T_BACK_QUOTED_STRING: case T_SINGLE_QUOTED_STRING: slen = tmpl_afrom_substr(map, &map->rhs, &our_in, token, - tmpl_parse_rules_quoted[token], rhs_rules); + value_parse_rules_quoted[token], rhs_rules); break; default: - if (!p_rules) p_rules = &tmpl_parse_rules_bareword_quoted; + if (!p_rules) p_rules = &value_parse_rules_bareword_quoted; /* * Use the RHS termination rules ONLY for bare diff --git a/src/lib/server/tmpl.h b/src/lib/server/tmpl.h index 8207356dbce..192da0a7509 100644 --- a/src/lib/server/tmpl.h +++ b/src/lib/server/tmpl.h @@ -559,20 +559,6 @@ typedef struct { ///< ars referenced. } tmpl_attr_extent_t; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_bareword_unquoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_double_unquoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_single_unquoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_solidus_unquoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_backtick_unquoted; -extern fr_sbuff_parse_rules_t const *tmpl_parse_rules_unquoted[T_TOKEN_LAST]; - -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_bareword_quoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_double_quoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_single_quoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_solidus_quoted; -extern fr_sbuff_parse_rules_t const tmpl_parse_rules_backtick_quoted; -extern fr_sbuff_parse_rules_t const *tmpl_parse_rules_quoted[T_TOKEN_LAST]; - /** Convenience macro for printing a meaningful assert message when we get a bad tmpl type */ #define tmpl_assert_type(_cond) \ diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index fa24bde4e6b..d3bf4d61ac2 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -40,6 +40,18 @@ RCSID("$Id$") #include +/** Default parser rules + * + * Because this is getting to be a ridiculous number of parsing rules + * to pass in via arguments. + * + * Defaults are used if a NULL rules pointer is passed to the parsing function. + */ +static tmpl_rules_t const default_attr_rules = { + .request_def = REQUEST_CURRENT, + .list_def = PAIR_LIST_REQUEST +}; + /* clang-format off */ /** Map #tmpl_type_t values to descriptive strings */ @@ -1006,123 +1018,6 @@ int tmpl_attr_afrom_list(TALLOC_CTX *ctx, tmpl_t **out, tmpl_t const *list, fr_d } /** @} */ -/** @name Produce a #tmpl_t from a string or substring - * - * @{ - */ - -/* clang-format off */ -/** Default parser rules - * - * Because this is getting to be a ridiculous number of parsing rules - * to pass in via arguments. - * - * Defaults are used if a NULL rules pointer is passed to the parsing function. - */ -static tmpl_rules_t const default_attr_rules = { - .request_def = REQUEST_CURRENT, - .list_def = PAIR_LIST_REQUEST -}; - -/** Default formatting rules - * - * Control token termination, escaping and how the tmpl is printed. - */ -fr_sbuff_parse_rules_t const tmpl_parse_rules_bareword_unquoted = { - -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_double_unquoted = { - .escapes = &fr_value_unescape_double -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_single_unquoted = { - .escapes = &fr_value_unescape_single -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_solidus_unquoted = { - .escapes = &fr_value_unescape_solidus -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_backtick_unquoted = { - .escapes = &fr_value_unescape_backtick -}; - -/** Parse rules for non-quoted strings - * - * These parse rules should be used for processing escape sequences in - * data from external data sources like SQL databases and REST APIs. - * - * They do not include terminals to stop parsing as it assumes the values - * are discreet, and not wrapped in quotes. - */ -fr_sbuff_parse_rules_t const *tmpl_parse_rules_unquoted[T_TOKEN_LAST] = { - [T_BARE_WORD] = &tmpl_parse_rules_bareword_unquoted, - [T_DOUBLE_QUOTED_STRING] = &tmpl_parse_rules_double_unquoted, - [T_SINGLE_QUOTED_STRING] = &tmpl_parse_rules_single_unquoted, - [T_SOLIDUS_QUOTED_STRING] = &tmpl_parse_rules_solidus_unquoted, - [T_BACK_QUOTED_STRING] = &tmpl_parse_rules_backtick_unquoted -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_bareword_quoted = { - .escapes = &(fr_sbuff_unescape_rules_t){ - .chr = '\\', - /* - * Allow barewords to contain whitespace - * if they're escaped. - */ - .subs = { - ['\t'] = '\t', - ['\n'] = '\n', - [' '] = ' ' - }, - .do_hex = false, - .do_oct = false - }, - .terminals = &FR_SBUFF_TERMS( - L("\t"), - L("\n"), - L(" ") - ) -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_double_quoted = { - .escapes = &fr_value_unescape_double, - .terminals = &FR_SBUFF_TERM("\"") -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_single_quoted = { - .escapes = &fr_value_unescape_single, - .terminals = &FR_SBUFF_TERM("'") -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_solidus_quoted = { - .escapes = &fr_value_unescape_solidus, - .terminals = &FR_SBUFF_TERM("/") -}; - -fr_sbuff_parse_rules_t const tmpl_parse_rules_backtick_quoted = { - .escapes = &fr_value_unescape_backtick, - .terminals = &FR_SBUFF_TERM("`") -}; - -/** Parse rules for quoted strings - * - * These parse rules should be used for internal parsing functions that - * are working with configuration files. - * - * They include appropriate quote terminals to force functions parsing - * quoted strings to return when they reach a quote character. - */ -fr_sbuff_parse_rules_t const *tmpl_parse_rules_quoted[T_TOKEN_LAST] = { - [T_BARE_WORD] = &tmpl_parse_rules_bareword_quoted, - [T_DOUBLE_QUOTED_STRING] = &tmpl_parse_rules_double_quoted, - [T_SINGLE_QUOTED_STRING] = &tmpl_parse_rules_single_quoted, - [T_SOLIDUS_QUOTED_STRING] = &tmpl_parse_rules_solidus_quoted, - [T_BACK_QUOTED_STRING] = &tmpl_parse_rules_backtick_quoted -}; -/* clang-format on */ - /** Verify, after skipping whitespace, that a substring ends in a terminal char, or ends without further chars * * @param[in] in the sbuff to check. diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index c01774e1a38..a28e3c6abb8 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -1335,12 +1335,12 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla if (p_rules && p_rules->terminals) { tmp_p_rules = (fr_sbuff_parse_rules_t){ /* Stack allocated due to CL scope */ .terminals = fr_sbuff_terminals_amerge(NULL, p_rules->terminals, - tmpl_parse_rules_bareword_quoted.terminals), - .escapes = (p_rules->escapes ? p_rules->escapes : tmpl_parse_rules_bareword_quoted.escapes) + value_parse_rules_bareword_quoted.terminals), + .escapes = (p_rules->escapes ? p_rules->escapes : value_parse_rules_bareword_quoted.escapes) }; our_p_rules = &tmp_p_rules; } else { - our_p_rules = &tmpl_parse_rules_bareword_quoted; + our_p_rules = &value_parse_rules_bareword_quoted; } /* @@ -1378,7 +1378,7 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla if (xlat_tokenize_literal(node, &node->child, &node->flags, &our_in, false, our_p_rules, t_rules) < 0) { error: - if (our_p_rules != &tmpl_parse_rules_bareword_quoted) { + if (our_p_rules != &value_parse_rules_bareword_quoted) { talloc_const_free(our_p_rules->terminals); } talloc_free(node); @@ -1395,7 +1395,7 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla */ case T_DOUBLE_QUOTED_STRING: if (xlat_tokenize_literal(node, &node->child, &node->flags, &our_in, - false, &tmpl_parse_rules_double_quoted, t_rules) < 0) goto error; + false, &value_parse_rules_double_quoted, t_rules) < 0) goto error; xlat_flags_merge(flags, &node->flags); break; @@ -1411,8 +1411,8 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla node->flags.needs_async = false; /* Literals are always needs_async */ slen = fr_sbuff_out_aunescape_until(node->child, &str, &our_in, SIZE_MAX, - tmpl_parse_rules_single_quoted.terminals, - tmpl_parse_rules_single_quoted.escapes); + value_parse_rules_single_quoted.terminals, + value_parse_rules_single_quoted.escapes); if (slen < 0) goto error; xlat_exp_set_name_buffer_shallow(node->child, str); xlat_flags_merge(flags, &node->flags); @@ -1468,7 +1468,7 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla } } - if (our_p_rules != &tmpl_parse_rules_bareword_quoted) talloc_const_free(our_p_rules->terminals); + if (our_p_rules != &value_parse_rules_bareword_quoted) talloc_const_free(our_p_rules->terminals); return fr_sbuff_set(in, &our_in); } diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 184d321dd47..99889708782 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -51,7 +51,7 @@ RCSID("$Id$") #include #include #include - +#include /** Sanity checks * @@ -491,6 +491,129 @@ fr_sbuff_escape_rules_t fr_value_escape_unprintables = { .do_oct = true }; + +/** @name Produce a #tmpl_t from a string or substring + * + * @{ + */ + +/* clang-format off */ +/** Default formatting rules + * + * Control token termination, escaping and how the tmpl is printed. + */ +fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted = { + +}; + +fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted = { + .escapes = &fr_value_unescape_double +}; + +fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted = { + .escapes = &fr_value_unescape_single +}; + +fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted = { + .escapes = &fr_value_unescape_solidus +}; + +fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted = { + .escapes = &fr_value_unescape_backtick +}; + +/** Parse rules for non-quoted strings + * + * These parse rules should be used for processing escape sequences in + * data from external data sources like SQL databases and REST APIs. + * + * They do not include terminals to stop parsing as it assumes the values + * are discreet, and not wrapped in quotes. + */ +fr_sbuff_parse_rules_t const *value_parse_rules_unquoted[T_TOKEN_LAST] = { + [T_BARE_WORD] = &value_parse_rules_bareword_unquoted, + [T_DOUBLE_QUOTED_STRING] = &value_parse_rules_double_unquoted, + [T_SINGLE_QUOTED_STRING] = &value_parse_rules_single_unquoted, + [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_unquoted, + [T_BACK_QUOTED_STRING] = &value_parse_rules_backtick_unquoted +}; + +fr_sbuff_parse_rules_t const *value_parse_rules_unquoted_char[UINT8_MAX] = { + ['\0'] = &value_parse_rules_bareword_unquoted, + ['"'] = &value_parse_rules_double_unquoted, + ['\''] = &value_parse_rules_single_unquoted, + ['/'] = &value_parse_rules_solidus_unquoted, + ['`'] = &value_parse_rules_backtick_unquoted +}; + +fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted = { + .escapes = &(fr_sbuff_unescape_rules_t){ + .chr = '\\', + /* + * Allow barewords to contain whitespace + * if they're escaped. + */ + .subs = { + ['\t'] = '\t', + ['\n'] = '\n', + [' '] = ' ' + }, + .do_hex = false, + .do_oct = false + }, + .terminals = &FR_SBUFF_TERMS( + L("\t"), + L("\n"), + L(" ") + ) +}; + +fr_sbuff_parse_rules_t const value_parse_rules_double_quoted = { + .escapes = &fr_value_unescape_double, + .terminals = &FR_SBUFF_TERM("\"") +}; + +fr_sbuff_parse_rules_t const value_parse_rules_single_quoted = { + .escapes = &fr_value_unescape_single, + .terminals = &FR_SBUFF_TERM("'") +}; + +fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted = { + .escapes = &fr_value_unescape_solidus, + .terminals = &FR_SBUFF_TERM("/") +}; + +fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted = { + .escapes = &fr_value_unescape_backtick, + .terminals = &FR_SBUFF_TERM("`") +}; + +/** Parse rules for quoted strings + * + * These parse rules should be used for internal parsing functions that + * are working with configuration files. + * + * They include appropriate quote terminals to force functions parsing + * quoted strings to return when they reach a quote character. + */ +fr_sbuff_parse_rules_t const *value_parse_rules_quoted[T_TOKEN_LAST] = { + [T_BARE_WORD] = &value_parse_rules_bareword_quoted, + [T_DOUBLE_QUOTED_STRING] = &value_parse_rules_double_quoted, + [T_SINGLE_QUOTED_STRING] = &value_parse_rules_single_quoted, + [T_SOLIDUS_QUOTED_STRING] = &value_parse_rules_solidus_quoted, + [T_BACK_QUOTED_STRING] = &value_parse_rules_backtick_quoted +}; + +fr_sbuff_parse_rules_t const *value_parse_rules_quoted_char[UINT8_MAX] = { + ['\0'] = &value_parse_rules_bareword_quoted, + ['"'] = &value_parse_rules_double_quoted, + ['\''] = &value_parse_rules_single_quoted, + ['/'] = &value_parse_rules_solidus_quoted, + ['`'] = &value_parse_rules_backtick_quoted +}; +/* clang-format on */ +/** @} */ + /** Copy flags and type data from one value box to another * * @param[in] dst to copy flags to diff --git a/src/lib/util/value.h b/src/lib/util/value.h index 1dad5074742..8cd227bee6a 100644 --- a/src/lib/util/value.h +++ b/src/lib/util/value.h @@ -350,6 +350,27 @@ typedef enum { #define fr_box_is_non_value(_x) fr_type_is_non_value((_x)->type) /** @} */ +/** @name Parsing rules for various types of string + * + * @{ + */ +extern fr_sbuff_parse_rules_t const value_parse_rules_bareword_unquoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_double_unquoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_single_unquoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_solidus_unquoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_backtick_unquoted; +extern fr_sbuff_parse_rules_t const *value_parse_rules_unquoted[T_TOKEN_LAST]; +extern fr_sbuff_parse_rules_t const *value_parse_rules_unquoted_char[UINT8_MAX]; + +extern fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_double_quoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_single_quoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_solidus_quoted; +extern fr_sbuff_parse_rules_t const value_parse_rules_backtick_quoted; +extern fr_sbuff_parse_rules_t const *value_parse_rules_quoted[T_TOKEN_LAST]; +extern fr_sbuff_parse_rules_t const *value_parse_rules_quoted_char[UINT8_MAX]; +/** @} */ + /** @name Convenience functions * * These macros and inline functions simplify working diff --git a/src/modules/rlm_smtp/rlm_smtp.c b/src/modules/rlm_smtp/rlm_smtp.c index 6e084fd0c2f..fd3e1bf999f 100644 --- a/src/modules/rlm_smtp/rlm_smtp.c +++ b/src/modules/rlm_smtp/rlm_smtp.c @@ -126,7 +126,7 @@ static int cf_table_parse_tmpl(TALLOC_CTX *ctx, void *out, UNUSED void *parent, slen = tmpl_afrom_substr(cp, &vpt, &FR_SBUFF_IN(cf_pair_value(cp), strlen(cf_pair_value(cp))), cf_pair_value_quote(cp), - tmpl_parse_rules_unquoted[cf_pair_value_quote(cp)], + value_parse_rules_unquoted[cf_pair_value_quote(cp)], &rules); /* There was an error */