]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
config: Split off config_filter_parse()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 8 Nov 2024 09:55:32 +0000 (11:55 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:01 +0000 (10:40 +0200)
src/config/config-parser.c
src/config/config-parser.h

index a4542eed23d502b203f2d63d5d14b02dcf9177b0..40e4b26be6b0d220ef089cbb37e59fd9442fafac 100644 (file)
@@ -1114,95 +1114,117 @@ int config_parse_net(const char *value, struct ip_addr *ip_r,
        return 0;
 }
 
-static bool
-config_filter_add_new_filter(struct config_parser_context *ctx,
-                            const char *key, const char *value,
-                            bool value_quoted)
+int config_filter_parse(struct config_filter *filter, pool_t pool,
+                       const char *key, const char *value,
+                       const char **error_r)
 {
-       struct config_filter filter;
-       struct config_filter *parent = &ctx->cur_section->prev->filter_parser->filter;
-       struct config_filter_parser *filter_parser;
-       const struct setting_parser_info *filter_info = NULL;
-       const struct setting_define *filter_def = NULL;
+       struct config_filter *parent = filter->parent;
        const char *error;
 
-       i_zero(&filter);
-       filter.parent = parent;
+       *error_r = NULL;
 
        if (key[0] == SETTINGS_INCLUDE_GROUP_PREFIX) {
                if (!config_filter_is_empty(parent) &&
                    !config_filter_is_empty_defaults(parent)) {
-                       ctx->error = "groups must defined at top-level, not under filters";
-                       return TRUE;
+                       *error_r = "groups must defined at top-level, not under filters";
+                       return -1;
                }
-               filter.filter_name =
-                       p_strdup_printf(ctx->pool, "%s/%s", key, value);
-               filter.filter_name_array = TRUE;
+               filter->filter_name =
+                       p_strdup_printf(pool, "%s/%s", key, value);
+               filter->filter_name_array = TRUE;
        } else if (strcmp(key, "protocol") == 0) {
                if (parent->service != NULL)
-                       ctx->error = "Nested protocol { protocol { .. } } block not allowed";
+                       *error_r = "Nested protocol { protocol { .. } } block not allowed";
                else if (parent->filter_name != NULL)
-                       ctx->error = p_strdup_printf(ctx->pool,
+                       *error_r = t_strdup_printf(
                                "%s { protocol { .. } } not allowed (use protocol { %s { .. } } instead)",
                                t_strcut(parent->filter_name, '/'),
                                t_strcut(parent->filter_name, '/'));
                else
-                       filter.service = p_strdup(ctx->pool, value);
+                       filter->service = p_strdup(pool, value);
        } else if (strcmp(key, "local") == 0) {
                if (parent->remote_bits > 0)
-                       ctx->error = "remote { local { .. } } not allowed (use local { remote { .. } } instead)";
+                       *error_r = "remote { local { .. } } not allowed (use local { remote { .. } } instead)";
                else if (parent->service != NULL)
-                       ctx->error = "protocol { local { .. } } not allowed (use local { protocol { .. } } instead)";
+                       *error_r = "protocol { local { .. } } not allowed (use local { protocol { .. } } instead)";
                else if (parent->local_name != NULL)
-                       ctx->error = "local_name { local { .. } } not allowed (use local { local_name { .. } } instead)";
+                       *error_r = "local_name { local { .. } } not allowed (use local { local_name { .. } } instead)";
                else if (parent->filter_name != NULL)
-                       ctx->error = p_strdup_printf(ctx->pool,
+                       *error_r = p_strdup_printf(pool,
                                "%s { local { .. } } not allowed (use local { %s { .. } } instead)",
                                t_strcut(parent->filter_name, '/'),
                                t_strcut(parent->filter_name, '/'));
-               else if (config_parse_net(value, &filter.local_net,
-                                         &filter.local_bits, &error) < 0)
-                       ctx->error = p_strdup(ctx->pool, error);
-               else if (parent->local_bits > filter.local_bits ||
+               else if (config_parse_net(value, &filter->local_net,
+                                         &filter->local_bits, &error) < 0)
+                       *error_r = p_strdup(pool, error);
+               else if (parent->local_bits > filter->local_bits ||
                         (parent->local_bits > 0 &&
-                         !net_is_in_network(&filter.local_net,
+                         !net_is_in_network(&filter->local_net,
                                             &parent->local_net,
                                             parent->local_bits)))
-                       ctx->error = "local net1 { local net2 { .. } } requires net2 to be inside net1";
+                       *error_r = "local net1 { local net2 { .. } } requires net2 to be inside net1";
                else
-                       filter.local_host = p_strdup(ctx->pool, value);
+                       filter->local_host = p_strdup(pool, value);
        } else if (strcmp(key, "local_name") == 0) {
                if (parent->remote_bits > 0)
-                       ctx->error = "remote { local_name { .. } } not allowed (use local_name { remote { .. } } instead)";
+                       *error_r = "remote { local_name { .. } } not allowed (use local_name { remote { .. } } instead)";
                else if (parent->service != NULL)
-                       ctx->error = "protocol { local_name { .. } } not allowed (use local_name { protocol { .. } } instead)";
+                       *error_r = "protocol { local_name { .. } } not allowed (use local_name { protocol { .. } } instead)";
                else if (parent->filter_name != NULL)
-                       ctx->error = p_strdup_printf(ctx->pool,
+                       *error_r = p_strdup_printf(pool,
                                "%s { local_name { .. } } not allowed (use local_name { %s { .. } } instead)",
                                t_strcut(parent->filter_name, '/'),
                                t_strcut(parent->filter_name, '/'));
                else
-                       filter.local_name = p_strdup(ctx->pool, value);
+                       filter->local_name = p_strdup(pool, value);
        } else if (strcmp(key, "remote") == 0) {
                if (parent->service != NULL)
-                       ctx->error = "protocol { remote { .. } } not allowed (use remote { protocol { .. } } instead)";
+                       *error_r = "protocol { remote { .. } } not allowed (use remote { protocol { .. } } instead)";
                else if (parent->filter_name != NULL)
-                       ctx->error = p_strdup_printf(ctx->pool,
+                       *error_r = p_strdup_printf(pool,
                                "%s { remote { .. } } not allowed (use remote { %s { .. } } instead)",
                                t_strcut(parent->filter_name, '/'),
                                t_strcut(parent->filter_name, '/'));
-               else if (config_parse_net(value, &filter.remote_net,
-                                         &filter.remote_bits, &error) < 0)
-                       ctx->error = p_strdup(ctx->pool, error);
-               else if (parent->remote_bits > filter.remote_bits ||
+               else if (config_parse_net(value, &filter->remote_net,
+                                         &filter->remote_bits, &error) < 0)
+                       *error_r = p_strdup(pool, error);
+               else if (parent->remote_bits > filter->remote_bits ||
                         (parent->remote_bits > 0 &&
-                         !net_is_in_network(&filter.remote_net,
+                         !net_is_in_network(&filter->remote_net,
                                             &parent->remote_net,
                                             parent->remote_bits)))
-                       ctx->error = "remote net1 { remote net2 { .. } } requires net2 to be inside net1";
+                       *error_r = "remote net1 { remote net2 { .. } } requires net2 to be inside net1";
                else
-                       filter.remote_host = p_strdup(ctx->pool, value);
-       } else if (config_is_filter_name(ctx, key, &filter_info, &filter_def)) {
+                       filter->remote_host = p_strdup(pool, value);
+       } else {
+               return 0;
+       }
+       return *error_r == NULL ? 1 : -1;
+}
+
+static bool
+config_filter_add_new_filter(struct config_parser_context *ctx,
+                            const char *key, const char *value,
+                            bool value_quoted)
+{
+       struct config_filter filter;
+       struct config_filter *parent = &ctx->cur_section->prev->filter_parser->filter;
+       struct config_filter_parser *filter_parser;
+       const struct setting_parser_info *filter_info = NULL;
+       const struct setting_define *filter_def = NULL;
+       const char *error;
+
+       i_zero(&filter);
+       filter.parent = parent;
+
+       int ret = config_filter_parse(&filter, ctx->pool, key, value, &error);
+       if (ret < 0) {
+               ctx->error = p_strdup(ctx->pool, error);
+               return FALSE;
+       }
+       if (ret > 0)
+               ; /* already parsed */
+       else if (config_is_filter_name(ctx, key, &filter_info, &filter_def)) {
                if (filter_def->type == SET_FILTER_NAME) {
                        if (value[0] != '\0' || value_quoted) {
                                ctx->error = p_strdup_printf(ctx->pool,
index fd1e103ee9abe8a353b6af6b7334b278f8d791f5..fd35d892052acc76992411aadae64db57d0142fc 100644 (file)
@@ -70,6 +70,9 @@ extern struct module *modules;
 
 int config_parse_net(const char *value, struct ip_addr *ip_r,
                     unsigned int *bits_r, const char **error_r);
+int config_filter_parse(struct config_filter *filter, pool_t pool,
+                       const char *key, const char *value,
+                       const char **error_r);
 int config_parse_file(const char *path, enum config_parse_flags flags,
                      struct config_parsed **config_r,
                      const char **error_r)