virtual-config.c revision 1330f999b8076b2f8eed2572c667f7482a555c1b
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenvirtual_search_args_parse(const string_t *rule, const char **error_r)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen input = i_stream_create_from_data(str_data(rule), str_len(rule));
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen parser = imap_parser_create(input, NULL, (size_t)-1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = imap_parser_finish_line(parser, 0, 0, &args);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *error_r = t_strdup(imap_parser_get_error(parser, &fatal));
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen } else if (mail_search_build_from_imap_args(args, "UTF-8", &sargs,
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenvirtual_config_add_rule(struct virtual_parse_context *ctx, const char **error_r)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen unsigned int i, count;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen crc32_str_more(ctx->mbox->search_args_crc32, str_c(ctx->rule));
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen search_args = virtual_search_args_parse(ctx->rule, error_r);
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen *error_r = t_strconcat("Previous search rule is invalid: ",
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen /* update at all the mailboxes that were introduced since the previous
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen bboxes = array_get(&ctx->mbox->backend_boxes, &count);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ctx->rule_idx = array_count(&ctx->mbox->backend_boxes);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvirtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen const char **error_r)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mail_user *user = ctx->mbox->storage->storage.ns->user;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* continues the previous search rule */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* if there is no rule yet, it means we want the previous mailboxes
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen to use the rule that comes later */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (virtual_config_add_rule(ctx, error_r) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* new mailbox. the search args are added to it later. */
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_namespace_find(user->namespaces, &line) :
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *error_r = t_strdup_printf("Namespace not found for %s",
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen name = bbox->name[0] == '-' ? bbox->name + 1 : bbox->name;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen bbox->glob = imap_match_init(ctx->pool, name, TRUE, ctx->sep);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* save messages here */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen array_append(&ctx->mbox->backend_boxes, &bbox, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenvirtual_mailbox_get_list_patterns(struct virtual_parse_context *ctx)
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen unsigned int i, count;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen p_array_init(&mbox->list_include_patterns, ctx->pool, count);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen p_array_init(&mbox->list_exclude_patterns, ctx->pool, count);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen for (i = 0; i < count; i++) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenseparate_wildcard_mailboxes(struct virtual_mailbox *mbox,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen ARRAY_TYPE(virtual_backend_box) *wildcard_boxes,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen unsigned int i, count;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen t_array_init(wildcard_boxes, I_MIN(16, count));
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen for (i = 0; i < count;) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic void virtual_config_copy_expanded(struct virtual_parse_context *ctx,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen array_append(&ctx->mbox->backend_boxes, &bbox, 1);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic bool virtual_config_match(const struct mailbox_info *info,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen unsigned int *idx_r)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen unsigned int i, count;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen boxes = array_get_modifiable(boxes_arr, &count);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen for (i = 0; i < count; i++) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* we match only one namespace for each pattern. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (strcmp(boxes[i]->name + 1, info->name) == 0) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainenstatic int virtual_config_expand_wildcards(struct virtual_parse_context *ctx)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mail_user *user = ctx->mbox->storage->storage.ns->user;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen ARRAY_TYPE(virtual_backend_box) wildcard_boxes, neg_boxes;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen unsigned int i, j, count;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen separate_wildcard_mailboxes(ctx->mbox, &wildcard_boxes, &neg_boxes);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* get patterns we want to list */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen wboxes = array_get_modifiable(&wildcard_boxes, &count);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* only negative wildcards - doesn't really make sense.
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen just ignore. */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen for (i = 0; i < count; i++)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* match listed mailboxes to wildcards */
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen iter = mailbox_list_iter_init_namespaces(user->namespaces, patterns,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* skip non-selectable mailboxes (especially mbox
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen directories) */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (virtual_config_match(info, &wildcard_boxes, &i) &&
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen !virtual_config_match(info, &neg_boxes, &j) &&
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen for (i = 0; i < count; i++)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen mail_search_args_unref(&wboxes[i]->search_args);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenint virtual_config_read(struct virtual_mailbox *mbox)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_user *user = mbox->storage->storage.ns->user;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen unsigned int linenum = 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen path = t_strconcat(mbox->path, "/"VIRTUAL_CONFIG_FNAME, NULL);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen "Virtual mailbox missing configuration file");
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen ctx.sep = mail_namespace_get_root_sep(user->namespaces);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ctx.input = i_stream_create_fd(fd, (size_t)-1, FALSE);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen i_stream_set_return_partial_line(ctx.input, TRUE);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen while ((line = i_stream_read_next_line(ctx.input)) != NULL) {
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen ret = virtual_config_parse_line(&ctx, line, &error);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen "%s: Error at line %u: %s",
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (ret == 0 && array_count(&mbox->backend_boxes) == 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid virtual_config_free(struct virtual_mailbox *mbox)
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen unsigned int i, count;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen for (i = 0; i < count; i++) {