dovecot-2.1: Implemented IMAP SPECIAL-USE extension.
dovecot at dovecot.org
dovecot at dovecot.org
Fri Dec 2 17:07:51 EET 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/32d1a903d42d
changeset: 13794:32d1a903d42d
user: Timo Sirainen <tss at iki.fi>
date: Fri Dec 02 17:05:31 2011 +0200
description:
Implemented IMAP SPECIAL-USE extension.
diffstat:
configure.in | 2 +-
src/imap/cmd-list.c | 22 ++++++++++--
src/lib-storage/mail-storage-settings.c | 56 +++++++++++++++++++++++++++++++-
src/lib-storage/mail-storage-settings.h | 1 +
src/lib-storage/mail-storage.c | 2 +-
src/lib-storage/mail-storage.h | 3 +
src/lib-storage/mailbox-list-iter.c | 51 ++++++++++++++++++++++-------
src/lib-storage/mailbox-list-private.h | 1 +
src/lib-storage/mailbox-list.h | 6 ++-
9 files changed, 121 insertions(+), 23 deletions(-)
diffs (truncated from 351 to 300 lines):
diff -r ee783a878120 -r 32d1a903d42d configure.in
--- a/configure.in Fri Dec 02 16:22:31 2011 +0200
+++ b/configure.in Fri Dec 02 17:05:31 2011 +0200
@@ -2671,7 +2671,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 UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS FUZZY"
+capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS FUZZY SPECIAL-USE"
AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", IMAP capabilities)
AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", IMAP capabilities advertised in banner)
diff -r ee783a878120 -r 32d1a903d42d src/imap/cmd-list.c
--- a/src/imap/cmd-list.c Fri Dec 02 16:22:31 2011 +0200
+++ b/src/imap/cmd-list.c Fri Dec 02 17:05:31 2011 +0200
@@ -37,7 +37,7 @@
static void
mailbox_flags2str(struct cmd_list_context *ctx, string_t *str,
- enum mailbox_info_flags flags)
+ const char *special_use, enum mailbox_info_flags flags)
{
unsigned int orig_len = str_len(str);
@@ -76,6 +76,11 @@
if ((flags & MAILBOX_UNMARKED) != 0)
str_append(str, "\\UnMarked ");
+ if ((ctx->list_flags & MAILBOX_LIST_ITER_RETURN_SPECIALUSE) != 0 &&
+ special_use != NULL) {
+ str_append(str, special_use);
+ str_append_c(str, ' ');
+ }
if (str_len(str) != orig_len)
str_truncate(str, str_len(str)-1);
}
@@ -150,6 +155,8 @@
list_flags |= MAILBOX_LIST_ITER_RETURN_SUBSCRIBED;
else if (strcasecmp(str, "CHILDREN") == 0)
list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN;
+ else if (strcasecmp(str, "SPECIAL-USE") == 0)
+ list_flags |= MAILBOX_LIST_ITER_RETURN_SPECIALUSE;
else if (strcasecmp(str, "STATUS") == 0 &&
imap_arg_get_list(&args[1], &list_args)) {
if (imap_status_parse_items(ctx->cmd, list_args,
@@ -262,6 +269,7 @@
list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
{
struct mail_namespace *const *listed;
+ const struct mailbox_settings *mailbox_set;
unsigned int len;
enum mailbox_info_flags flags;
const char *name;
@@ -330,7 +338,10 @@
str_printfa(str, "* %s (", ctx->lsub ? "LSUB" : "LIST");
if (ctx->lsub)
flags |= MAILBOX_NONEXISTENT;
- mailbox_flags2str(ctx, str, flags);
+ mailbox_set = (ctx->list_flags & MAILBOX_LIST_ITER_RETURN_SPECIALUSE) == 0 ? NULL :
+ mailbox_settings_find(ctx->cmd->client->user, name);
+ mailbox_flags2str(ctx, str, mailbox_set == NULL ? NULL :
+ mailbox_set->special_use, flags);
str_append(str, ") ");
list_reply_append_ns_sep_param(str, ns_sep);
str_append_c(str, ' ');
@@ -447,7 +458,7 @@
str_truncate(str, 0);
str_printfa(str, "* %s (", ctx->lsub ? "LSUB" : "LIST");
- mailbox_flags2str(ctx, str, flags);
+ mailbox_flags2str(ctx, str, info->special_use, flags);
str_append(str, ") ");
list_reply_append_ns_sep_param(str,
mail_namespace_get_sep(ctx->ns));
@@ -954,8 +965,9 @@
WORKAROUND_TB_LSUB_FLAGS) == 0)
ctx->list_flags |= MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
} else if (!ctx->used_listext) {
- /* non-extended LIST - return children flags always */
- ctx->list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN;
+ /* non-extended LIST: use default flags */
+ ctx->list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN |
+ MAILBOX_LIST_ITER_RETURN_SPECIALUSE;
}
ctx->list_flags |= MAILBOX_LIST_ITER_SHOW_EXISTING_PARENT;
diff -r ee783a878120 -r 32d1a903d42d src/lib-storage/mail-storage-settings.c
--- a/src/lib-storage/mail-storage-settings.c Fri Dec 02 16:22:31 2011 +0200
+++ b/src/lib-storage/mail-storage-settings.c Fri Dec 02 17:05:31 2011 +0200
@@ -150,6 +150,7 @@
static const struct setting_define mailbox_setting_defines[] = {
DEF(SET_STR, name),
{ SET_ENUM, "auto", offsetof(struct mailbox_settings, autocreate), NULL } ,
+ DEF(SET_STR, special_use),
SETTING_DEFINE_LIST_END
};
@@ -158,7 +159,8 @@
.name = "",
.autocreate = MAILBOX_SET_AUTO_NO":"
MAILBOX_SET_AUTO_CREATE":"
- MAILBOX_SET_AUTO_SUBSCRIBE
+ MAILBOX_SET_AUTO_SUBSCRIBE,
+ .special_use = ""
};
const struct setting_parser_info mailbox_setting_parser_info = {
@@ -460,7 +462,53 @@
return TRUE;
}
-static bool mailbox_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+static bool mailbox_special_use_exists(const char *name)
+{
+ if (name[0] != '\\')
+ return FALSE;
+ name++;
+
+ if (strcasecmp(name, "All") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Archive") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Drafts") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Flagged") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Junk") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Sent") == 0)
+ return TRUE;
+ if (strcasecmp(name, "Trash") == 0)
+ return TRUE;
+ return FALSE;
+}
+
+static bool
+mailbox_special_use_check(struct mailbox_settings *set, pool_t pool,
+ const char **error_r)
+{
+ const char *const *uses, *str;
+ unsigned int i;
+
+ uses = t_strsplit_spaces(set->special_use, " ");
+ for (i = 0; uses[i] != NULL; i++) {
+ if (!mailbox_special_use_exists(uses[i])) {
+ *error_r = t_strdup_printf(
+ "mailbox %s: unknown special_use: %s",
+ set->name, uses[i]);
+ return FALSE;
+ }
+ }
+ /* make sure there are no extra spaces */
+ str = t_strarray_join(uses, " ");
+ if (strcmp(str, set->special_use) != 0)
+ set->special_use = p_strdup(pool, str);
+ return TRUE;
+}
+
+static bool mailbox_settings_check(void *_set, pool_t pool,
const char **error_r)
{
struct mailbox_settings *set = _set;
@@ -470,6 +518,10 @@
set->name);
return FALSE;
}
+ if (*set->special_use != '\0') {
+ if (!mailbox_special_use_check(set, pool, error_r))
+ return FALSE;
+ }
return TRUE;
}
diff -r ee783a878120 -r 32d1a903d42d src/lib-storage/mail-storage-settings.h
--- a/src/lib-storage/mail-storage-settings.h Fri Dec 02 16:22:31 2011 +0200
+++ b/src/lib-storage/mail-storage-settings.h Fri Dec 02 17:05:31 2011 +0200
@@ -63,6 +63,7 @@
struct mailbox_settings {
const char *name;
const char *autocreate;
+ const char *special_use;
};
struct mail_user_settings {
diff -r ee783a878120 -r 32d1a903d42d src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c Fri Dec 02 16:22:31 2011 +0200
+++ b/src/lib-storage/mail-storage.c Fri Dec 02 17:05:31 2011 +0200
@@ -602,7 +602,7 @@
return TRUE;
}
-static struct mailbox_settings *
+const struct mailbox_settings *
mailbox_settings_find(struct mail_user *user, const char *vname)
{
struct mailbox_settings *const *box_set;
diff -r ee783a878120 -r 32d1a903d42d src/lib-storage/mail-storage.h
--- a/src/lib-storage/mail-storage.h Fri Dec 02 16:22:31 2011 +0200
+++ b/src/lib-storage/mail-storage.h Fri Dec 02 17:05:31 2011 +0200
@@ -429,6 +429,9 @@
/* Returns the storage's settings. */
const struct mail_storage_settings *
mailbox_get_settings(struct mailbox *box) ATTR_PURE;
+/* Returns the mailbox's settings, or NULL if there are none. */
+const struct mailbox_settings *
+mailbox_settings_find(struct mail_user *user, const char *vname);
/* Returns name of given mailbox */
const char *mailbox_get_name(const struct mailbox *box) ATTR_PURE;
diff -r ee783a878120 -r 32d1a903d42d src/lib-storage/mailbox-list-iter.c
--- a/src/lib-storage/mailbox-list-iter.c Fri Dec 02 16:22:31 2011 +0200
+++ b/src/lib-storage/mailbox-list-iter.c Fri Dec 02 17:05:31 2011 +0200
@@ -3,6 +3,7 @@
#include "lib.h"
#include "array.h"
#include "imap-match.h"
+#include "mail-storage.h"
#include "mailbox-tree.h"
#include "mailbox-list-private.h"
@@ -17,6 +18,7 @@
struct autocreate_box {
const char *name;
+ const struct mailbox_settings *set;
enum mailbox_info_flags flags;
bool child_listed;
};
@@ -103,6 +105,7 @@
array_append(&actx->box_sets, &box_sets[i], 1);
autobox = array_append_space(&actx->boxes);
autobox->name = box_sets[i]->name;
+ autobox->set = box_sets[i];
}
}
}
@@ -530,18 +533,41 @@
}
static const struct mailbox_info *
+mailbox_list_iter_next_call(struct mailbox_list_iterate_context *ctx)
+{
+ const struct mailbox_info *info;
+ const struct mailbox_settings *set;
+
+ info = ctx->list->v.iter_next(ctx);
+ if (info == NULL)
+ return NULL;
+
+ ctx->list->ns->flags |= NAMESPACE_FLAG_USABLE;
+ if ((ctx->list->flags & MAILBOX_LIST_ITER_RETURN_SPECIALUSE) != 0) {
+ set = mailbox_settings_find(ctx->list->ns->user, info->name);
+ if (set != NULL && *set->special_use != '\0') {
+ ctx->specialuse_info = *info;
+ ctx->specialuse_info.special_use =
+ *set->special_use == '\0' ? NULL :
+ set->special_use;
+ info = &ctx->specialuse_info;
+ }
+ }
+ return info;
+}
+
+static const struct mailbox_info *
autocreate_iter_next(struct mailbox_list_iterate_context *ctx)
{
struct mailbox_list_autocreate_iterate_context *actx =
ctx->autocreate_ctx;
const struct mailbox_info *info;
- const struct autocreate_box *autoboxes;
+ const struct autocreate_box *autoboxes, *autobox;
unsigned int count;
if (actx->idx == 0) {
- info = ctx->list->v.iter_next(ctx);
+ info = mailbox_list_iter_next_call(ctx);
if (info != NULL) {
- ctx->list->ns->flags |= NAMESPACE_FLAG_USABLE;
actx->new_info = *info;
return autocreate_iter_existing(ctx);
}
@@ -550,8 +576,13 @@
/* list missing mailboxes */
autoboxes = array_get(&actx->boxes, &count);
while (actx->idx < count) {
- if (autocreate_iter_autobox(ctx, &autoboxes[actx->idx++]))
+ autobox = &autoboxes[actx->idx++];
+ if (autocreate_iter_autobox(ctx, autobox)) {
+ actx->new_info.special_use =
+ *autobox->set->special_use == '\0' ? NULL :
+ autobox->set->special_use;
return &actx->new_info;
+ }
}
i_assert(array_count(&actx->boxes) == array_count(&actx->box_sets));
return NULL;
@@ -560,16 +591,10 @@
const struct mailbox_info *
mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
{
More information about the dovecot-cvs
mailing list