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