dovecot-2.1: imapc: Added imapc_features=rfc822.size setting to ...

dovecot at dovecot.org dovecot at dovecot.org
Fri Mar 30 05:20:20 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/6a8b78450202
changeset: 14367:6a8b78450202
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Mar 30 05:20:08 2012 +0300
description:
imapc: Added imapc_features=rfc822.size setting to use RFC822.size for physical sizes.

diffstat:

 src/lib-storage/index/imapc/imapc-mail-fetch.c |  18 ++++++++
 src/lib-storage/index/imapc/imapc-mail.c       |  53 ++++++++++++++++++-------
 src/lib-storage/index/imapc/imapc-settings.c   |  41 ++++++++++++++++++++
 src/lib-storage/index/imapc/imapc-settings.h   |   9 ++++
 src/lib-storage/index/imapc/imapc-storage.h    |   6 ++
 5 files changed, 112 insertions(+), 15 deletions(-)

diffs (264 lines):

diff -r 87cd04f35f82 -r 6a8b78450202 src/lib-storage/index/imapc/imapc-mail-fetch.c
--- a/src/lib-storage/index/imapc/imapc-mail-fetch.c	Fri Mar 30 05:11:09 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c	Fri Mar 30 05:20:08 2012 +0300
@@ -95,6 +95,8 @@
 	str_printfa(str, "UID FETCH %u (", _mail->uid);
 	if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0)
 		str_append(str, "INTERNALDATE ");
+	if ((fields & MAIL_FETCH_PHYSICAL_SIZE) != 0)
+		str_append(str, "RFC822.SIZE ");
 	if ((fields & MAIL_FETCH_GUID) != 0) {
 		str_append(str, mbox->guid_fetch_field_name);
 		str_append_c(str, ' ');
@@ -157,6 +159,10 @@
 	if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0 &&
 	    data->received_date == (time_t)-1)
 		fields |= MAIL_FETCH_RECEIVED_DATE;
+	if ((data->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE) != 0 &&
+	    data->physical_size == (uoff_t)-1 &&
+	    IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
+		fields |= MAIL_FETCH_PHYSICAL_SIZE;
 	if ((data->wanted_fields & MAIL_FETCH_GUID) != 0 &&
 	    data->guid == NULL && mbox->guid_fetch_field_name != NULL)
 		fields |= MAIL_FETCH_GUID;
@@ -181,6 +187,11 @@
 			return FALSE;
 		fields &= ~MAIL_FETCH_RECEIVED_DATE;
 	}
+	if ((fields & MAIL_FETCH_PHYSICAL_SIZE) != 0) {
+		if (imail->imail.data.physical_size == (uoff_t)-1)
+			return FALSE;
+		fields &= ~MAIL_FETCH_PHYSICAL_SIZE;
+	}
 	if ((fields & MAIL_FETCH_GUID) != 0) {
 		if (imail->imail.data.guid == NULL)
 			return FALSE;
@@ -357,6 +368,7 @@
 		(struct imapc_mailbox *)mail->imail.mail.mail.box;
 	const char *key, *value;
 	unsigned int i;
+	uoff_t size;
 	time_t t;
 	int tz;
 	bool match = FALSE;
@@ -377,6 +389,12 @@
 			    imap_parse_datetime(value, &t, &tz))
 				mail->imail.data.received_date = t;
 			match = TRUE;
+		} else if (strcasecmp(key, "RFC822.SIZE") == 0) {
+			if (imap_arg_get_atom(&args[i+1], &value) &&
+			    str_to_uoff(value, &size) == 0 &&
+			    IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
+				mail->imail.data.physical_size = size;
+			match = TRUE;
 		} else if (strcasecmp(key, "X-GM-MSGID") == 0 ||
 			   strcasecmp(key, "X-GUID") == 0) {
 			if (imap_arg_get_astring(&args[i+1], &value)) {
diff -r 87cd04f35f82 -r 6a8b78450202 src/lib-storage/index/imapc/imapc-mail.c
--- a/src/lib-storage/index/imapc/imapc-mail.c	Fri Mar 30 05:11:09 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-mail.c	Fri Mar 30 05:20:08 2012 +0300
@@ -107,29 +107,50 @@
 
 static int imapc_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
 {
+	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	struct istream *input;
 	uoff_t old_offset;
 	int ret;
 
-	if (data->physical_size == (uoff_t)-1)
+	if (data->physical_size == (uoff_t)-1) {
 		(void)index_mail_get_physical_size(_mail, size_r);
-	if (data->physical_size == (uoff_t)-1) {
-		old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
-		if (mail_get_stream(_mail, NULL, NULL, &input) < 0)
+		if (data->physical_size != (uoff_t)-1) {
+			*size_r = data->physical_size;
+			return 0;
+		}
+	}
+
+	if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE) &&
+	    data->stream == NULL) {
+		/* trust RFC822.SIZE to be correct */
+		if (imapc_mail_fetch(_mail, MAIL_FETCH_PHYSICAL_SIZE) < 0)
 			return -1;
-		i_stream_seek(data->stream, old_offset);
+		if (data->physical_size == (uoff_t)-1) {
+			if (imapc_mail_failed(_mail, "RFC822.SIZE") < 0)
+				return -1;
+			/* assume that the server never returns RFC822.SIZE
+			   for this mail (see BODY[] failure handling) */
+			data->physical_size = 0;
+		}
+		*size_r = data->physical_size;
+		return 0;
+	}
 
-		ret = i_stream_get_size(data->stream, TRUE,
-					&data->physical_size);
-		if (ret <= 0) {
-			i_assert(ret != 0);
-			mail_storage_set_critical(_mail->box->storage,
-				"imapc: stat(%s) failed: %m",
-				i_stream_get_name(data->stream));
-			return -1;
-		}
+	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
+	if (mail_get_stream(_mail, NULL, NULL, &input) < 0)
+		return -1;
+	i_stream_seek(data->stream, old_offset);
+
+	ret = i_stream_get_size(data->stream, TRUE,
+				&data->physical_size);
+	if (ret <= 0) {
+		i_assert(ret != 0);
+		mail_storage_set_critical(_mail->box->storage,
+					  "imapc: stat(%s) failed: %m",
+					  i_stream_get_name(data->stream));
+		return -1;
 	}
 	*size_r = data->physical_size;
 	return 0;
@@ -200,6 +221,7 @@
 static void index_mail_update_access_parts(struct index_mail *mail)
 {
 	struct mail *_mail = &mail->mail.mail;
+	struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box;
 	struct index_mail_data *data = &mail->data;
 	struct mailbox_header_lookup_ctx *header_ctx;
 	time_t date;
@@ -208,7 +230,8 @@
 	if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0)
 		(void)index_mail_get_received_date(_mail, &date);
 	if ((data->wanted_fields & MAIL_FETCH_PHYSICAL_SIZE) != 0) {
-		if (index_mail_get_physical_size(_mail, &size) < 0)
+		if (index_mail_get_physical_size(_mail, &size) < 0 &&
+		    !IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_RFC822_SIZE))
 			data->access_part |= READ_HDR | READ_BODY;
 	}
 
diff -r 87cd04f35f82 -r 6a8b78450202 src/lib-storage/index/imapc/imapc-settings.c
--- a/src/lib-storage/index/imapc/imapc-settings.c	Fri Mar 30 05:11:09 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-settings.c	Fri Mar 30 05:20:08 2012 +0300
@@ -25,6 +25,7 @@
 	DEF(SET_STR, imapc_ssl_ca_dir),
 	DEF(SET_BOOL, imapc_ssl_verify),
 
+	DEF(SET_STR, imapc_features),
 	DEF(SET_STR, imapc_rawlog_dir),
 	DEF(SET_STR, ssl_crypto_device),
 
@@ -43,6 +44,7 @@
 	.imapc_ssl_ca_dir = "",
 	.imapc_ssl_verify = TRUE,
 
+	.imapc_features = "",
 	.imapc_rawlog_dir = "",
 	.ssl_crypto_device = ""
 };
@@ -67,6 +69,43 @@
 }
 
 /* <settings checks> */
+struct imapc_feature_list {
+	const char *name;
+	enum imapc_features num;
+};
+
+static const struct imapc_feature_list imapc_feature_list[] = {
+	{ "rfc822.size", IMAPC_FEATURE_RFC822_SIZE },
+	{ NULL, 0 }
+};
+
+static int
+imapc_settings_parse_features(struct imapc_settings *set,
+			      const char **error_r)
+{
+        enum imapc_features features = 0;
+        const struct imapc_feature_list *list;
+	const char *const *str;
+
+        str = t_strsplit_spaces(set->imapc_features, " ,");
+	for (; *str != NULL; str++) {
+		list = imapc_feature_list;
+		for (; list->name != NULL; list++) {
+			if (strcasecmp(*str, list->name) == 0) {
+				features |= list->num;
+				break;
+			}
+		}
+		if (list->name == NULL) {
+			*error_r = t_strdup_printf("imapc_features: "
+				"Unknown feature: %s", *str);
+			return -1;
+		}
+	}
+	set->parsed_features = features;
+	return 0;
+}
+
 static bool imapc_settings_check(void *_set, pool_t pool ATTR_UNUSED,
 				 const char **error_r)
 {
@@ -85,5 +124,7 @@
 		return FALSE;
 	}
 #endif
+	if (imapc_settings_parse_features(set, error_r) < 0)
+		return FALSE;
 	return TRUE;
 }
diff -r 87cd04f35f82 -r 6a8b78450202 src/lib-storage/index/imapc/imapc-settings.h
--- a/src/lib-storage/index/imapc/imapc-settings.h	Fri Mar 30 05:11:09 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-settings.h	Fri Mar 30 05:20:08 2012 +0300
@@ -1,6 +1,12 @@
 #ifndef IMAPC_SETTINGS_H
 #define IMAPC_SETTINGS_H
 
+/* <settings checks> */
+enum imapc_features {
+	IMAPC_FEATURE_RFC822_SIZE	= 0x01
+};
+/* </settings checks> */
+
 struct imapc_settings {
 	const char *imapc_host;
 	unsigned int imapc_port;
@@ -13,8 +19,11 @@
 	const char *imapc_ssl_ca_dir;
 	bool imapc_ssl_verify;
 
+	const char *imapc_features;
 	const char *imapc_rawlog_dir;
 	const char *ssl_crypto_device;
+
+	enum imapc_features parsed_features;
 };
 
 const struct setting_parser_info *imapc_get_setting_parser_info(void);
diff -r 87cd04f35f82 -r 6a8b78450202 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Fri Mar 30 05:11:09 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Fri Mar 30 05:20:08 2012 +0300
@@ -2,6 +2,7 @@
 #define IMAPC_STORAGE_H
 
 #include "index-storage.h"
+#include "imapc-settings.h"
 
 #define IMAPC_STORAGE_NAME "imapc"
 #define IMAPC_INDEX_PREFIX "dovecot.index"
@@ -28,6 +29,11 @@
 	imapc_mailbox_callback_t *callback;
 };
 
+#define IMAPC_HAS_FEATURE(mstorage, feature) \
+	(((mstorage)->set->parsed_features & feature) != 0)
+#define IMAPC_BOX_HAS_FEATURE(mbox, feature) \
+	(((mbox)->storage->set->parsed_features & feature) != 0)
+
 struct imapc_storage {
 	struct mail_storage storage;
 	const struct imapc_settings *set;


More information about the dovecot-cvs mailing list