dovecot-2.2: lib-imap-storage: Created new METADATA API.

dovecot at dovecot.org dovecot at dovecot.org
Sat Nov 15 00:28:57 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/a350812e07bf
changeset: 18094:a350812e07bf
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Nov 15 02:27:27 2014 +0200
description:
lib-imap-storage: Created new METADATA API.

diffstat:

 dovecot-config.in.in                 |    2 +-
 src/imap/Makefile.am                 |    2 -
 src/imap/cmd-getmetadata.c           |  147 +++++++++-------
 src/imap/cmd-setmetadata.c           |  140 +++++++++------
 src/imap/imap-metadata.c             |   85 ---------
 src/imap/imap-metadata.h             |   13 -
 src/lib-imap-storage/Makefile.am     |    6 +-
 src/lib-imap-storage/imap-metadata.c |  307 +++++++++++++++++++++++++++++++++++
 src/lib-imap-storage/imap-metadata.h |   57 ++++++
 9 files changed, 531 insertions(+), 228 deletions(-)

diffs (truncated from 1068 to 300 lines):

diff -r 372de41933c0 -r a350812e07bf dovecot-config.in.in
--- a/dovecot-config.in.in	Sat Nov 15 02:22:56 2014 +0200
+++ b/dovecot-config.in.in	Sat Nov 15 02:27:27 2014 +0200
@@ -23,7 +23,7 @@
 LIBDOVECOT_INCLUDE="-I$(incdir) -I$(incdir)/src/lib -I$(incdir)/src/lib-dict -I$(incdir)/src/lib-dns -I$(incdir)/src/lib-http -I$(incdir)/src/lib-mail -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-fs -I$(incdir)/src/lib-charset -I$(incdir)/src/lib-auth -I$(incdir)/src/lib-master -I$(incdir)/src/lib-ssl-iostream -I$(incdir)/src/lib-compression -I$(incdir)/src/lib-settings -I$(incdir)/src/lib-test"
 LIBDOVECOT_LDA_INCLUDE="-I$(incdir)/src/lib-lda -I$(incdir)/src/lda"
 LIBDOVECOT_DOVEADM_INCLUDE="-I$(incdir)/src/doveadm"
-LIBDOVECOT_STORAGE_INCLUDE="-I$(incdir)/src/lib-index -I$(incdir)/src/lib-storage -I$(incdir)/src/lib-storage/list -I$(incdir)/src/lib-storage/index -I$(incdir)/src/lib-storage/index/raw -I$(incdir)/src/plugins/quota"
+LIBDOVECOT_STORAGE_INCLUDE="-I$(incdir)/src/lib-index -I$(incdir)/src/lib-storage -I$(incdir)/src/lib-storage/list -I$(incdir)/src/lib-storage/index -I$(incdir)/src/lib-storage/index/raw -I$(incdir)/src/lib-imap-storage -I$(incdir)/src/plugins/quota"
 LIBDOVECOT_DSYNC_INCLUDE="-I$(incdir)/src/doveadm/dsync"
 LIBDOVECOT_LOGIN_INCLUDE="-I$(incdir)/src/login-common"
 LIBDOVECOT_IMAP_INCLUDE="-I$(incdir)/src/imap"
diff -r 372de41933c0 -r a350812e07bf src/imap/Makefile.am
--- a/src/imap/Makefile.am	Sat Nov 15 02:22:56 2014 +0200
+++ b/src/imap/Makefile.am	Sat Nov 15 02:27:27 2014 +0200
@@ -72,7 +72,6 @@
 	imap-fetch.c \
 	imap-fetch-body.c \
 	imap-list.c \
-	imap-metadata.c \
 	imap-notify.c \
 	imap-search.c \
 	imap-search-args.c \
@@ -90,7 +89,6 @@
 	imap-expunge.h \
 	imap-fetch.h \
 	imap-list.h \
-	imap-metadata.h \
 	imap-notify.h \
 	imap-search.h \
 	imap-search-args.h \
diff -r 372de41933c0 -r a350812e07bf src/imap/cmd-getmetadata.c
--- a/src/imap/cmd-getmetadata.c	Sat Nov 15 02:22:56 2014 +0200
+++ b/src/imap/cmd-getmetadata.c	Sat Nov 15 02:27:27 2014 +0200
@@ -13,7 +13,7 @@
 	struct client_command_context *cmd;
 
 	struct mailbox *box;
-	struct mailbox_transaction_context *trans;
+	struct imap_metadata_transaction *trans;
 	struct mailbox_list_iterate_context *list_iter;
 
 	ARRAY_TYPE(const_string) entries;
@@ -24,16 +24,16 @@
 	struct istream *cur_stream;
 	uoff_t cur_stream_offset, cur_stream_size;
 
-	struct mailbox_attribute_iter *iter;
+	struct imap_metadata_iter *iter;
 	string_t *iter_entry_prefix;
 
-	const char *key_prefix;
 	unsigned int entry_idx;
 	bool first_entry_sent;
 	bool failed;
 };
 
-static bool cmd_getmetadata_iter_next(struct imap_getmetadata_context *ctx);
+static bool
+cmd_getmetadata_mailbox_iter_next(struct imap_getmetadata_context *ctx);
 
 static bool
 cmd_getmetadata_parse_options(struct imap_getmetadata_context *ctx,
@@ -81,7 +81,7 @@
 imap_metadata_parse_entry_names(struct imap_getmetadata_context *ctx,
 				const struct imap_arg *entries)
 {
-	const char *value;
+	const char *value, *error;
 
 	p_array_init(&ctx->entries, ctx->cmd->pool, 4);
 	for (; !IMAP_ARG_IS_EOL(entries); entries++) {
@@ -89,8 +89,10 @@
 			client_send_command_error(ctx->cmd, "Entry isn't astring");
 			return FALSE;
 		}
-		if (!imap_metadata_verify_entry_name(ctx->cmd, value))
+		if (!imap_metadata_verify_entry_name(value, &error)) {
+			client_send_command_error(ctx->cmd, error);
 			return FALSE;
+		}
 
 		/* names are case-insensitive so we'll always lowercase them */
 		value = p_strdup(ctx->cmd->pool, t_str_lcase(value));
@@ -110,9 +112,14 @@
 
 		ctx->first_entry_sent = TRUE;
 		str_append(str, "* METADATA ");
-		if (imap_utf8_to_utf7(mailbox_get_vname(ctx->box), mailbox_mutf7) < 0)
-			i_unreached();
-		imap_append_astring(str, str_c(mailbox_mutf7));
+		if (ctx->box == NULL) {
+			/* server metadata reply */
+			str_append(str, "\"\"");
+		} else {
+			if (imap_utf8_to_utf7(mailbox_get_vname(ctx->box), mailbox_mutf7) < 0)
+				i_unreached();
+			imap_append_astring(str, str_c(mailbox_mutf7));
+		}
 		str_append(str, " (");
 
 		/* nothing can be sent until untagged METADATA is finished */
@@ -140,33 +147,22 @@
 static void cmd_getmetadata_send_entry(struct imap_getmetadata_context *ctx,
 				       const char *entry, bool require_reply)
 {
-	enum mail_attribute_type type;
+	struct client *client = ctx->cmd->client;
 	struct mail_attribute_value value;
+	const char *error_string;
 	enum mail_error error;
 	uoff_t value_len;
-	const char *key;
 	string_t *str;
 
-	imap_metadata_entry2key(entry, ctx->key_prefix, &type, &key);
-	if (ctx->key_prefix == NULL &&
-	    strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT,
-		    strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT)) == 0) {
-		/* skip over dovecot's internal attributes. (if key_prefix
-		   isn't NULL, we're getting server metadata, which is handled
-		   inside the private metadata.) */
-		if (require_reply)
-			cmd_getmetadata_send_nil_reply(ctx, entry);
-		return;
-	}
-
-	if (mailbox_attribute_get_stream(ctx->trans, type, key, &value) < 0) {
-		(void)mailbox_get_last_error(ctx->box, &error);
+	if (imap_metadata_get_stream(ctx->trans, entry, &value) < 0) {
+		error_string = imap_metadata_transaction_get_last_error(
+			ctx->trans, &error);
 		if (error != MAIL_ERROR_NOTFOUND && error != MAIL_ERROR_PERM) {
-			client_send_untagged_storage_error(ctx->cmd->client,
-				mailbox_get_storage(ctx->box));
+			client_send_line(client, t_strconcat("* NO ", error_string, NULL));
 			ctx->failed = TRUE;
 		}
 	}
+
 	if (value.value != NULL)
 		value_len = strlen(value.value);
 	else if (value.value_stream != NULL) {
@@ -198,10 +194,10 @@
 	str = metadata_add_entry(ctx, entry);
 	if (value.value != NULL) {
 		str_printfa(str, " {%"PRIuUOFF_T"}\r\n%s", value_len, value.value);
-		o_stream_send(ctx->cmd->client->output, str_data(str), str_len(str));
+		o_stream_nsend(client->output, str_data(str), str_len(str));
 	} else {
 		str_printfa(str, " ~{%"PRIuUOFF_T"}\r\n", value_len);
-		o_stream_send(ctx->cmd->client->output, str_data(str), str_len(str));
+		o_stream_nsend(client->output, str_data(str), str_len(str));
 
 		ctx->cur_stream_offset = 0;
 		ctx->cur_stream_size = value_len;
@@ -245,35 +241,39 @@
 	return FALSE;
 }
 
-static int cmd_getmetadata_send_entry_tree(struct imap_getmetadata_context *ctx,
+static int
+cmd_getmetadata_send_entry_tree(struct imap_getmetadata_context *ctx,
 					   const char *entry)
 {
-	const char *key;
-	enum mail_attribute_type type;
+	struct client *client = ctx->cmd->client;
 
-	if (o_stream_get_buffer_used_size(ctx->cmd->client->output) >=
+	if (o_stream_get_buffer_used_size(client->output) >=
 	    CLIENT_OUTPUT_OPTIMAL_SIZE) {
-		if (o_stream_flush(ctx->cmd->client->output) <= 0) {
-			o_stream_set_flush_pending(ctx->cmd->client->output, TRUE);
+		if (o_stream_flush(client->output) <= 0) {
+			o_stream_set_flush_pending(client->output, TRUE);
 			return 0;
 		}
 	}
 
 	if (ctx->iter != NULL) {
+		const char *subentry;
+
 		/* DEPTH iteration */
 		do {
-			key = mailbox_attribute_iter_next(ctx->iter);
-			if (key == NULL) {
+			subentry = imap_metadata_iter_next(ctx->iter);
+			if (subentry == NULL) {
 				/* iteration finished, get to the next entry */
-				if (mailbox_attribute_iter_deinit(&ctx->iter) < 0) {
-					client_send_untagged_storage_error(ctx->cmd->client,
-						mailbox_get_storage(ctx->box));
+				if (imap_metadata_iter_deinit(&ctx->iter) < 0) {
+					enum mail_error error;
+					client_send_line(client, t_strconcat("* NO ",
+						imap_metadata_transaction_get_last_error(ctx->trans, &error),
+						NULL));
 					ctx->failed = TRUE;
 				}
 				return -1;
 			}
-		} while (ctx->depth == 1 && strchr(key, '/') != NULL);
-		entry = t_strconcat(str_c(ctx->iter_entry_prefix), key, NULL);
+		} while (ctx->depth == 1 && strchr(subentry, '/') != NULL);
+		entry = t_strconcat(str_c(ctx->iter_entry_prefix), subentry, NULL);
 	}
 	cmd_getmetadata_send_entry(ctx, entry, ctx->iter == NULL);
 
@@ -295,21 +295,19 @@
 		str_append(ctx->iter_entry_prefix, entry);
 		str_append_c(ctx->iter_entry_prefix, '/');
 
-		imap_metadata_entry2key(entry, ctx->key_prefix, &type, &key);
-		ctx->iter = mailbox_attribute_iter_init(ctx->box, type,
-			key[0] == '\0' ? "" : t_strconcat(key, "/", NULL));
+		ctx->iter = imap_metadata_iter_init(ctx->trans, entry);
 		return 1;
 	}
 }
 
-static void cmd_getmetadata_mailbox_deinit(struct imap_getmetadata_context *ctx)
+static void cmd_getmetadata_iter_deinit(struct imap_getmetadata_context *ctx)
 {
 	if (ctx->iter != NULL)
-		(void)mailbox_attribute_iter_deinit(&ctx->iter);
-	if (ctx->box != NULL) {
-		(void)mailbox_transaction_commit(&ctx->trans);
+		(void)imap_metadata_iter_deinit(&ctx->iter);
+	if (ctx->trans != NULL)
+		(void)imap_metadata_transaction_commit(&ctx->trans, NULL, NULL);
+	if (ctx->box != NULL)
 		mailbox_free(&ctx->box);
-	}
 	ctx->first_entry_sent = FALSE;
 	ctx->entry_idx = 0;
 }
@@ -318,7 +316,7 @@
 {
 	struct client_command_context *cmd = ctx->cmd;
 
-	cmd_getmetadata_mailbox_deinit(ctx);
+	cmd_getmetadata_iter_deinit(ctx);
 	cmd->client->output_cmd_lock = NULL;
 
 	if (ctx->list_iter != NULL &&
@@ -366,33 +364,46 @@
 	if (ctx->first_entry_sent)
 		o_stream_nsend_str(cmd->client->output, ")\r\n");
 
-	cmd_getmetadata_mailbox_deinit(ctx);
+	cmd_getmetadata_iter_deinit(ctx);
 	if (ctx->list_iter != NULL)
-		return cmd_getmetadata_iter_next(ctx);
+		return cmd_getmetadata_mailbox_iter_next(ctx);
 	cmd_getmetadata_deinit(ctx);
 	return TRUE;
 }
 
-static int
-cmd_getmetadata_try_mailbox(struct imap_getmetadata_context *ctx,
-			    struct mail_namespace *ns, const char *mailbox)
+static bool
+cmd_getmetadata_start(struct imap_getmetadata_context *ctx)
 {
 	struct client_command_context *cmd = ctx->cmd;
 
-	ctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
-	if (mailbox_open(ctx->box) < 0)
-		return -1;
-	ctx->trans = mailbox_transaction_begin(ctx->box, 0);
-
 	if (ctx->depth > 0)
 		ctx->iter_entry_prefix = str_new(cmd->pool, 128);
 
 	if (!cmd_getmetadata_continue(cmd)) {
 		cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 		cmd->func = cmd_getmetadata_continue;
-		return 0;
+		return FALSE;
 	}
-	return 1;
+	return TRUE;
+}
+
+static bool
+cmd_getmetadata_server(struct imap_getmetadata_context *ctx)
+{
+	ctx->trans = imap_metadata_transaction_begin_server(ctx->cmd->client->user);
+	return cmd_getmetadata_start(ctx);
+}
+
+static int
+cmd_getmetadata_try_mailbox(struct imap_getmetadata_context *ctx,
+			    struct mail_namespace *ns, const char *mailbox)
+{
+	ctx->box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
+	if (mailbox_open(ctx->box) < 0)
+		return -1;
+


More information about the dovecot-cvs mailing list