dovecot-2.2: Merged changes from v2.1 tree.

dovecot at dovecot.org dovecot at dovecot.org
Mon Aug 20 11:09:53 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/2fc74b72817b
changeset: 14939:2fc74b72817b
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Aug 20 11:09:42 2012 +0300
description:
Merged changes from v2.1 tree.

diffstat:

 configure.in                                 |    2 +-
 src/doveadm/doveadm-mail-server.c            |    3 +
 src/imap/cmd-list.c                          |    6 +-
 src/imap/cmd-thread.c                        |  148 ++++++++++++++++++++++++++-
 src/lib-imap-client/imapc-client.h           |    1 +
 src/lib-imap-client/imapc-connection.c       |    4 +-
 src/lib-storage/index/imapc/imapc-settings.c |    4 +
 src/lib-storage/index/imapc/imapc-settings.h |    2 +
 src/lib-storage/index/imapc/imapc-storage.c  |    1 +
 src/lib-storage/list/mailbox-list-fs-iter.c  |   32 ++++-
 src/lib-storage/mail-namespace.c             |   11 +-
 src/lib-storage/mail-namespace.h             |    5 +-
 src/lib-storage/mail-storage.h               |    5 +-
 src/lib-storage/mail-thread.c                |    2 +
 src/lib-storage/mailbox-list.c               |    6 +-
 src/lib/ioloop.c                             |    4 +-
 16 files changed, 214 insertions(+), 22 deletions(-)

diffs (truncated from 495 to 300 lines):

diff -r 9c69df65af7b -r 2fc74b72817b configure.in
--- a/configure.in	Mon Aug 20 10:54:04 2012 +0300
+++ b/configure.in	Mon Aug 20 11:09:42 2012 +0300
@@ -2718,7 +2718,7 @@
 dnl IDLE doesn't really belong to banner. It's there just to make Blackberries
 dnl happy, because otherwise BIS server disables push email.
 capability_banner="IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
-capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE"
+capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE"
 AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities)
 AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", IMAP capabilities advertised in banner) 
 
diff -r 9c69df65af7b -r 2fc74b72817b src/doveadm/doveadm-mail-server.c
--- a/src/doveadm/doveadm-mail-server.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/doveadm/doveadm-mail-server.c	Mon Aug 20 11:09:42 2012 +0300
@@ -181,6 +181,9 @@
 	if (ret < 0) {
 		*error_r = fields[0] != NULL ?
 			t_strdup(fields[0]) : "passdb lookup failed";
+		*error_r = t_strdup_printf("%s (to see if user is proxied, "
+					   "because doveadm_proxy_port is set)",
+					   *error_r);
 	} else if (ret == 0) {
 		/* user not found from passdb. it could be in userdb though,
 		   so just continue with the default host */
diff -r 9c69df65af7b -r 2fc74b72817b src/imap/cmd-list.c
--- a/src/imap/cmd-list.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/imap/cmd-list.c	Mon Aug 20 11:09:42 2012 +0300
@@ -438,10 +438,12 @@
 		if (ctx->cur_ns_send_prefix)
 			list_namespace_send_prefix(ctx, TRUE);
 
-		/* if there's a namespace with this name, list it as
+		/* if there's a list=yes namespace with this name, list it as
 		   having children */
 		ns = mail_namespace_find_prefix_nosep(ctx->ns, name);
-		if (ns != NULL) {
+		if (ns != NULL &&
+		    (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+				  NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
 			flags |= MAILBOX_CHILDREN;
 			flags &= ~MAILBOX_NOCHILDREN;
 			array_append(&ctx->ns_prefixes_listed, &ns, 1);
diff -r 9c69df65af7b -r 2fc74b72817b src/imap/cmd-thread.c
--- a/src/imap/cmd-thread.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/imap/cmd-thread.c	Mon Aug 20 11:09:42 2012 +0300
@@ -3,6 +3,7 @@
 #include "imap-common.h"
 #include "str.h"
 #include "ostream.h"
+#include "imap-base-subject.h"
 #include "imap-commands.h"
 #include "imap-search-args.h"
 #include "mail-thread.h"
@@ -100,6 +101,148 @@
 	return ret;
 }
 
+struct orderedsubject_thread {
+	time_t timestamp;
+	ARRAY_TYPE(uint32_t) msgs;
+};
+
+static int orderedsubject_thread_cmp(const struct orderedsubject_thread *t1,
+				     const struct orderedsubject_thread *t2)
+{
+	const uint32_t *m1, *m2;
+
+	if (t1->timestamp < t2->timestamp)
+		return -1;
+	if (t1->timestamp > t2->timestamp)
+		return 1;
+
+	m1 = array_idx(&t1->msgs, 0);
+	m2 = array_idx(&t2->msgs, 0);
+	if (*m1 < *m2)
+		return -1;
+	if (*m1 > *m2)
+		return 1;
+	i_unreached();
+}
+
+static void
+imap_orderedsubject_thread_write(struct ostream *output, string_t *reply,
+				 const struct orderedsubject_thread *thread)
+{
+	const uint32_t *msgs;
+	unsigned int i, count;
+
+	if (str_len(reply) > 128-10) {
+		o_stream_send(output, str_data(reply), str_len(reply));
+		str_truncate(reply, 0);
+	}
+
+	msgs = array_get(&thread->msgs, &count);
+	switch (count) {
+	case 1:
+		str_printfa(reply, "(%u)", msgs[0]);
+		break;
+	case 2:
+		str_printfa(reply, "(%u %u)", msgs[0], msgs[1]);
+		break;
+	default:
+		/* (1 (2)(3)) */
+		str_printfa(reply, "(%u ", msgs[0]);
+		for (i = 1; i < count; i++) {
+			if (str_len(reply) > 128-10) {
+				o_stream_send(output, str_data(reply),
+					      str_len(reply));
+				str_truncate(reply, 0);
+			}
+			str_printfa(reply, "(%u)", msgs[i]);
+		}
+		str_append_c(reply, ')');
+	}
+}
+
+static int imap_thread_orderedsubject(struct client_command_context *cmd,
+				      struct mail_search_args *search_args)
+{
+	static const enum mail_sort_type sort_program[] = {
+		MAIL_SORT_SUBJECT,
+		MAIL_SORT_DATE,
+		0
+	};
+	struct mailbox_transaction_context *trans;
+	struct mail_search_context *search_ctx;
+	struct mail *mail;
+	string_t *prev_subject, *reply;
+	const char *subject, *base_subject;
+	pool_t pool;
+	ARRAY(struct orderedsubject_thread) threads;
+	const struct orderedsubject_thread *thread;
+	struct orderedsubject_thread *cur_thread = NULL;
+	uint32_t num;
+	int ret;
+
+	prev_subject = str_new(default_pool, 128);
+
+	/* first read all of the threads into memory */
+	pool = pool_alloconly_create("orderedsubject thread", 1024);
+	i_array_init(&threads, 128);
+	trans = mailbox_transaction_begin(cmd->client->mailbox, 0);
+	search_ctx = mailbox_search_init(trans, search_args, sort_program,
+					 0, NULL);
+	while (mailbox_search_next(search_ctx, &mail)) {
+		if (mail_get_first_header(mail, "Subject", &subject) <= 0)
+			subject = "";
+		T_BEGIN {
+			base_subject = imap_get_base_subject_cased(
+					pool_datastack_create(), subject, NULL);
+			if (strcmp(str_c(prev_subject), base_subject) != 0) {
+				/* thread changed */
+				cur_thread = NULL;
+			}
+			str_truncate(prev_subject, 0);
+			str_append(prev_subject, base_subject);
+		} T_END;
+
+		if (cur_thread == NULL) {
+			/* starting a new thread. get the first message's
+			   date */
+			cur_thread = array_append_space(&threads);
+			if (mail_get_date(mail, &cur_thread->timestamp, NULL) == 0 &&
+			    cur_thread->timestamp == 0) {
+				(void)mail_get_received_date(mail,
+					&cur_thread->timestamp);
+			}
+			p_array_init(&cur_thread->msgs, pool, 4);
+		}
+		num = cmd->uid ? mail->uid : mail->seq;
+		array_append(&cur_thread->msgs, &num, 1);
+	}
+	str_free(&prev_subject);
+	ret = mailbox_search_deinit(&search_ctx);
+	(void)mailbox_transaction_commit(&trans);
+	if (ret < 0) {
+		array_free(&threads);
+		pool_unref(&pool);
+		return -1;
+	}
+
+	/* sort the threads by their first message's timestamp */
+	array_sort(&threads, orderedsubject_thread_cmp);
+
+	/* write the threads to client */
+	reply = t_str_new(128);
+	str_append(reply, "* THREAD ");
+	array_foreach(&threads, thread) {
+		imap_orderedsubject_thread_write(cmd->client->output,
+						 reply, thread);
+	}
+	str_append(reply, "\r\n");
+	o_stream_send(cmd->client->output, str_data(reply), str_len(reply));
+
+	array_free(&threads);
+	pool_unref(&pool);
+	return 0;
+}
+
 bool cmd_thread(struct client_command_context *cmd)
 {
 	struct client *client = cmd->client;
@@ -131,7 +274,10 @@
 	if (ret <= 0)
 		return ret < 0;
 
-	ret = imap_thread(cmd, sargs, thread_type);
+	if (thread_type != MAIL_THREAD_ORDEREDSUBJECT)
+		ret = imap_thread(cmd, sargs, thread_type);
+	else
+		ret = imap_thread_orderedsubject(cmd, sargs);
 	mail_search_args_unref(&sargs);
 	if (ret < 0) {
 		client_send_storage_error(cmd,
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-imap-client/imapc-client.h
--- a/src/lib-imap-client/imapc-client.h	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-imap-client/imapc-client.h	Mon Aug 20 11:09:42 2012 +0300
@@ -52,6 +52,7 @@
 	const char *master_user;
 	const char *username;
 	const char *password;
+	unsigned int max_idle_time;
 
 	const char *dns_client_socket_path;
 	const char *temp_path_prefix;
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-imap-client/imapc-connection.c
--- a/src/lib-imap-client/imapc-connection.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-imap-client/imapc-connection.c	Mon Aug 20 11:09:42 2012 +0300
@@ -24,8 +24,6 @@
 #define IMAPC_CONNECT_TIMEOUT_MSECS (1000*30)
 #define IMAPC_COMMAND_TIMEOUT_MSECS (1000*60*5)
 #define IMAPC_MAX_INLINE_LITERAL_SIZE (1024*32)
-/* IMAP protocol requires activity at least every 30 minutes */
-#define IMAPC_MAX_IDLE_MSECS (1000*60*29)
 
 enum imapc_input_state {
 	IMAPC_INPUT_STATE_NONE = 0,
@@ -1310,7 +1308,7 @@
 	conn->parser = imap_parser_create(conn->input, NULL, (size_t)-1);
 	conn->to = timeout_add(IMAPC_CONNECT_TIMEOUT_MSECS,
 			       imapc_connection_timeout, conn);
-	conn->to_output = timeout_add(IMAPC_MAX_IDLE_MSECS,
+	conn->to_output = timeout_add(conn->client->set.max_idle_time*1000,
 				      imapc_connection_reset_idle, conn);
 	if (conn->client->set.debug) {
 		i_debug("imapc(%s): Connecting to %s:%u", conn->name,
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-storage/index/imapc/imapc-settings.c
--- a/src/lib-storage/index/imapc/imapc-settings.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-settings.c	Mon Aug 20 11:09:42 2012 +0300
@@ -28,6 +28,8 @@
 	DEF(SET_STR, imapc_features),
 	DEF(SET_STR, imapc_rawlog_dir),
 	DEF(SET_STR, imapc_list_prefix),
+	DEF(SET_TIME, imapc_max_idle_time),
+
 	DEF(SET_STR, ssl_crypto_device),
 
 	SETTING_DEFINE_LIST_END
@@ -48,6 +50,8 @@
 	.imapc_features = "",
 	.imapc_rawlog_dir = "",
 	.imapc_list_prefix = "",
+	.imapc_max_idle_time = 60*29,
+
 	.ssl_crypto_device = ""
 };
 
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-storage/index/imapc/imapc-settings.h
--- a/src/lib-storage/index/imapc/imapc-settings.h	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-settings.h	Mon Aug 20 11:09:42 2012 +0300
@@ -23,6 +23,8 @@
 	const char *imapc_features;
 	const char *imapc_rawlog_dir;
 	const char *imapc_list_prefix;
+	unsigned int imapc_max_idle_time;
+
 	const char *ssl_crypto_device;
 
 	enum imapc_features parsed_features;
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Mon Aug 20 11:09:42 2012 +0300
@@ -228,6 +228,7 @@
 		*error_r = "missing imapc_password";
 		return -1;
 	}
+	set.max_idle_time = storage->set->imapc_max_idle_time;
 	set.dns_client_socket_path =
 		*_storage->user->set->base_dir == '\0' ? "" :
 		t_strconcat(_storage->user->set->base_dir, "/",
diff -r 9c69df65af7b -r 2fc74b72817b src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c	Mon Aug 20 10:54:04 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c	Mon Aug 20 11:09:42 2012 +0300
@@ -49,6 +49,7 @@
 	struct list_dir_context *dir;
 
 	unsigned int inbox_found:1;
+	unsigned int list_inbox_inbox:1;
 };


More information about the dovecot-cvs mailing list