dovecot-1.1: LIST X-STATUS: Don't return STATUS reply for mailbo...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jun 10 20:07:17 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/0d7ea59a0dfa
changeset: 7625:0d7ea59a0dfa
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jun 10 20:07:13 2008 +0300
description:
LIST X-STATUS: Don't return STATUS reply for mailboxes that don't match the
LIST-EXTENDED selection criteria. Handle failures better if we can't look up
STATUS information.

diffstat:

1 file changed, 54 insertions(+), 20 deletions(-)
src/imap/cmd-list.c |   74 +++++++++++++++++++++++++++++++++++++--------------

diffs (135 lines):

diff -r 30c40c820021 -r 0d7ea59a0dfa src/imap/cmd-list.c
--- a/src/imap/cmd-list.c	Tue Jun 10 07:26:58 2008 +0300
+++ b/src/imap/cmd-list.c	Tue Jun 10 20:07:13 2008 +0300
@@ -22,6 +22,7 @@ struct cmd_list_context {
 
 	ARRAY_DEFINE(ns_prefixes_listed, struct mail_namespace *);
 
+	unsigned int status_failed:1;
 	unsigned int lsub:1;
 	unsigned int lsub_no_unsubscribed:1;
 	unsigned int inbox_found:1;
@@ -151,7 +152,6 @@ parse_return_flags(struct cmd_list_conte
 			list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN;
 		else if (strcasecmp(atom, "X-STATUS") == 0 &&
 			 args[1].type == IMAP_ARG_LIST) {
-			/* FIXME: this should probably be a plugin.. */
 			if (imap_status_parse_items(ctx->cmd,
 						IMAP_ARG_LIST_ARGS(&args[1]),
 						&ctx->status_items) < 0)
@@ -270,33 +270,54 @@ list_namespace_send_prefix(struct cmd_li
 	client_send_line(ctx->cmd->client, str_c(str));
 }
 
-static void list_send_status(struct cmd_list_context *ctx, const char *name)
-{
-	struct mailbox_status status;
+static bool list_want_status_reply(struct cmd_list_context *ctx,
+				   enum mailbox_info_flags flags)
+{
+	if ((flags & (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) != 0)
+		return FALSE;
+	if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 &&
+	    (flags & MAILBOX_SUBSCRIBED) == 0)
+		return FALSE;
+	return TRUE;
+}
+
+static bool list_get_status(struct cmd_list_context *ctx, const char *name,
+			    struct mailbox_status *status_r)
+{
 	const char *storage_name;
 	size_t prefix_len = strlen(ctx->ns->prefix);
+	const char *error_string;
+	enum mail_error error;
 
 	storage_name = strncmp(name, ctx->ns->prefix, prefix_len) == 0 ?
 		name + prefix_len : name;
 
-	if (!imap_status_get(ctx->cmd->client, ctx->ns->storage, storage_name,
-			     ctx->status_items, &status)) {
-		client_send_untagged_storage_error(ctx->cmd->client,
-						   ctx->ns->storage);
-		return;
-	}
-
-	imap_status_send(ctx->cmd->client, name, ctx->status_items, &status);
+	if (imap_status_get(ctx->cmd->client, ctx->ns->storage, storage_name,
+			    ctx->status_items, status_r))
+		return 1;
+
+	/* failed */
+	error_string = mail_storage_get_last_error(ctx->ns->storage, &error);
+	if (error == MAIL_ERROR_TEMP) {
+		client_send_line(ctx->cmd->client,
+				 t_strconcat("* NO ", error_string, NULL));
+		ctx->status_failed = TRUE;
+		return -1;
+	}
+	/* treat this mailbox as \NoSelect */
+	return 0;
 }
 
 static int
 list_namespace_mailboxes(struct cmd_list_context *ctx)
 {
+	struct mailbox_status status;
 	const struct mailbox_info *info;
 	struct mail_namespace *ns;
 	enum mailbox_info_flags flags;
 	string_t *str, *name_str;
 	const char *name;
+	bool status_send;
 	int ret = 0;
 
 	str = t_str_new(256);
@@ -340,6 +361,18 @@ list_namespace_mailboxes(struct cmd_list
 			continue;
 		}
 
+		status_send = FALSE;
+		if (ctx->status_items != 0 &&
+		    list_want_status_reply(ctx, flags)) T_BEGIN {
+			ret = list_get_status(ctx, name, &status);
+			if (ret > 0)
+				status_send = TRUE;
+			else if (ret == 0) {
+				/* turned into \NoSelect */
+				flags |= MAILBOX_NOSELECT;
+			}
+		} T_END;
+
 		str_truncate(str, 0);
 		str_printfa(str, "* %s (", ctx->lsub ? "LSUB" : "LIST");
 		mailbox_flags2str(ctx, str, flags);
@@ -348,11 +381,9 @@ list_namespace_mailboxes(struct cmd_list
 		mailbox_childinfo2str(ctx, str, flags);
 
 		ret = client_send_line(ctx->cmd->client, str_c(str));
-		if (ctx->status_items != 0 &&
-		    (flags & (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) == 0) {
-			T_BEGIN {
-				list_send_status(ctx, name);
-			} T_END;
+		if (status_send) {
+			imap_status_send(ctx->cmd->client, name,
+					 ctx->status_items, &status);
 		}
 		if (ret == 0) {
 			/* buffer is full, continue later */
@@ -683,9 +714,12 @@ static bool cmd_list_continue(struct cli
 		list_inbox(ctx);
 	}
 
-	client_send_tagline(cmd, !ctx->lsub ?
-			    "OK List completed." :
-			    "OK Lsub completed.");
+	if (ctx->lsub)
+		client_send_tagline(cmd, "OK Lsub completed.");
+	else if (!ctx->status_failed)
+		client_send_tagline(cmd, "OK List completed.");
+	else
+		client_send_tagline(cmd, "NO Some STATUS replies failed.");
 	return TRUE;
 }
 


More information about the dovecot-cvs mailing list