dovecot-2.2: imap: Implemented NOTIFY extension.
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 13 15:23:46 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/f9d0ea98157f
changeset: 14899:f9d0ea98157f
user: Timo Sirainen <tss at iki.fi>
date: Mon Aug 13 15:23:32 2012 +0300
description:
imap: Implemented NOTIFY extension.
Requires mailbox_list_index=yes to work (and to show up in capabilities).
SubscriptionChange event is still unimplemented.
diffstat:
src/imap/Makefile.am | 5 +
src/imap/cmd-cancelupdate.c | 4 +-
src/imap/cmd-fetch.c | 23 +-
src/imap/cmd-idle.c | 2 +-
src/imap/cmd-list.c | 29 +-
src/imap/cmd-notify.c | 542 ++++++++++++++++++++++++++++++++++++++++++++
src/imap/cmd-search.c | 5 +-
src/imap/cmd-select.c | 9 +-
src/imap/cmd-sort.c | 10 +-
src/imap/imap-client.c | 105 +++++---
src/imap/imap-client.h | 13 +-
src/imap/imap-commands.c | 1 +
src/imap/imap-commands.h | 1 +
src/imap/imap-fetch.c | 97 +++++--
src/imap/imap-fetch.h | 12 +-
src/imap/imap-list.c | 35 ++
src/imap/imap-list.h | 7 +
src/imap/imap-notify.c | 518 ++++++++++++++++++++++++++++++++++++++++++
src/imap/imap-notify.h | 71 +++++
src/imap/imap-search.c | 70 +++++-
src/imap/imap-search.h | 5 +
src/imap/imap-sync.c | 298 +++++++++++++++++------
src/imap/main.c | 2 +-
23 files changed, 1665 insertions(+), 199 deletions(-)
diffs (truncated from 2672 to 300 lines):
diff -r a16d77a075bb -r f9d0ea98157f src/imap/Makefile.am
--- a/src/imap/Makefile.am Mon Aug 13 15:20:33 2012 +0300
+++ b/src/imap/Makefile.am Mon Aug 13 15:23:32 2012 +0300
@@ -43,6 +43,7 @@
cmd-lsub.c \
cmd-namespace.c \
cmd-noop.c \
+ cmd-notify.c \
cmd-rename.c \
cmd-search.c \
cmd-select.c \
@@ -64,6 +65,8 @@
imap-expunge.c \
imap-fetch.c \
imap-fetch-body.c \
+ imap-list.c \
+ imap-notify.c \
imap-search.c \
imap-search-args.c \
imap-settings.c \
@@ -79,6 +82,8 @@
imap-common.h \
imap-expunge.h \
imap-fetch.h \
+ imap-list.h \
+ imap-notify.h \
imap-search.h \
imap-search-args.h \
imap-settings.h \
diff -r a16d77a075bb -r f9d0ea98157f src/imap/cmd-cancelupdate.c
--- a/src/imap/cmd-cancelupdate.c Mon Aug 13 15:20:33 2012 +0300
+++ b/src/imap/cmd-cancelupdate.c Mon Aug 13 15:23:32 2012 +0300
@@ -1,6 +1,7 @@
/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
#include "imap-common.h"
+#include "imap-search.h"
#include "imap-commands.h"
static bool client_search_update_cancel(struct client *client, const char *tag)
@@ -12,8 +13,7 @@
if (update == NULL)
return FALSE;
- i_free(update->tag);
- mailbox_search_result_free(&update->result);
+ imap_search_update_free(update);
array_delete(&client->search_updates, idx, 1);
return TRUE;
}
diff -r a16d77a075bb -r f9d0ea98157f src/imap/cmd-fetch.c
--- a/src/imap/cmd-fetch.c Mon Aug 13 15:20:33 2012 +0300
+++ b/src/imap/cmd-fetch.c Mon Aug 13 15:23:32 2012 +0300
@@ -103,6 +103,7 @@
static bool
fetch_parse_modifier(struct imap_fetch_context *ctx,
struct client_command_context *cmd,
+ struct mail_search_args *search_args,
const char *name, const struct imap_arg **args,
bool *send_vanished)
{
@@ -117,7 +118,7 @@
return FALSE;
}
*args += 1;
- imap_fetch_add_changed_since(ctx, modseq);
+ imap_fetch_add_changed_since(ctx, search_args, modseq);
return TRUE;
}
if (strcmp(name, "VANISHED") == 0 && cmd->uid) {
@@ -137,6 +138,7 @@
static bool
fetch_parse_modifiers(struct imap_fetch_context *ctx,
struct client_command_context *cmd,
+ struct mail_search_args *search_args,
const struct imap_arg *args, bool *send_vanished_r)
{
const char *name;
@@ -150,13 +152,14 @@
return FALSE;
}
args++;
- if (!fetch_parse_modifier(ctx, cmd, t_str_ucase(name),
+ if (!fetch_parse_modifier(ctx, cmd, search_args,
+ t_str_ucase(name),
&args, send_vanished_r))
return FALSE;
}
if (*send_vanished_r &&
- (ctx->search_args->args->next == NULL ||
- ctx->search_args->args->next->type != SEARCH_MODSEQ)) {
+ (search_args->args->next == NULL ||
+ search_args->args->next->type != SEARCH_MODSEQ)) {
client_send_command_error(cmd,
"VANISHED used without CHANGEDSINCE");
return FALSE;
@@ -250,23 +253,27 @@
return ret < 0;
ctx = imap_fetch_alloc(client, cmd->pool);
- ctx->search_args = search_args;
if (!fetch_parse_args(ctx, cmd, &args[1], &next_arg) ||
(imap_arg_get_list(next_arg, &list_arg) &&
- !fetch_parse_modifiers(ctx, cmd, list_arg, &send_vanished))) {
+ !fetch_parse_modifiers(ctx, cmd, search_args, list_arg,
+ &send_vanished))) {
imap_fetch_free(&ctx);
+ mail_search_args_unref(&search_args);
return TRUE;
}
if (send_vanished) {
memset(&qresync_args, 0, sizeof(qresync_args));
if (imap_fetch_send_vanished(client, client->mailbox,
- search_args, &qresync_args) < 0)
+ search_args, &qresync_args) < 0) {
+ mail_search_args_unref(&search_args);
return cmd_fetch_finish(ctx, cmd);
+ }
}
- imap_fetch_begin_once(ctx, client->mailbox);
+ imap_fetch_begin(ctx, client->mailbox, search_args);
+ mail_search_args_unref(&search_args);
if (imap_fetch_more(ctx, cmd) == 0) {
/* unfinished */
diff -r a16d77a075bb -r f9d0ea98157f src/imap/cmd-idle.c
--- a/src/imap/cmd-idle.c Mon Aug 13 15:20:33 2012 +0300
+++ b/src/imap/cmd-idle.c Mon Aug 13 15:23:32 2012 +0300
@@ -115,7 +115,7 @@
static void keepalive_timeout(struct cmd_idle_context *ctx)
{
- if (ctx->client->output_lock != NULL) {
+ if (ctx->client->output_locked) {
/* it's busy sending output */
return;
}
diff -r a16d77a075bb -r f9d0ea98157f src/imap/cmd-list.c
--- a/src/imap/cmd-list.c Mon Aug 13 15:20:33 2012 +0300
+++ b/src/imap/cmd-list.c Mon Aug 13 15:23:32 2012 +0300
@@ -9,6 +9,7 @@
#include "imap-match.h"
#include "imap-status.h"
#include "imap-commands.h"
+#include "imap-list.h"
#include "mail-namespace.h"
struct cmd_list_context {
@@ -49,40 +50,22 @@
if ((ctx->list_flags & MAILBOX_LIST_ITER_RETURN_CHILDREN) == 0)
flags &= ~(MAILBOX_CHILDREN|MAILBOX_NOCHILDREN);
- if ((flags & MAILBOX_SUBSCRIBED) != 0 &&
- (ctx->list_flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) != 0)
- str_append(str, "\\Subscribed ");
+ if ((ctx->list_flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) == 0)
+ flags &= ~MAILBOX_SUBSCRIBED;
if ((flags & MAILBOX_CHILD_SUBSCRIBED) != 0 &&
(flags & MAILBOX_SUBSCRIBED) == 0 && !ctx->used_listext) {
/* LSUB uses \Noselect for this */
flags |= MAILBOX_NOSELECT;
}
-
- if ((flags & MAILBOX_NOSELECT) != 0)
- str_append(str, "\\Noselect ");
- if ((flags & MAILBOX_NONEXISTENT) != 0)
- str_append(str, "\\NonExistent ");
-
- if ((flags & MAILBOX_CHILDREN) != 0)
- str_append(str, "\\HasChildren ");
- else if ((flags & MAILBOX_NOINFERIORS) != 0)
- str_append(str, "\\NoInferiors ");
- else if ((flags & MAILBOX_NOCHILDREN) != 0)
- str_append(str, "\\HasNoChildren ");
-
- if ((flags & MAILBOX_MARKED) != 0)
- str_append(str, "\\Marked ");
- if ((flags & MAILBOX_UNMARKED) != 0)
- str_append(str, "\\UnMarked ");
+ imap_mailbox_flags2str(str, flags);
if ((ctx->list_flags & MAILBOX_LIST_ITER_RETURN_SPECIALUSE) != 0 &&
special_use != NULL) {
+ if (str_len(str) != orig_len)
+ str_append_c(str, ' ');
str_append(str, special_use);
- str_append_c(str, ' ');
}
- if (str_len(str) != orig_len)
- str_truncate(str, str_len(str)-1);
}
static void
diff -r a16d77a075bb -r f9d0ea98157f src/imap/cmd-notify.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/imap/cmd-notify.c Mon Aug 13 15:23:32 2012 +0300
@@ -0,0 +1,542 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "imap-common.h"
+#include "str.h"
+#include "imap-quote.h"
+#include "imap-commands.h"
+#include "imap-fetch.h"
+#include "imap-list.h"
+#include "imap-status.h"
+#include "imap-notify.h"
+
+#define IMAP_NOTIFY_MAX_NAMES_PER_NS 100
+
+static const char *imap_notify_event_names[] = {
+ "MessageNew", "MessageExpunge", "FlagChange", "AnnotationChange",
+ "MailboxName", "SubscriptionChange", "MailboxMetadataChange",
+ "ServerMetadataChange"
+};
+
+static int
+cmd_notify_parse_event(const struct imap_arg *arg,
+ enum imap_notify_event *event_r)
+{
+ const char *str;
+ unsigned int i;
+
+ if (!imap_arg_get_atom(arg, &str))
+ return -1;
+
+ for (i = 0; i < N_ELEMENTS(imap_notify_event_names); i++) {
+ if (strcasecmp(str, imap_notify_event_names[i]) == 0) {
+ *event_r = (enum imap_notify_event)(1 << i);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+cmd_notify_parse_fetch(struct imap_notify_context *ctx,
+ const struct imap_arg *list)
+{
+ return imap_fetch_att_list_parse(ctx->client, ctx->pool, list,
+ &ctx->fetch_ctx, &ctx->error);
+}
+
+static int
+cmd_notify_set_selected(struct imap_notify_context *ctx,
+ const struct imap_arg *events)
+{
+#define EV_NEW_OR_EXPUNGE \
+ (IMAP_NOTIFY_EVENT_MESSAGE_NEW | IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE)
+ const struct imap_arg *list, *fetch_att_list;
+ const char *str;
+ enum imap_notify_event event;
+
+ if (imap_arg_get_atom(events, &str) &&
+ strcasecmp(str, "NONE") == 0) {
+ /* no events for selected mailbox. this is also the default
+ when NOTIFY command doesn't specify it explicitly */
+ return 0;
+ }
+
+ if (!imap_arg_get_list(events, &list))
+ return -1;
+
+ for (; list->type != IMAP_ARG_EOL; list++) {
+ if (cmd_notify_parse_event(list, &event) < 0)
+ return -1;
+ ctx->selected_events |= event;
+ ctx->global_used_events |= event;
+
+ if (event == IMAP_NOTIFY_EVENT_MESSAGE_NEW &&
+ imap_arg_get_list(&list[1], &fetch_att_list)) {
+ /* MessageNew: list of fetch-att */
+ if (cmd_notify_parse_fetch(ctx, fetch_att_list) < 0)
+ return -1;
+ list++;
+ }
+ }
+
+ /* if MessageNew or MessageExpunge is specified, both of them must */
+ if ((ctx->selected_events & EV_NEW_OR_EXPUNGE) != 0 &&
+ (ctx->selected_events & EV_NEW_OR_EXPUNGE) != EV_NEW_OR_EXPUNGE) {
+ ctx->error = "MessageNew and MessageExpunge must be together";
+ return -1;
+ }
+
+ /* if FlagChange or AnnotationChange is specified,
+ MessageNew and MessageExpunge must also be specified */
+ if ((ctx->selected_events &
+ (IMAP_NOTIFY_EVENT_FLAG_CHANGE |
+ IMAP_NOTIFY_EVENT_ANNOTATION_CHANGE)) != 0 &&
+ (ctx->selected_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) == 0) {
+ ctx->error = "FlagChange requires MessageNew and MessageExpunge";
+ return -1;
+ }
+ return 0;
+}
More information about the dovecot-cvs
mailing list