#ifdef DEBUG
static const char *boollist_eol_sentry = "boollist-eol";
#endif
+static const char *set_array_stop = "array-stop";
static void
setting_parser_copy_defaults(struct setting_parser_context *ctx,
break;
case SET_FILTER_ARRAY: {
/* Add filter names to the array. Userdb can add more simply
- by giving e.g. "namespace=newname" without it removing the
+ by giving e.g. "namespace+=newname" without it removing the
existing ones. */
ARRAY_TYPE(const_string) *arr = ptr;
const char *const *list = t_strsplit(value, ",\t ");
unsigned int i, count = str_array_length(list);
if (!array_is_created(arr))
p_array_init(arr, ctx->set_pool, count);
+ else {
+ /* If the next element after the visible array is
+ set_array_stop, then the named list filter
+ should not be modified any further. */
+ unsigned int old_count;
+ const char *const *old_values =
+ array_get(arr, &old_count);
+ if (old_values[old_count] == set_array_stop)
+ break;
+ }
unsigned int insert_pos = 0;
for (i = 0; i < count; i++) {
const char *value = p_strdup(ctx->set_pool,
else
array_push_back(arr, &value);
}
+ /* Make sure the next element after the array is accessible for
+ the set_array_stop check. */
+ array_append_zero(arr);
+ array_pop_back(arr);
break;
}
case SET_FILTER_NAME:
key, value, FALSE);
}
+void settings_parse_array_stop(struct setting_parser_context *ctx,
+ unsigned int key_idx)
+{
+ i_assert(ctx->info->defines[key_idx].type == SET_FILTER_ARRAY);
+
+ ARRAY_TYPE(const_string) *arr =
+ PTR_OFFSET(ctx->set_struct, ctx->info->defines[key_idx].offset);
+ if (!array_is_created(arr))
+ p_array_init(arr, ctx->set_pool, 1);
+ /* Use the next element hidden after the array to keep the stop-state */
+ array_push_back(arr, &set_array_stop);
+ array_pop_back(arr);
+}
+
static int boollist_removal_cmp(const struct boollist_removal *r1,
const struct boollist_removal *r2)
{
int settings_parse_keyidx_value_nodup(struct setting_parser_context *ctx,
unsigned int key_idx, const char *key,
const char *value);
+/* Ignore any further attempts to add to the named list filter. */
+void settings_parse_array_stop(struct setting_parser_context *ctx,
+ unsigned int key_idx);
/* Returns TRUE if list has the specific key. The key must NOT include the
list/ prefix. */
bool settings_parse_list_has_key(struct setting_parser_context *ctx,
else
key = t_strconcat(ctx->info->defines[key_idx].key, list, NULL);
- if (!set->append) {
+ if (!set->append ||
+ ctx->info->defines[key_idx].type == SET_FILTER_ARRAY) {
*_key = key;
*key_idx_r = key_idx;
*value_r = set->value;
if (ctx->info->defines[key_idx].type != SET_STR) {
*error_r = t_strdup_printf(
- "%s setting is not a string - can't use '+'", key);
+ "%s setting is not a string or named list filter - can't use '+'", key);
return -1;
}
const char *const *strp =
key, value, settings_parser_get_error(ctx->parser));
return -1;
}
+
+ if (!set->append &&
+ ctx->info->defines[key_idx].type == SET_FILTER_ARRAY) {
+ /* The named list filter is filled in reverse order.
+ Mark it now as "stopped", so following filters won't
+ try to insert anything more into it. */
+ settings_parse_array_stop(ctx->parser, key_idx);
+ }
}
return seen_filter ? 1 : 0;
}
return set;
}
-void settings_override(struct settings_instance *instance,
+static void
+settings_override_fill(struct settings_override *set, pool_t pool,
const char *key, const char *value,
enum settings_override_type type)
{
- if (!array_is_created(&instance->overrides))
- p_array_init(&instance->overrides, instance->pool, 16);
- struct settings_override *set =
- array_append_space(&instance->overrides);
- set->pool = instance->pool;
+ set->pool = pool;
set->type = type;
size_t len = strlen(key);
T_BEGIN {
set->append = TRUE;
key = t_strndup(key, len-1);
}
- set->key = set->orig_key = p_strdup(instance->pool, key);
+ set->key = set->orig_key = p_strdup(pool, key);
set->path_element_count = path_element_count(set->key);
- set->value = p_strdup(instance->pool, value);
+ set->value = p_strdup(pool, value);
} T_END;
}
+void settings_override(struct settings_instance *instance,
+ const char *key, const char *value,
+ enum settings_override_type type)
+{
+ if (!array_is_created(&instance->overrides))
+ p_array_init(&instance->overrides, instance->pool, 16);
+ struct settings_override *set =
+ array_append_space(&instance->overrides);
+ settings_override_fill(set, instance->pool, key, value, type);
+}
+
void settings_root_override(struct settings_root *root,
const char *key, const char *value,
enum settings_override_type type)
p_array_init(&root->overrides, root->pool, 16);
struct settings_override *set =
array_append_space(&root->overrides);
- set->pool = root->pool;
- set->type = type;
- set->key = set->orig_key = p_strdup(root->pool, key);
- set->path_element_count = path_element_count(set->key);
- set->value = p_strdup(root->pool, value);
+ settings_override_fill(set, root->pool, key, value, type);
}
static struct settings_instance *
const char *const default_input[] = {
t_strdup_printf("mail_driver=%s", set->driver),
"postmaster_address=postmaster@localhost",
- "namespace=inbox",
+ "namespace+=inbox",
"namespace/inbox/prefix=",
"namespace/inbox/inbox=yes",
t_strdup_printf("mail_path=%s", home),
mailbox_list_layout[0] == '\0' ? NULL :
t_strdup_printf("mailbox_list_layout=%s", mailbox_list_layout);
const char *const ns2[] = {
- "namespace=subspace",
+ "namespace+=subspace",
"namespace/subspace/separator=/",
"namespace/subspace/prefix=SubSpace/",
layout_option,
mailbox_list_layout[0] == '\0' ? NULL :
t_strdup_printf("mailbox_list_layout=%s", mailbox_list_layout);
const char *const ns2[] = {
- "namespace=subspace",
+ "namespace+=subspace",
"namespace/subspace/separator=.",
"namespace/subspace/prefix=SubSpace.",
layout_option,
mailbox_list_layout[0] == '\0' ? NULL :
t_strdup_printf("mailbox_list_layout=%s", mailbox_list_layout);
const char *const ns2[] = {
- "namespace=subspace",
+ "namespace+=subspace",
t_strdup_printf("namespace/subspace/separator=%s", sep),
t_strdup_printf("namespace/subspace/prefix=SubSpace%s", sep),
layout_option,