]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
config: Fix grouping settings under a named filter
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 8 Nov 2024 12:14:19 +0000 (14:14 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:00 +0000 (10:40 +0200)
src/config/config-parser.c

index 597f3a0c44242fac3c636ac5d4266f2424398907..a4542eed23d502b203f2d63d5d14b02dcf9177b0 100644 (file)
@@ -805,28 +805,42 @@ static bool replace_filter_prefix(struct config_parser_context *ctx,
                           ctx->filter_name_prefixes_count,
                           sizeof(ctx->filter_name_prefixes[0]),
                           i_strcmp_p, &filter_name_idx);
-       if (filter_name_idx == 0)
-               return FALSE;
+       /* Insert position might not be exactly the place we want to look at.
+          For example:
+
+          *key = "foo_3"
+          filter_name_prefixes[filter_name_idx-1] = "foo_2"
+          filter_name_prefixes[filter_name_idx-2] = "foo_"
+
+          In this case we want to use the "foo_" prefix.
+       */
+       const char *key_minimum_prefix = t_strcut(*key, '_');
+       for (; filter_name_idx > 0; filter_name_idx--) {
+               const char *filter_name_prefix =
+                       ctx->filter_name_prefixes[filter_name_idx-1];
+               size_t filter_name_prefix_len = strlen(filter_name_prefix);
+               if (strncmp(*key, filter_name_prefix, filter_name_prefix_len) != 0) {
+                       if (strcmp(key_minimum_prefix, filter_name_prefix) > 0)
+                               break;
+                       /* Previous prefixes could still match. */
+                       continue;
+               }
 
-       const char *filter_name_prefix =
-               ctx->filter_name_prefixes[filter_name_idx-1];
-       size_t filter_name_prefix_len = strlen(filter_name_prefix);
-       if (strncmp(*key, filter_name_prefix, filter_name_prefix_len) != 0)
-               return FALSE;
+               const char *cur_filter_name =
+                       ctx->cur_section->filter_parser->filter.filter_name;
+               if (cur_filter_name != NULL &&
+                   strncmp(filter_name_prefix, cur_filter_name,
+                           filter_name_prefix_len - 1) == 0 &&
+                   cur_filter_name[filter_name_prefix_len-1] == '\0') {
+                       /* already inside the correct filter */
+                       return FALSE;
+               }
 
-       const char *cur_filter_name =
-               ctx->cur_section->filter_parser->filter.filter_name;
-       if (cur_filter_name != NULL &&
-           strncmp(filter_name_prefix, cur_filter_name,
-                   filter_name_prefix_len - 1) == 0 &&
-           cur_filter_name[filter_name_prefix_len-1] == '\0') {
-               /* already inside the correct filter */
-               return FALSE;
+               *key = t_strdup_printf("%.*s/%s", (int)filter_name_prefix_len-1,
+                                      filter_name_prefix, *key);
+               return TRUE;
        }
-
-       *key = t_strdup_printf("%.*s/%s", (int)filter_name_prefix_len-1,
-                              filter_name_prefix, *key);
-       return TRUE;
+       return FALSE;
 }
 
 static const char *filter_key_skip_group_prefix(const char *key)