]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add var_expand_with_arrays()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 21 Nov 2023 09:41:04 +0000 (11:41 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:10 +0000 (12:34 +0200)
src/lib/test-var-expand.c
src/lib/var-expand-if.c
src/lib/var-expand-private.h
src/lib/var-expand.c
src/lib/var-expand.h
src/plugins/var-expand-crypt/var-expand-crypt-plugin.c

index 531d51ec324b48231584c986d7ce5676aa1e00b5..c519bd401e82f374adc47bcffe7c4ac59f2ede63 100644 (file)
@@ -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();
index 0387840a4a40066a8dc7f69cc63e1debfb796ffd..6da05a868288b60fb8dc5dd12531a4575cbf92b4 100644 (file)
@@ -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(&params, &p);
        }
index f02356a322de305769b6c87d1112d81427faabf2..2de885dd3ac0a4784b18833291aacfc9e43820cd 100644 (file)
@@ -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 */
index 5904964bdbf6490b0fe1dc78a28918b33b192187..1d7fe7d04c823d653374493488a131743fbca54e 100644 (file)
@@ -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 != '%')
index c8485a43770fcac16f958557a0078ac9cde53ae2..73a5a3303db3140286f5638897586e52472a5bc2 100644 (file)
@@ -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.
index 7f05e1909f790c79f824590224b5934bafd03576..79567ca974d7fbf556399bcb068c0e441b0dd8e5 100644 (file)
@@ -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));