From: Timo Sirainen Date: Tue, 21 Nov 2023 09:41:04 +0000 (+0200) Subject: lib: Add var_expand_with_arrays() X-Git-Tag: 2.4.1~1330 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ba4263bb6eba8df6824fb622e2bc37e2474a003;p=thirdparty%2Fdovecot%2Fcore.git lib: Add var_expand_with_arrays() --- diff --git a/src/lib/test-var-expand.c b/src/lib/test-var-expand.c index 531d51ec32..c519bd401e 100644 --- a/src/lib/test-var-expand.c +++ b/src/lib/test-var-expand.c @@ -209,6 +209,66 @@ static void test_var_expand_with_funcs(void) test_end(); } +static int +test_var_expand_arrays_func1(const char *data ATTR_UNUSED, void *context, + const char **value_r, + const char **error_r ATTR_UNUSED) +{ + test_assert(strcmp(context, "context1") == 0); + *value_r = context; + return 1; +} + +static int +test_var_expand_arrays_func2(const char *data ATTR_UNUSED, void *context, + const char **value_r, + const char **error_r ATTR_UNUSED) +{ + test_assert(strcmp(context, "context2") == 0); + *value_r = context; + return 1; +} + +static void test_var_expand_with_arrays(void) +{ + static const struct var_expand_table table1[] = { + { 'f', "firstvalue", "first" }, + { '\0', NULL, NULL } + }; + static const struct var_expand_table table2[] = { + { 's', "secondvalue", "second" }, + { '\0', NULL, NULL } + }; + static const struct var_expand_func_table func_table1[] = { + { "func1", test_var_expand_arrays_func1 }, + { NULL, NULL } + }; + static const struct var_expand_func_table func_table2[] = { + { "func2", test_var_expand_arrays_func2 }, + { NULL, NULL } + }; + + static const struct var_expand_table *tables[] = { + table1, table2, NULL + }; + static const struct var_expand_func_table *func_tables[] = { + func_table1, func_table2, NULL + }; + static void *func_contexts[] = { + "context1", "context2", + }; + const char *input = "%f, %s, %{first}, %{second}, %{func1}, %{func2}"; + const char *output = "firstvalue, secondvalue, firstvalue, secondvalue, context1, context2"; + string_t *str = t_str_new(128); + const char *error; + + test_begin("var_expand_with_arrays"); + test_assert(var_expand_with_arrays(str, input, tables, func_tables, + func_contexts, &error) == 1); + test_assert_strcmp(str_c(str), output); + test_end(); +} + static void test_var_get_key(void) { static const struct { @@ -512,6 +572,7 @@ void test_var_expand(void) test_var_expand_builtin(); test_var_get_key_range(); test_var_expand_with_funcs(); + test_var_expand_with_arrays(); test_var_get_key(); test_var_has_key(); test_var_expand_extensions(); diff --git a/src/lib/var-expand-if.c b/src/lib/var-expand-if.c index 0387840a4a..6da05a8682 100644 --- a/src/lib/var-expand-if.c +++ b/src/lib/var-expand-if.c @@ -249,11 +249,11 @@ int var_expand_if(struct var_expand_context *ctx, for(;*parms != NULL; parms++) { /* expand the parameters */ string_t *param = t_str_new(64); - if ((ret = var_expand_with_funcs(param, *parms, ctx->table, - ctx->func_table, ctx->context, - error_r)) <= 0) { + ret = var_expand_with_arrays(param, *parms, ctx->tables, + ctx->func_tables, ctx->contexts, + error_r); + if (ret <= 0) return ret; - } const char *p = str_c(param); array_push_back(¶ms, &p); } diff --git a/src/lib/var-expand-private.h b/src/lib/var-expand-private.h index f02356a322..2de885dd3a 100644 --- a/src/lib/var-expand-private.h +++ b/src/lib/var-expand-private.h @@ -2,12 +2,13 @@ #define VAR_EXPAND_PRIVATE_H 1 struct var_expand_context { - /* current variables */ - const struct var_expand_table *table; - /* caller provided function table */ - const struct var_expand_func_table *func_table; - /* caller provided context */ - void *context; + /* NULL-terminated array of variable tables */ + const struct var_expand_table *const *tables; + /* NULL-terminated array of function tables */ + const struct var_expand_func_table *const *func_tables; + /* contexts for each function table */ + void *const *contexts; + /* last offset, negative counts from end*/ int offset; /* last width, negative counts from end */ diff --git a/src/lib/var-expand.c b/src/lib/var-expand.c index 5904964bdb..1d7fe7d04c 100644 --- a/src/lib/var-expand.c +++ b/src/lib/var-expand.c @@ -176,8 +176,8 @@ var_expand_short(const struct var_expand_context *ctx, char key, { const struct var_expand_table *t; - if (ctx->table != NULL) { - for (t = ctx->table; !TABLE_LAST(t); t++) { + for (unsigned int i = 0; ctx->tables[i] != NULL; i++) { + for (t = ctx->tables[i]; !TABLE_LAST(t); t++) { if (t->key == key) { *var_r = t->value != NULL ? t->value : ""; return 1; @@ -185,13 +185,14 @@ var_expand_short(const struct var_expand_context *ctx, char key, } } - if (ctx->func_table != NULL) { - for (unsigned int i = 0; ctx->func_table[i].key != NULL; i++) { - if (ctx->func_table[i].key[0] == key && - ctx->func_table[i].key[1] == '\0') { + for (unsigned int j = 0; ctx->func_tables[j] != NULL; j++) { + const struct var_expand_func_table *func_table = ctx->func_tables[j]; + for (unsigned int i = 0; func_table[i].key != NULL; i++) { + if (func_table[i].key[0] == key && + func_table[i].key[1] == '\0') { const char *value; - int ret = ctx->func_table->func( - "", ctx->context, &value, error_r); + int ret = func_table->func( + "", ctx->contexts[j], &value, error_r); *var_r = value != NULL ? value : ""; return ret; } @@ -297,9 +298,9 @@ var_expand_hash(struct var_expand_context *ctx, truncbits = I_MIN(truncbits, method->digest_size*8); } else if (strcmp(k, "salt") == 0) { str_truncate(salt, 0); - ret = var_expand_with_funcs(salt, value, ctx->table, - ctx->func_table, - ctx->context, error_r); + ret = var_expand_with_arrays(salt, value, ctx->tables, + ctx->func_tables, + ctx->contexts, error_r); if (ret <= 0) return ret; break; @@ -425,8 +426,8 @@ var_expand_system(struct var_expand_context *ctx ATTR_UNUSED, } static int -var_expand_func(const struct var_expand_func_table *func_table, - const char *key, const char *data, void *context, +var_expand_func(const struct var_expand_func_table *const *func_tables, + const char *key, const char *data, void *const *contexts, const char **var_r, const char **error_r) { const char *value = NULL; @@ -437,10 +438,11 @@ var_expand_func(const struct var_expand_func_table *func_table, *var_r = value != NULL ? value : ""; return 1; } - if (func_table != NULL) { + for (unsigned int i = 0; func_tables[i] != NULL; i++) { + const struct var_expand_func_table *func_table = func_tables[i]; for (; func_table->key != NULL; func_table++) { if (strcmp(func_table->key, key) == 0) { - ret = func_table->func(data, context, &value, error_r); + ret = func_table->func(data, contexts[i], &value, error_r); if (*error_r == NULL) *error_r = t_strdup_printf("Unknown variables in function %%%s", key); *var_r = value != NULL ? value : ""; @@ -475,8 +477,8 @@ var_expand_try_extension(struct var_expand_context *ctx, return ret; } } - return var_expand_func(ctx->func_table, key, data, - ctx->context, var_r, error_r); + return var_expand_func(ctx->func_tables, key, data, + ctx->contexts, var_r, error_r); } @@ -489,8 +491,8 @@ var_expand_long(struct var_expand_context *ctx, const char *key, *value = NULL; int ret = 1; - if (ctx->table != NULL) { - for (t = ctx->table; !TABLE_LAST(t); t++) { + for (unsigned int i = 0; ctx->tables[i] != NULL; i++) { + for (t = ctx->tables[i]; !TABLE_LAST(t); t++) { if (t->long_key != NULL && strncmp(t->long_key, key_start, key_len) == 0 && t->long_key[key_len] == '\0') { @@ -522,6 +524,21 @@ int var_expand_with_funcs(string_t *dest, const char *str, const struct var_expand_func_table *func_table, void *context, const char **error_r) { + const struct var_expand_table *tables[2] = { table, NULL }; + const struct var_expand_func_table *func_tables[2] = { func_table, NULL }; + void *contexts[2] = { context, NULL }; + + return var_expand_with_arrays(dest, str, tables, func_tables, + contexts, error_r); +} + +int var_expand_with_arrays(string_t *dest, const char *str, + const struct var_expand_table *const *tables, + const struct var_expand_func_table *const *func_tables, + void *const *func_contexts, const char **error_r) +{ + static const struct var_expand_table *empty_table = NULL; + static const struct var_expand_func_table *empty_func_table = NULL; const struct var_expand_modifier *m; const char *var; struct var_expand_context ctx; @@ -535,9 +552,9 @@ int var_expand_with_funcs(string_t *dest, const char *str, *error_r = NULL; i_zero(&ctx); - ctx.table = table; - ctx.func_table = func_table; - ctx.context = context; + ctx.tables = tables != NULL ? tables : &empty_table; + ctx.func_tables = func_tables != NULL ? func_tables : &empty_func_table; + ctx.contexts = func_contexts; for (; *str != '\0'; str++) { if (*str != '%') diff --git a/src/lib/var-expand.h b/src/lib/var-expand.h index c8485a4377..73a5a3303d 100644 --- a/src/lib/var-expand.h +++ b/src/lib/var-expand.h @@ -29,6 +29,12 @@ int var_expand_with_funcs(string_t *dest, const char *str, const struct var_expand_table *table, const struct var_expand_func_table *func_table, void *func_context, const char **error_r) ATTR_NULL(3, 4, 5); +/* Like var_expand_with_funcs(), but multiple separate tables can be given. + Each func_table[n] has a matching func_context[n] */ +int var_expand_with_arrays(string_t *dest, const char *str, + const struct var_expand_table *const *tables, + const struct var_expand_func_table *const *func_tables, + void *const *func_contexts, const char **error_r); /* Returns the actual key character for given string, ie. skip any modifiers that are before it. The string should be the data after the '%' character. diff --git a/src/plugins/var-expand-crypt/var-expand-crypt-plugin.c b/src/plugins/var-expand-crypt/var-expand-crypt-plugin.c index 7f05e1909f..79567ca974 100644 --- a/src/plugins/var-expand-crypt/var-expand-crypt-plugin.c +++ b/src/plugins/var-expand-crypt/var-expand-crypt-plugin.c @@ -52,9 +52,11 @@ var_expand_crypt_settings(struct var_expand_crypt_context *ctx, if (strcmp(k, "iv") == 0) { str_truncate(ctx->iv, 0); - if ((ret = var_expand_with_funcs(ctx->iv, value, ctx->ctx->table, - ctx->ctx->func_table, - ctx->ctx->context, error_r)) <= 0) { + if ((ret = var_expand_with_arrays(ctx->iv, value, + ctx->ctx->tables, + ctx->ctx->func_tables, + ctx->ctx->contexts, + error_r)) <= 0) { return ret; } const char *hexiv = t_strdup(str_c(ctx->iv)); @@ -67,11 +69,11 @@ var_expand_crypt_settings(struct var_expand_crypt_context *ctx, ctx->algo = value; } else if (strcmp(k, "key") == 0) { str_truncate(ctx->enckey, 0); - if ((ret = var_expand_with_funcs(ctx->enckey, value, - ctx->ctx->table, - ctx->ctx->func_table, - ctx->ctx->context, - error_r)) <= 0) { + if ((ret = var_expand_with_arrays(ctx->enckey, value, + ctx->ctx->tables, + ctx->ctx->func_tables, + ctx->ctx->contexts, + error_r)) <= 0) { return ret; } const char *hexkey = t_strdup(str_c(ctx->enckey));