changeset 12583:4073ccc8123f

lib-storage: Replaced mailbox_list_get_name_status() with mailbox_exists().
author Timo Sirainen <tss@iki.fi>
date Thu, 20 Jan 2011 18:14:53 +0200
parents 3949d0091a44
children 8dbcf27f7c08
files src/imap/cmd-subscribe.c src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/index/imapc/imapc-storage.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/index/shared/shared-list.c src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/list/mailbox-list-none.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h src/lib-storage/test-mailbox.c src/plugins/acl/acl-mailbox-list.c src/plugins/acl/acl-mailbox.c src/plugins/listescape/listescape-plugin.c src/plugins/virtual/virtual-storage.c
diffstat 25 files changed, 89 insertions(+), 206 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-subscribe.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/imap/cmd-subscribe.c	Thu Jan 20 18:14:53 2011 +0200
@@ -29,9 +29,10 @@
 static bool
 subscribe_is_valid_name(struct client_command_context *cmd, const char *mailbox)
 {
-	enum mailbox_name_status name_status;
 	struct mail_namespace *ns;
+	struct mailbox *box;
 	const char *storage_name;
+	int ret;
 
 	if (have_listable_namespace_prefix(cmd->client->user->namespaces,
 					   mailbox)) {
@@ -44,12 +45,15 @@
 	if (ns == NULL)
 		return FALSE;
 
-	if (mailbox_list_get_mailbox_name_status(ns->list, storage_name,
-						 &name_status) < 0) {
-		client_send_list_error(cmd, ns->list);
+	box = mailbox_alloc(ns->list, storage_name, 0);
+	if ((ret = mailbox_exists(box)) < 0) {
+		client_send_storage_error(cmd, mailbox_get_storage(box));
+		mailbox_free(&box);
 		return FALSE;
 	}
-	if (name_status == MAILBOX_NAME_NONEXISTENT) {
+	mailbox_free(&box);
+
+	if (ret == 0) {
 		client_send_tagline(cmd, t_strdup_printf(
 			"NO "MAIL_ERRSTR_MAILBOX_NOT_FOUND, mailbox));
 		return FALSE;
--- a/src/lib-storage/index/cydir/cydir-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -136,6 +136,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		cydir_mailbox_open,
 		index_storage_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -409,6 +409,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		mdbox_mailbox_open,
 		mdbox_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -367,6 +367,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		sdbox_mailbox_open,
 		sdbox_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/imapc/imapc-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -536,6 +536,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		imapc_mailbox_open,
 		imapc_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/index-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/index-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -150,6 +150,31 @@
 					  box->index_prefix);
 }
 
+int index_storage_mailbox_exists(struct mailbox *box)
+{
+	struct stat st;
+	const char *path;
+
+	if (strcmp(box->name, "INBOX") == 0 &&
+	    (box->list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
+		/* INBOX always exists */
+		return 1;
+	}
+
+	path = mailbox_list_get_path(box->list, box->name,
+				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
+	if (stat(path, &st) == 0)
+		return 1;
+	else if (ENOTFOUND(errno) || errno == EACCES)
+		return 0;
+	else {
+		mail_storage_set_critical(box->storage,
+					  "stat(%s) failed: %m", path);
+		return -1;
+	}
+}
+
+
 int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
 {
 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
--- a/src/lib-storage/index/index-storage.h	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/index-storage.h	Thu Jan 20 18:14:53 2011 +0200
@@ -63,6 +63,7 @@
 void index_storage_mailbox_alloc(struct mailbox *box, const char *name,
 				 enum mailbox_flags flags,
 				 const char *index_prefix);
+int index_storage_mailbox_exists(struct mailbox *box);
 int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory);
 int index_storage_mailbox_enable(struct mailbox *box,
 				 enum mailbox_feature feature);
--- a/src/lib-storage/index/maildir/maildir-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -643,6 +643,7 @@
 		maildir_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		maildir_mailbox_open,
 		maildir_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -753,6 +753,7 @@
 		mbox_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		mbox_mailbox_open,
 		mbox_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/raw/raw-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/raw/raw-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -136,6 +136,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		raw_mailbox_open,
 		index_storage_mailbox_close,
 		index_storage_mailbox_free,
--- a/src/lib-storage/index/shared/shared-list.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/index/shared/shared-list.c	Thu Jan 20 18:14:53 2011 +0200
@@ -110,21 +110,6 @@
 	return mailbox_list_get_path(ns->list, name, type);
 }
 
-static int
-shared_list_get_mailbox_name_status(struct mailbox_list *list, const char *name,
-				    enum mailbox_name_status *status_r)
-{
-	struct mail_namespace *ns = list->ns;
-	int ret;
-
-	if (shared_storage_get_namespace(&ns, &name) < 0)
-		return -1;
-	ret = mailbox_list_get_mailbox_name_status(ns->list, name, status_r);
-	if (ret < 0)
-		shared_list_copy_error(list, ns);
-	return ret;
-}
-
 static const char *
 shared_list_get_temp_prefix(struct mailbox_list *list, bool global ATTR_UNUSED)
 {
@@ -326,7 +311,6 @@
 		shared_is_valid_existing_name,
 		shared_is_valid_create_name,
 		shared_list_get_path,
-		shared_list_get_mailbox_name_status,
 		shared_list_get_temp_prefix,
 		shared_list_join_refpattern,
 		shared_list_iter_init,
--- a/src/lib-storage/list/mailbox-list-fs.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-fs.c	Thu Jan 20 18:14:53 2011 +0200
@@ -211,58 +211,6 @@
 	}
 }
 
-static int
-fs_list_get_mailbox_name_status(struct mailbox_list *_list, const char *name,
-				enum mailbox_name_status *status)
-{
-	struct stat st;
-	const char *path, *dir_path;
-	enum mailbox_info_flags flags;
-
-	if (strcmp(name, "INBOX") == 0 &&
-	    (_list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
-		*status = MAILBOX_NAME_EXISTS_MAILBOX;
-		return 0;
-	}
-
-	path = mailbox_list_get_path(_list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(path, &st) == 0) {
-		if (*_list->set.maildir_name != '\0' ||
-		    _list->v.is_internal_name == NULL || !S_ISDIR(st.st_mode)) {
-			*status = MAILBOX_NAME_EXISTS_MAILBOX;
-			return 0;
-		}
-
-		/* check if mailbox is selectable */
-		if (mailbox_list_mailbox(_list, name, &flags) < 0)
-			return -1;
-		if ((flags & (MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) == 0)
-			*status = MAILBOX_NAME_EXISTS_MAILBOX;
-		else
-			*status = MAILBOX_NAME_EXISTS_DIR;
-		return 0;
-	}
-	if (errno == ENOENT) {
-		/* see if the directory exists */
-		dir_path = mailbox_list_get_path(_list, name,
-						 MAILBOX_LIST_PATH_TYPE_DIR);
-		if (strcmp(path, dir_path) != 0 && stat(dir_path, &st) == 0) {
-			*status = MAILBOX_NAME_EXISTS_DIR;
-			return 0;
-		}
-		errno = ENOENT;
-	}
-
-	if (ENOTFOUND(errno) || errno == EACCES) {
-		*status = MAILBOX_NAME_NONEXISTENT;
-		return 0;
-	} else {
-		mailbox_list_set_critical(_list, "stat(%s) failed: %m", path);
-		return -1;
-	}
-}
-
 static const char *
 fs_list_get_temp_prefix(struct mailbox_list *_list, bool global)
 {
@@ -628,7 +576,6 @@
 		fs_is_valid_existing_name,
 		fs_is_valid_create_name,
 		fs_list_get_path,
-		fs_list_get_mailbox_name_status,
 		fs_list_get_temp_prefix,
 		fs_list_join_refpattern,
 		fs_list_iter_init,
--- a/src/lib-storage/list/mailbox-list-maildir.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Thu Jan 20 18:14:53 2011 +0200
@@ -222,33 +222,6 @@
 	return maildir_list_get_dirname_path(_list, root_dir, name);
 }
 
-static int
-maildir_list_get_mailbox_name_status(struct mailbox_list *_list,
-				     const char *name,
-				     enum mailbox_name_status *status)
-{
-	struct stat st;
-	const char *path;
-
-	path = mailbox_list_get_path(_list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
-	if ((strcmp(name, "INBOX") == 0 &&
-	     (_list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) ||
-	    stat(path, &st) == 0) {
-		*status = MAILBOX_NAME_EXISTS_MAILBOX;
-		return 0;
-	}
-
-	if (ENOTFOUND(errno) || errno == EACCES) {
-		*status = MAILBOX_NAME_NONEXISTENT;
-		return 0;
-	} else {
-		mailbox_list_set_critical(_list, "stat(%s) failed: %m", path);
-		return -1;
-	}
-}
-
 static const char *
 maildir_list_get_temp_prefix(struct mailbox_list *_list, bool global)
 {
@@ -637,7 +610,6 @@
 		maildir_is_valid_existing_name,
 		maildir_is_valid_create_name,
 		maildir_list_get_path,
-		maildir_list_get_mailbox_name_status,
 		maildir_list_get_temp_prefix,
 		NULL,
 		maildir_list_iter_init,
@@ -669,7 +641,6 @@
 		maildir_is_valid_existing_name,
 		maildir_is_valid_create_name,
 		maildir_list_get_path,
-		maildir_list_get_mailbox_name_status,
 		maildir_list_get_temp_prefix,
 		NULL,
 		maildir_list_iter_init,
--- a/src/lib-storage/list/mailbox-list-none.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-none.c	Thu Jan 20 18:14:53 2011 +0200
@@ -57,15 +57,6 @@
 	return NULL;
 }
 
-static int
-none_list_get_mailbox_name_status(struct mailbox_list *list ATTR_UNUSED,
-				  const char *name ATTR_UNUSED,
-				  enum mailbox_name_status *status)
-{
-	*status = MAILBOX_NAME_NONEXISTENT;
-	return 0;
-}
-
 static const char *
 none_list_get_temp_prefix(struct mailbox_list *list ATTR_UNUSED,
 			  bool global ATTR_UNUSED)
@@ -168,7 +159,6 @@
 		none_is_valid_existing_name,
 		none_is_valid_create_name,
 		none_list_get_path,
-		none_list_get_mailbox_name_status,
 		none_list_get_temp_prefix,
 		NULL,
 		none_list_iter_init,
--- a/src/lib-storage/mail-storage-private.h	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mail-storage-private.h	Thu Jan 20 18:14:53 2011 +0200
@@ -103,6 +103,7 @@
 	bool (*allow_new_keywords)(struct mailbox *box);
 
 	int (*enable)(struct mailbox *box, enum mailbox_feature features);
+	int (*exists)(struct mailbox *box);
 	int (*open)(struct mailbox *box);
 	void (*close)(struct mailbox *box);
 	void (*free)(struct mailbox *box);
--- a/src/lib-storage/mail-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mail-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -567,6 +567,17 @@
 	return box;
 }
 
+int mailbox_exists(struct mailbox *box)
+{
+	if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
+		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+				       "Invalid mailbox name");
+		return -1;
+	}
+
+	return box->v.exists(box);
+}
+
 static int mailbox_open_full(struct mailbox *box, struct istream *input)
 {
 	int ret;
--- a/src/lib-storage/mail-storage.h	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mail-storage.h	Thu Jan 20 18:14:53 2011 +0200
@@ -338,6 +338,9 @@
    with possibly different readonly-state. */
 struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
 			      enum mailbox_flags flags);
+/* Returns 1 if mailbox exists (even if it's unselectable),
+   0 if not and -1 if some error occurred. */
+int mailbox_exists(struct mailbox *box);
 /* Open the mailbox. If this function isn't called explicitly, it's also called
    internally by lib-storage when necessary. */
 int mailbox_open(struct mailbox *box);
--- a/src/lib-storage/mailbox-list-private.h	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mailbox-list-private.h	Thu Jan 20 18:14:53 2011 +0200
@@ -45,9 +45,6 @@
 
 	const char *(*get_path)(struct mailbox_list *list, const char *name,
 				enum mailbox_list_path_type type);
-	int (*get_mailbox_name_status)(struct mailbox_list *list,
-				       const char *name,
-				       enum mailbox_name_status *status);
 
 	const char *(*get_temp_prefix)(struct mailbox_list *list, bool global);
 	const char *(*join_refpattern)(struct mailbox_list *list,
--- a/src/lib-storage/mailbox-list.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mailbox-list.c	Thu Jan 20 18:14:53 2011 +0200
@@ -775,18 +775,6 @@
 	return pattern;
 }
 
-int mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
-					 const char *name,
-					 enum mailbox_name_status *status)
-{
-	if (!mailbox_list_is_valid_existing_name(list, name)) {
-		mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
-				       "Invalid mailbox name");
-		return -1;
-	}
-	return list->v.get_mailbox_name_status(list, name, status);
-}
-
 struct mailbox_list_iterate_context *
 mailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
 		       enum mailbox_list_iter_flags flags)
--- a/src/lib-storage/mailbox-list.h	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/mailbox-list.h	Thu Jan 20 18:14:53 2011 +0200
@@ -48,14 +48,6 @@
 	MAILBOX_MATCHED			= 0x40000000
 };
 
-enum mailbox_name_status {
-	MAILBOX_NAME_NONEXISTENT,
-	/* name points to a selectable mailbox */
-	MAILBOX_NAME_EXISTS_MAILBOX,
-	/* name points to non-selectable mailbox */
-	MAILBOX_NAME_EXISTS_DIR
-};
-
 enum mailbox_list_iter_flags {
 	/* Ignore index file and ACLs (used by ACL plugin internally) */
 	MAILBOX_LIST_ITER_RAW_LIST		= 0x000001,
@@ -211,10 +203,6 @@
    For INDEX=MEMORY it returns "" as the path. */
 const char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
 				  enum mailbox_list_path_type type);
-/* Returns mailbox name status */
-int mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
-					 const char *name,
-					 enum mailbox_name_status *status);
 /* Returns mailbox's change log, or NULL if it doesn't have one. */
 struct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list);
 /* Specify timestamp to use when writing mailbox changes to changelog.
--- a/src/lib-storage/test-mailbox.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/lib-storage/test-mailbox.c	Thu Jan 20 18:14:53 2011 +0200
@@ -24,6 +24,11 @@
 	return 0;
 }
 
+static int test_mailbox_exists(struct mailbox *box ATTR_UNUSED)
+{
+	return 1;
+}
+
 static int test_mailbox_open(struct mailbox *box ATTR_UNUSED)
 {
 	return 0;
@@ -229,6 +234,7 @@
 		test_mailbox_is_readonly,
 		test_mailbox_allow_new_keywords,
 		test_mailbox_enable,
+		test_mailbox_exists,
 		test_mailbox_open,
 		test_mailbox_close,
 		NULL,
--- a/src/plugins/acl/acl-mailbox-list.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/plugins/acl/acl-mailbox-list.c	Thu Jan 20 18:14:53 2011 +0200
@@ -407,59 +407,6 @@
 	return ret;
 }
 
-static int acl_mailbox_have_visibility_rights(struct acl_mailbox_list *alist,
-					      const char *name)
-{
-	struct acl_object *aclobj;
-	const char *const *rights;
-	unsigned int i;
-	int ret;
-
-	aclobj = acl_object_init_from_name(alist->rights.backend, name);
-	ret = acl_object_get_my_rights(aclobj, pool_datastack_create(),
-				       &rights);
-	acl_object_deinit(&aclobj);
-
-	if (ret < 0)
-		return -1;
-
-	/* for now this is used only by IMAP SUBSCRIBE. we'll intentionally
-	   violate RFC 4314 here, because it says SUBSCRIBE should succeed only
-	   when mailbox has 'l' right. But there's no point in not allowing
-	   a subscribe for a mailbox that can be selected anyway. Just the
-	   opposite: subscribing to such mailboxes is a very useful feature. */
-	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_INSERT) == 0)
-			return 1;
-	}
-	return 0;
-}
-
-static int acl_get_mailbox_name_status(struct mailbox_list *list,
-				       const char *name,
-				       enum mailbox_name_status *status)
-{
-	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
-	int ret;
-
-	T_BEGIN {
-		ret = acl_mailbox_have_visibility_rights(alist, name);
-	} T_END;
-	if (ret < 0)
-		return -1;
-
-	if (alist->module_ctx.super.get_mailbox_name_status(list, name,
-							    status) < 0)
-		return -1;
-	if (ret == 0) {
-		/* we shouldn't reveal this mailbox's existance */
-		*status = MAILBOX_NAME_NONEXISTENT;
-	}
-	return 0;
-}
-
 static int
 acl_mailbox_list_create_dir(struct mailbox_list *list, const char *name,
 			    enum mailbox_dir_create_type type)
@@ -537,7 +484,6 @@
 	v->iter_init = acl_mailbox_list_iter_init;
 	v->iter_next = acl_mailbox_list_iter_next;
 	v->iter_deinit = acl_mailbox_list_iter_deinit;
-	v->get_mailbox_name_status = acl_get_mailbox_name_status;
 	v->create_mailbox_dir = acl_mailbox_list_create_dir;
 
 	MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
--- a/src/plugins/acl/acl-mailbox.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/plugins/acl/acl-mailbox.c	Thu Jan 20 18:14:53 2011 +0200
@@ -428,6 +428,30 @@
 	return abox->module_ctx.super.transaction_commit(ctx, changes_r);
 }
 
+static int acl_mailbox_exists(struct mailbox *box)
+{
+	struct acl_mailbox *abox = ACL_CONTEXT(box);
+	const char *const *rights;
+	unsigned int i;
+
+	if (acl_object_get_my_rights(abox->aclobj, pool_datastack_create(),
+				     &rights) < 0)
+		return -1;
+
+	/* for now this is used only by IMAP SUBSCRIBE. we'll intentionally
+	   violate RFC 4314 here, because it says SUBSCRIBE should succeed only
+	   when mailbox has 'l' right. But there's no point in not allowing
+	   a subscribe for a mailbox that can be selected anyway. Just the
+	   opposite: subscribing to such mailboxes is a very useful feature. */
+	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_INSERT) == 0)
+			return abox->module_ctx.super.exists(box);
+	}
+	return 0;
+}
+
 static int acl_mailbox_open_check_acl(struct mailbox *box)
 {
 	struct acl_mailbox *abox = ACL_CONTEXT(box);
@@ -494,6 +518,7 @@
 		abox->acl_enabled = TRUE;
 		v->is_readonly = acl_is_readonly;
 		v->allow_new_keywords = acl_allow_new_keywords;
+		v->exists = acl_mailbox_exists;
 		v->open = acl_mailbox_open;
 		v->create = acl_mailbox_create;
 		v->update = acl_mailbox_update;
--- a/src/plugins/listescape/listescape-plugin.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/plugins/listescape/listescape-plugin.c	Thu Jan 20 18:14:53 2011 +0200
@@ -285,17 +285,6 @@
 	return mlist->module_ctx.super.set_subscribed(list, name, set);
 }
 
-static int listescape_get_mailbox_name_status(struct mailbox_list *list,
-					      const char *name,
-					      enum mailbox_name_status *status)
-{
-	struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-
-	name = list_escape(mlist, list->ns, name, FALSE);
-	return mlist->module_ctx.super.
-		get_mailbox_name_status(list, name, status);
-}
-
 static bool listescape_is_valid_existing_name(struct mailbox_list *list,
 					      const char *name)
 {
@@ -346,7 +335,6 @@
 	v->iter_next = listescape_mailbox_list_iter_next;
 	v->iter_deinit = listescape_mailbox_list_iter_deinit;
 	v->set_subscribed = listescape_set_subscribed;
-	v->get_mailbox_name_status = listescape_get_mailbox_name_status;
 	v->is_valid_existing_name = listescape_is_valid_existing_name;
 	v->is_valid_create_name = listescape_is_valid_create_name;
 
--- a/src/plugins/virtual/virtual-storage.c	Wed Jan 19 01:21:03 2011 +0200
+++ b/src/plugins/virtual/virtual-storage.c	Thu Jan 20 18:14:53 2011 +0200
@@ -513,6 +513,7 @@
 		index_storage_is_readonly,
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
+		index_storage_mailbox_exists,
 		virtual_mailbox_open,
 		virtual_mailbox_close,
 		virtual_mailbox_free,