Ejemplo n.º 1
0
static void test_imap_match_globs_equal(void)
{
	struct imap_match_glob *glob;
	pool_t pool;

	pool = pool_alloconly_create("imap match globs equal", 1024);
	test_begin("imap match globs equal");

	glob = imap_match_init(pool, "1", FALSE, '/');
	test_assert(imap_match_globs_equal(glob,
		imap_match_init(pool, "1", FALSE, '/')));
	test_assert(imap_match_globs_equal(glob,
		imap_match_init(pool, "1", TRUE, '/')));
	test_assert(!imap_match_globs_equal(glob,
		imap_match_init(pool, "1", FALSE, '.')));
	test_assert(!imap_match_globs_equal(glob,
		imap_match_init(pool, "11", FALSE, '/')));

	glob = imap_match_init(pool, "in%", TRUE, '/');
	test_assert(!imap_match_globs_equal(glob,
		imap_match_init(pool, "in%", FALSE, '/')));
	test_assert(!imap_match_globs_equal(glob,
		imap_match_init(pool, "In%", TRUE, '/')));

	pool_unref(&pool);
	test_end();
}
Ejemplo n.º 2
0
static void
acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ctx->ctx.list);
	struct acl_backend *backend = alist->rights.backend;
	const unsigned int *idxp;
	const struct acl_mask *acl_mask;
	struct acl_mailbox_list_context *nonowner_list_ctx;
	struct mail_namespace *ns = ctx->ctx.list->ns;
	struct mailbox_list_iter_update_context update_ctx;
	const char *name;
	int ret;

	if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_RAW_LIST |
			       MAILBOX_LIST_ITER_SELECT_SUBSCRIBED)) != 0)
		return;

	if (ns->type == MAIL_NAMESPACE_TYPE_PUBLIC) {
		/* mailboxes in public namespace should all be listable to
		   someone. we don't benefit from fast listing. */
		return;
	}

	/* if this namespace's default rights contain LOOKUP, we'll need to
	   go through all mailboxes in any case. */
	idxp = alist->rights.acl_storage_right_idx + ACL_STORAGE_RIGHT_LOOKUP;
	if (acl_backend_get_default_rights(backend, &acl_mask) < 0 ||
	    acl_cache_mask_isset(acl_mask, *idxp))
		return;

	/* no LOOKUP right by default, we can optimize this */
	memset(&update_ctx, 0, sizeof(update_ctx));
	update_ctx.iter_ctx = &ctx->ctx;
	update_ctx.glob =
		imap_match_init(pool_datastack_create(), "*",
				(ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0,
				ctx->sep);
	update_ctx.match_parents = TRUE;
	update_ctx.tree_ctx = mailbox_tree_init(ctx->sep);

	nonowner_list_ctx = acl_backend_nonowner_lookups_iter_init(backend);
	while ((ret = acl_backend_nonowner_lookups_iter_next(nonowner_list_ctx,
							     &name)) > 0) {
		T_BEGIN {
			const char *vname =
				mailbox_list_get_vname(ns->list, name);
			mailbox_list_iter_update(&update_ctx, vname);
		} T_END;
	}
	acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);

	if (ret == 0)
		ctx->lookup_boxes = update_ctx.tree_ctx;
	else
		mailbox_tree_deinit(&update_ctx.tree_ctx);
}
Ejemplo n.º 3
0
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                          const char **error_r)
{
    struct mail_user *user = ctx->mbox->storage->storage.user;
    struct virtual_backend_box *bbox;
    const char *p;
    bool no_wildcards = FALSE;

    if (*line == ' ' || *line == '\t') {
        /* continues the previous search rule */
        if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
            *error_r = "Search rule without a mailbox";
            return -1;
        }
        while (*line == ' ' || *line == '\t') line++;
        str_append_c(ctx->rule, ' ');
        str_append(ctx->rule, line);
        return 0;
    }
    /* if there is no rule yet, it means we want the previous mailboxes
       to use the rule that comes later */
    if (str_len(ctx->rule) > 0) {
        if (virtual_config_add_rule(ctx, error_r) < 0)
            return -1;
    }
    if (!uni_utf8_str_is_valid(line)) {
        *error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
                                   line);
        return -1;
    }

    /* new mailbox. the search args are added to it later. */
    bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
    bbox->virtual_mbox = ctx->mbox;
    if (strcasecmp(line, "INBOX") == 0)
        line = "INBOX";
    bbox->name = p_strdup(ctx->pool, line);
    switch (bbox->name[0]) {
    case '+':
        bbox->name++;
        bbox->clear_recent = TRUE;
        break;
    case '-':
        bbox->name++;
        bbox->negative_match = TRUE;
        break;
    case '!':
        /* save messages here */
        if (ctx->mbox->save_bbox != NULL) {
            *error_r = "Multiple save mailboxes defined";
            return -1;
        }
        bbox->name++;
        ctx->mbox->save_bbox = bbox;
        no_wildcards = TRUE;
        break;
    }
    if (bbox->name[0] == '/') {
        /* [+-!]/metadata entry:value */
        if ((p = strchr(bbox->name, ':')) == NULL) {
            *error_r = "':' separator missing between metadata entry name and value";
            return -1;
        }
        bbox->metadata_entry = p_strdup_until(ctx->pool, bbox->name, p++);
        bbox->metadata_value = p;
        if (!imap_metadata_verify_entry_name(bbox->metadata_entry, error_r))
            return -1;
        no_wildcards = TRUE;
    }

    if (!no_wildcards &&
            (strchr(bbox->name, '*') != NULL ||
             strchr(bbox->name, '%') != NULL)) {
        bbox->glob = imap_match_init(ctx->pool, bbox->name, TRUE, ctx->sep);
        ctx->have_wildcards = TRUE;
    }
    if (bbox->metadata_entry == NULL) {
        /* now that the prefix characters have been processed,
           find the namespace */
        bbox->ns = strcasecmp(bbox->name, "INBOX") == 0 ?
                   mail_namespace_find_inbox(user->namespaces) :
                   mail_namespace_find(user->namespaces, bbox->name);
        if (bbox->ns == NULL) {
            *error_r = t_strdup_printf("Namespace not found for %s",
                                       bbox->name);
            return -1;
        }
        if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) {
            *error_r = "Virtual mailbox can't point to itself";
            return -1;
        }
        ctx->have_mailbox_defines = TRUE;
    }

    array_append(&ctx->mbox->backend_boxes, &bbox, 1);
    return 0;
}
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
			  const char **error_r)
{
	struct mail_user *user = ctx->mbox->storage->storage.user;
	struct virtual_backend_box *bbox;
	const char *name;

	if (*line == ' ' || *line == '\t') {
		/* continues the previous search rule */
		if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
			*error_r = "Search rule without a mailbox";
			return -1;
		}
		while (*line == ' ' || *line == '\t') line++;
		str_append_c(ctx->rule, ' ');
		str_append(ctx->rule, line);
		return 0;
	}
	/* if there is no rule yet, it means we want the previous mailboxes
	   to use the rule that comes later */
	if (str_len(ctx->rule) > 0) {
		if (virtual_config_add_rule(ctx, error_r) < 0)
			return -1;
	}

	/* new mailbox. the search args are added to it later. */
	bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
	if (strcasecmp(line, "INBOX") == 0)
		line = "INBOX";
	bbox->name = p_strdup(ctx->pool, line);
	if (*line == '-' || *line == '+' || *line == '!') line++;
	bbox->ns = strcasecmp(line, "INBOX") == 0 ?
		mail_namespace_find_inbox(user->namespaces) :
		mail_namespace_find(user->namespaces, line);
	if (!uni_utf8_str_is_valid(bbox->name)) {
		*error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
					   bbox->name);
		return -1;
	}
	if (bbox->ns == NULL) {
		*error_r = t_strdup_printf("Namespace not found for %s",
					   bbox->name);
		return -1;
	}
	if (bbox->name[0] == '+') {
		bbox->name++;
		bbox->clear_recent = TRUE;
	}

	if (strchr(bbox->name, '*') != NULL ||
	    strchr(bbox->name, '%') != NULL) {
		name = bbox->name[0] == '-' ? bbox->name + 1 : bbox->name;
		bbox->glob = imap_match_init(ctx->pool, name, TRUE, ctx->sep);
		ctx->have_wildcards = TRUE;
	} else if (bbox->name[0] == '!') {
		/* save messages here */
		if (ctx->mbox->save_bbox != NULL) {
			*error_r = "Multiple save mailboxes defined";
			return -1;
		}
		bbox->name++;
		ctx->mbox->save_bbox = bbox;
	}
	ctx->have_mailbox_defines = TRUE;
	array_append(&ctx->mbox->backend_boxes, &bbox, 1);
	return 0;
}
Ejemplo n.º 5
0
static void test_imap_match(void)
{
	struct test_imap_match test[] = {
		{ "", "", IMAP_MATCH_YES },
		{ "a", "b", IMAP_MATCH_NO },
		{ "foo", "foo", IMAP_MATCH_YES },
		{ "foo", "foo/", IMAP_MATCH_PARENT },
		{ "%", "", IMAP_MATCH_YES },
		{ "%", "foo", IMAP_MATCH_YES },
		{ "%", "foo/", IMAP_MATCH_PARENT },
		{ "%/", "foo/", IMAP_MATCH_YES },
		{ "%", "foo/bar", IMAP_MATCH_PARENT },
		{ "%/%", "foo", IMAP_MATCH_CHILDREN },
		{ "%/%", "foo/", IMAP_MATCH_YES },
		{ "foo/bar/%", "foo", IMAP_MATCH_CHILDREN },
		{ "foo/bar/%", "foo/", IMAP_MATCH_CHILDREN },
		{ "foo*", "foo", IMAP_MATCH_YES },
		{ "foo*", "foo/", IMAP_MATCH_YES },
		{ "foo*", "fobo", IMAP_MATCH_NO },
		{ "*foo*", "bar/foo/", IMAP_MATCH_YES },
		{ "*foo*", "fobo", IMAP_MATCH_CHILDREN },
		{ "foo*bar", "foobar/baz", IMAP_MATCH_CHILDREN | IMAP_MATCH_PARENT },
		{ "*foo*", "fobo", IMAP_MATCH_CHILDREN },
		{ "%/%/%", "foo/", IMAP_MATCH_CHILDREN },
		{ "%/%o/%", "foo/", IMAP_MATCH_CHILDREN },
		{ "%/%o/%", "foo", IMAP_MATCH_CHILDREN },
		{ "inbox", "inbox", IMAP_MATCH_YES },
		{ "inbox", "INBOX", IMAP_MATCH_NO }
	};
	struct test_imap_match inbox_test[] = {
		{ "inbox", "inbox", IMAP_MATCH_YES },
		{ "inbox", "iNbOx", IMAP_MATCH_YES },
		{ "i%X", "iNbOx", IMAP_MATCH_YES },
		{ "%I%N%B%O%X%", "inbox", IMAP_MATCH_YES },
		{ "i%X/foo", "iNbOx/foo", IMAP_MATCH_YES },
		{ "%I%N%B%O%X%/foo", "inbox/foo", IMAP_MATCH_YES },
		{ "i%X/foo", "inbx/foo", IMAP_MATCH_NO }
	};
	struct imap_match_glob *glob, *glob2;
	unsigned int i;
	pool_t pool;

	pool = pool_alloconly_create("imap match", 1024);

	/* first try tests without inboxcasing */
	test_begin("imap match");
	for (i = 0; i < N_ELEMENTS(test); i++) {
		glob = imap_match_init(pool, test[i].pattern,
				       FALSE, '/');
		test_assert(imap_match(glob, test[i].input) == test[i].result);

		glob2 = imap_match_dup(default_pool, glob);
		test_assert(imap_match_globs_equal(glob, glob2));
		p_clear(pool);

		/* test the dup after clearing first one's memory */
		test_assert(imap_match(glob2, test[i].input) == test[i].result);
		imap_match_deinit(&glob2);
	}

	/* inboxcasing tests */
	for (i = 0; i < N_ELEMENTS(inbox_test); i++) {
		glob = imap_match_init(pool, inbox_test[i].pattern,
				       TRUE, '/');
		test_assert(imap_match(glob, inbox_test[i].input) == inbox_test[i].result);

		glob2 = imap_match_dup(default_pool, glob);
		test_assert(imap_match_globs_equal(glob, glob2));
		p_clear(pool);

		/* test the dup after clearing first one's memory */
		test_assert(imap_match(glob2, inbox_test[i].input) == inbox_test[i].result);
		imap_match_deinit(&glob2);
	}
	pool_unref(&pool);
	test_end();
}