virtual-config.c revision efe78d3ba24fc866af1c79b9223dc0809ba26cad
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2008-2016 Dovecot authors, see the included COPYING file */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschvirtual_search_args_parse(const string_t *rule, const char **error_r)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch input = i_stream_create_from_data(str_data(rule), str_len(rule));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch imap_parser = imap_parser_create(input, NULL, (size_t)-1);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ret = imap_parser_finish_line(imap_parser, 0, 0, &args);
9a5980c7bb836f69a63082f4699c30596ea4ee74Timo Sirainen *error_r = t_strdup(imap_parser_get_error(imap_parser, NULL));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if (mail_search_build(mail_search_register_get_imap(),
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschvirtual_config_add_rule(struct virtual_parse_context *ctx, const char **error_r)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i, count;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch crc32_str_more(ctx->mbox->search_args_crc32, str_c(ctx->rule));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch search_args = virtual_search_args_parse(ctx->rule, error_r);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch *error_r = t_strconcat("Previous search rule is invalid: ",
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch /* update at all the mailboxes that were introduced since the previous
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch bboxes = array_get(&ctx->mbox->backend_boxes, &count);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ctx->rule_idx = array_count(&ctx->mbox->backend_boxes);
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainenvirtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch const char **error_r)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch struct mail_user *user = ctx->mbox->storage->storage.user;
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen const char *p;
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen /* continues the previous search rule */
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
d730192e34fbedbc590a5abc7351e5af5e120c5fTimo Sirainen /* if there is no rule yet, it means we want the previous mailboxes
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch to use the rule that comes later */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (virtual_config_add_rule(ctx, error_r) < 0)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch *error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen /* new mailbox. the search args are added to it later. */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch /* save messages here */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch /* [+-!]/metadata entry:value */
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch *error_r = "':' separator missing between metadata entry name and value";
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch bbox->metadata_entry = p_strdup_until(ctx->pool, bbox->name, p++);
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen if (!imap_metadata_verify_entry_name(bbox->metadata_entry, error_r))
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch bbox->glob = imap_match_init(ctx->pool, bbox->name, TRUE, ctx->sep);
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen /* now that the prefix characters have been processed,
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen find the namespace */
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen bbox->ns = strcasecmp(bbox->name, "INBOX") == 0 ?
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen mail_namespace_find(user->namespaces, bbox->name);
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen *error_r = t_strdup_printf("Namespace not found for %s",
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) {
5afe997e79978b7e989aa3b0bfdf4a813ecdc6f6Timo Sirainen *error_r = "Virtual mailbox can't point to itself";
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch array_append(&ctx->mbox->backend_boxes, &bbox, 1);
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainenvirtual_mailbox_get_list_patterns(struct virtual_parse_context *ctx)
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen unsigned int i, count;
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen p_array_init(&mbox->list_include_patterns, ctx->pool, count);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch p_array_init(&mbox->list_exclude_patterns, ctx->pool, count);
4afd5082f38342fd688acb5796912329f57dd02cTimo Sirainen for (i = 0; i < count; i++) {
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Boschseparate_wildcard_mailboxes(struct virtual_mailbox *mbox,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ARRAY_TYPE(virtual_backend_box) *wildcard_boxes,
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch ARRAY_TYPE(virtual_backend_box) *metadata_boxes)
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch unsigned int i, count;
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch t_array_init(wildcard_boxes, I_MIN(16, count));
0fe2992e4d09f3ae4cceea88c9871c832d67b461Stephan Bosch for (i = 0; i < count;) {
&count);
const char *name)
return TRUE;
return TRUE;
return TRUE;
return FALSE;
unsigned int *idx_r)
unsigned int i, count;
for (i = 0; i < count; i++) {
*idx_r = i;
return TRUE;
*idx_r = i;
return TRUE;
return FALSE;
const char **error_r)
int ret;
if (ret < 0)
if (ret > 0)
return ret;
const char **error_r)
unsigned int i, count;
if (count == 0)
for (i = 0; i < count; i++) {
return ret;
const char **error_r)
const char **patterns;
unsigned int i, j, count;
int ret = 0;
if (count == 0) {
for (i = 0; i < count; i++)
if (ret < 0)
if (ret > 0) {
for (i = 0; i < count; i++)
unsigned int i, count;
for (i = 0; i < count; i++) {
unsigned int linenum = 0;
linenum++;
if (ret < 0) {
if (ret == 0) {
if (ret < 0) {
if (ret < 0)
if (ret == 0)
return ret;
unsigned int i, count;
for (i = 0; i < count; i++) {