changeset 19116:73acc7075146

imap: NOTIFY (SUBSCRIPTIONS) assert-crashed when subscriptions hadn't been refreshed.
author Timo Sirainen <tss@iki.fi>
date Mon, 07 Sep 2015 23:08:44 +0300
parents bb80b907a116
children fa979ccfa34c
files src/imap/cmd-notify.c src/imap/imap-notify.h
diffstat 2 files changed, 28 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-notify.c	Mon Sep 07 22:35:30 2015 +0300
+++ b/src/imap/cmd-notify.c	Mon Sep 07 23:08:44 2015 +0300
@@ -206,11 +206,34 @@
 	}
 }
 
+static int
+imap_notify_refresh_subscriptions(struct client_command_context *cmd,
+				  struct imap_notify_context *ctx)
+{
+	struct mailbox_list_iterate_context *iter;
+	struct mail_namespace *ns;
+
+	if (!ctx->have_subscriptions)
+		return 0;
+
+	/* make sure subscriptions are refreshed at least once */
+	for (ns = ctx->client->user->namespaces; ns != NULL; ns = ns->next) {
+		iter = mailbox_list_iter_init(ns->list, "*", MAILBOX_LIST_ITER_SELECT_SUBSCRIBED);
+		(void)mailbox_list_iter_next(iter);
+		if (mailbox_list_iter_deinit(&iter) < 0) {
+			client_send_list_error(cmd, ns->list);
+			return -1;
+		}
+	}
+	return 0;
+}
+
 static void cmd_notify_add_subscribed(struct imap_notify_context *ctx,
 				      enum imap_notify_event events)
 {
 	struct mail_namespace *ns;
 
+	ctx->have_subscriptions = TRUE;
 	for (ns = ctx->client->user->namespaces; ns != NULL; ns = ns->next) {
 		cmd_notify_add_mailbox(ctx, ns, "",
 				       IMAP_NOTIFY_TYPE_SUBSCRIBED, events);
@@ -523,6 +546,10 @@
 			"NO [NOTIFICATIONOVERFLOW] Too many mailbox names");
 		pool_unref(&pool);
 		return TRUE;
+	} else if (imap_notify_refresh_subscriptions(cmd, ctx) < 0) {
+		/* tagline already sent */
+		pool_unref(&pool);
+		return TRUE;
 	} else if (imap_notify_begin(ctx) < 0) {
 		client_send_tagline(cmd,
 			"NO [NOTIFICATIONOVERFLOW] NOTIFY not supported for these mailboxes.");
--- a/src/imap/imap-notify.h	Mon Sep 07 22:35:30 2015 +0300
+++ b/src/imap/imap-notify.h	Mon Sep 07 23:08:44 2015 +0300
@@ -49,6 +49,7 @@
 	struct imap_fetch_context *fetch_ctx;
 	struct timeout *to_watch;
 
+	unsigned int have_subscriptions:1;
 	unsigned int selected_set:1;
 	unsigned int selected_immediate_expunges:1;
 	unsigned int send_immediate_status:1;