diff --git a/src/plugins/acl/acl-api.c b/src/plugins/acl/acl-api.c index 33410a51e78..5891fe9fb6a 100644 --- a/src/plugins/acl/acl-api.c +++ b/src/plugins/acl/acl-api.c @@ -19,6 +19,7 @@ struct acl_letter_map { static const struct acl_letter_map acl_letter_map[] = { { 'l', MAIL_ACL_LOOKUP }, { 'r', MAIL_ACL_READ }, + { 'f', MAIL_ACL_FAKE_EMPTY}, { 'w', MAIL_ACL_WRITE }, { 's', MAIL_ACL_WRITE_SEEN }, { 't', MAIL_ACL_WRITE_DELETED }, @@ -78,6 +79,10 @@ int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx) MAIL_ACL_READ); if (acl_cache_mask_isset(have_mask, read_idx)) return 1; + read_idx = acl_backend_lookup_right(aclobj->backend, + MAIL_ACL_FAKE_EMPTY); + if (acl_cache_mask_isset(have_mask, read_idx)) + return 1; } return 0; } diff --git a/src/plugins/acl/acl-api.h b/src/plugins/acl/acl-api.h index beb28072d42..2eded0d8c8a 100644 --- a/src/plugins/acl/acl-api.h +++ b/src/plugins/acl/acl-api.h @@ -10,6 +10,8 @@ struct acl_object; #define MAIL_ACL_LOOKUP "lookup" /* Allow opening mailbox for reading */ #define MAIL_ACL_READ "read" +/* The mailbox is readable but no messages are returned */ +#define MAIL_ACL_FAKE_EMPTY "fake-empty" /* Allow permanent flag changes (except for seen/deleted). If not set, doesn't allow save/copy to set any flags either. */ #define MAIL_ACL_WRITE "write" diff --git a/src/plugins/acl/acl-attributes.c b/src/plugins/acl/acl-attributes.c index 53792924a3e..1a10e0fcc66 100644 --- a/src/plugins/acl/acl-attributes.c +++ b/src/plugins/acl/acl-attributes.c @@ -132,6 +132,8 @@ static int acl_have_attribute_rights(struct mailbox *box) return 0; if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_POST) > 0) return 0; + if (acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_FAKE_EMPTY) > 0) + return 0; return -1; } diff --git a/src/plugins/acl/acl-backend.c b/src/plugins/acl/acl-backend.c index e620efa7687..536e17d8107 100644 --- a/src/plugins/acl/acl-backend.c +++ b/src/plugins/acl/acl-backend.c @@ -15,6 +15,7 @@ extern struct acl_backend_vfuncs acl_backend_vfile; const char *const all_mailbox_rights[] = { MAIL_ACL_LOOKUP, MAIL_ACL_READ, + MAIL_ACL_FAKE_EMPTY, MAIL_ACL_WRITE, MAIL_ACL_WRITE_SEEN, MAIL_ACL_WRITE_DELETED, diff --git a/src/plugins/acl/acl-mailbox-list.c b/src/plugins/acl/acl-mailbox-list.c index dace9e99f7d..cde36f9a5ca 100644 --- a/src/plugins/acl/acl-mailbox-list.c +++ b/src/plugins/acl/acl-mailbox-list.c @@ -29,6 +29,7 @@ struct acl_mailbox_list_iterate_context { static const char *acl_storage_right_names[ACL_STORAGE_RIGHT_COUNT] = { MAIL_ACL_LOOKUP, MAIL_ACL_READ, + MAIL_ACL_FAKE_EMPTY, MAIL_ACL_WRITE, MAIL_ACL_WRITE_SEEN, MAIL_ACL_WRITE_DELETED, diff --git a/src/plugins/acl/acl-mailbox.c b/src/plugins/acl/acl-mailbox.c index da6c05b0f69..17f6ad60b7d 100644 --- a/src/plugins/acl/acl-mailbox.c +++ b/src/plugins/acl/acl-mailbox.c @@ -364,6 +364,16 @@ void acl_mail_allocated(struct mail *_mail) MODULE_CONTEXT_SET_SELF(mail, acl_mail_module, amail); } +bool acl_search_next_nonblock(struct mail_search_context *ctx, + struct mail **mail_r, bool *tryagain_r) { + struct acl_mailbox *abox = ACL_CONTEXT(ctx->transaction->box); + + if (acl_mailbox_right_lookup(ctx->transaction->box, ACL_STORAGE_RIGHT_FAKE_EMPTY) > 0) { + return FALSE; + } + return abox->module_ctx.super.search_next_nonblock(ctx, mail_r, tryagain_r); +} + static int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags, enum mail_flags *pvt_flags, struct mail_keywords **keywords) @@ -484,6 +494,7 @@ static int acl_mailbox_exists(struct mailbox *box, bool auto_boxes, for (i = 0; rights[i] != NULL; i++) { if (strcmp(rights[i], MAIL_ACL_LOOKUP) == 0 || strcmp(rights[i], MAIL_ACL_READ) == 0 || + strcmp(rights[i], MAIL_ACL_FAKE_EMPTY) == 0 || strcmp(rights[i], MAIL_ACL_INSERT) == 0) return abox->module_ctx.super.exists(box, auto_boxes, existence_r); @@ -516,6 +527,9 @@ static int acl_mailbox_open_check_acl(struct mailbox *box) } ret = acl_object_have_right(abox->aclobj, idx_arr[open_right]); + if (ret == 0 && open_right == ACL_STORAGE_RIGHT_READ) { + ret = acl_object_have_right(abox->aclobj, idx_arr[ACL_STORAGE_RIGHT_FAKE_EMPTY]); + } if (ret <= 0) { if (ret == 0) { /* no access. */ @@ -612,6 +626,7 @@ void acl_mailbox_allocated(struct mailbox *box) v->attribute_iter_init = acl_attribute_iter_init; v->attribute_iter_next = acl_attribute_iter_next; v->attribute_iter_deinit = acl_attribute_iter_deinit; + v->search_next_nonblock = acl_search_next_nonblock; } MODULE_CONTEXT_SET(box, acl_storage_module, abox); } diff --git a/src/plugins/acl/acl-storage.h b/src/plugins/acl/acl-storage.h index e04d08e1166..39e3fa74034 100644 --- a/src/plugins/acl/acl-storage.h +++ b/src/plugins/acl/acl-storage.h @@ -8,6 +8,7 @@ struct acl_rights_update; enum acl_storage_rights { ACL_STORAGE_RIGHT_LOOKUP, ACL_STORAGE_RIGHT_READ, + ACL_STORAGE_RIGHT_FAKE_EMPTY, ACL_STORAGE_RIGHT_WRITE, ACL_STORAGE_RIGHT_WRITE_SEEN, ACL_STORAGE_RIGHT_WRITE_DELETED,