bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-common.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "str.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "ostream.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-quote.h"
a8fe899601735459641edae975c0fa08be8482e2Timo Sirainen#include "mailbox-list-iter.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "mailbox-list-notify.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "mail-search.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "mail-search-build.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-commands.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-fetch.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-list.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-status.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#include "imap-notify.h"
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen#define IMAP_NOTIFY_WATCH_ADD_DELAY_MSECS 1000
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int imap_notify_list(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mailbox_info_flags flags)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen string_t *str = t_str_new(128);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen char ns_sep = mail_namespace_get_sep(notify_ns->ns);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append(str, "* LIST (");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_mailbox_flags2str(str, flags);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append(str, ") \"");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ns_sep == '\\')
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append_c(str, '\\');
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append_c(str, ns_sep);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append(str, "\" ");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen imap_append_astring(str, rec->vname);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (rec->old_vname != NULL) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append(str, " (\"OLDNAME\" (");
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen imap_append_astring(str, rec->old_vname);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen str_append(str, "))");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return client_send_line_next(notify_ns->ctx->client, str_c(str));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int imap_notify_status(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct client *client = notify_ns->ctx->client;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mailbox *box;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_status_items items;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_status_result result;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mail_error error;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int ret = 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&items);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen items.status |= STATUS_HIGHESTMODSEQ;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "NOTIFY STATUS");
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen STATUS_MESSAGES | STATUS_UNSEEN;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_EXPUNGES)) != 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen items.status |= STATUS_UNSEEN;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* if HIGHESTMODSEQ isn't being sent, don't send anything */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (items.status == 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* don't send anything */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else if (mailbox_get_status(box, items.status, &result.status) < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* hide permission errors from client. we don't want to leak
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen information about existence of mailboxes where user doesn't
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen have access to */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen (void)mailbox_get_last_error(box, &error);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (error != MAIL_ERROR_PERM)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = imap_status_send(client, rec->vname, &items, &result);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_free(&box);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_notify_next(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mailbox_info_flags mailbox_flags;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen int ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_CREATE) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen &mailbox_flags) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_flags = 0;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) <= 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_DELETE) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT)) < 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_RENAME) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen &mailbox_flags) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_flags = 0;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SUBSCRIBE) != 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen &mailbox_flags) < 0)
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen mailbox_flags = 0;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec,
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen mailbox_flags | MAILBOX_SUBSCRIBED)) < 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UNSUBSCRIBE) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen &mailbox_flags) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_flags = 0;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_UIDVALIDITY |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_APPENDS |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_EXPUNGES |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((ret = imap_notify_status(notify_ns, rec)) < 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return ret;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic bool
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_notify_match_event(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct imap_notify_mailboxes *notify_boxes,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum imap_notify_event wanted_events = notify_boxes->events;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mailbox *box;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen /* check for mailbox list events first */
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_CREATE |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_DELETE |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_RENAME)) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_UNSUBSCRIBE)) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen /* if this is an event for the selected mailbox, ignore it */
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen box = notify_ns->ctx->client->mailbox;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if (box != NULL && mailbox_equals(box, notify_ns->ns, rec->vname))
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return FALSE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen IMAP_NOTIFY_EVENT_FLAG_CHANGE)) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_EXPUNGES) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0)
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return TRUE;
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen }
e27db67b4549773e5015643e776bda9e7025719fTimo Sirainen return FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenbool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct imap_notify_mailboxes *notify_boxes,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const char *vname)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen struct mailbox *box;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const char *const *namep;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t name_len;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen char ns_sep;
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen bool ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen switch (notify_boxes->type) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen case IMAP_NOTIFY_TYPE_SUBSCRIBED:
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen box = mailbox_alloc(notify_ns->ns->list, vname, 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "NOTIFY is subscribed");
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen ret = mailbox_is_subscribed(box);
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen mailbox_free(&box);
98bd9a8b6d894c3648d0e2074a0d441e48425cfcTimo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen case IMAP_NOTIFY_TYPE_SUBTREE:
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ns_sep = mail_namespace_get_sep(notify_ns->ns);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach(&notify_boxes->names, namep) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen name_len = strlen(*namep);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (name_len == 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* everything under root. NOTIFY spec itself
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen doesn't define this, but we use it for
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen implementing "personal" */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (strncmp(*namep, vname, name_len) == 0 &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen (vname[name_len] == '\0' ||
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen vname[name_len] == ns_sep))
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen break;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen case IMAP_NOTIFY_TYPE_MAILBOX:
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach(&notify_boxes->names, namep) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (strcmp(*namep, vname) == 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen break;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic bool
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_notify_match(struct imap_notify_namespace *notify_ns,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct imap_notify_mailboxes *notify_boxes;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach(&notify_ns->mailboxes, notify_boxes) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (imap_notify_match_event(notify_ns, notify_boxes, rec) &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_notify_match_mailbox(notify_ns, notify_boxes, rec->vname))
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int imap_client_notify_ns(struct imap_notify_namespace *notify_ns)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct mailbox_list_notify_rec *rec;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int ret, ret2 = 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
1c1e591e42f6c3cdfeeed26164f5c85d85d01877Timo Sirainen if (notify_ns->notify == NULL)
1c1e591e42f6c3cdfeeed26164f5c85d85d01877Timo Sirainen return 0; /* notifications not supported in this namespace */
1c1e591e42f6c3cdfeeed26164f5c85d85d01877Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen while ((ret = mailbox_list_notify_next(notify_ns->notify, &rec)) > 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (imap_notify_match(notify_ns, rec)) T_BEGIN {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret2 = imap_notify_next(notify_ns, rec);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } T_END;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ret2 <= 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen break;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ret < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* failed to get some notifications */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret2;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_client_notify_selected(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_fetch_context *fetch_ctx = client->notify_ctx->fetch_ctx;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (!fetch_ctx->state.fetching)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((ret = imap_fetch_more_no_lock_update(fetch_ctx)) <= 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* finished the FETCH */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (imap_fetch_end(fetch_ctx) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int imap_client_notify_more(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_notify_namespace *notify_ns;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int ret = 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* send notifications for selected mailbox first. note that it may
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen leave the client's output stream in the middle of a FETCH reply. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (client->notify_ctx->fetch_ctx != NULL) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((ret = imap_client_notify_selected(client)) < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_ctx->fetch_ctx->state.failed = FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* send notifications for non-selected mailboxes */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach_modifiable(&client->notify_ctx->namespaces, notify_ns) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ret == 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen break;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (imap_client_notify_ns(notify_ns) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ret < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client_send_line(notify_ns->ctx->client,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen "* NO NOTIFY error, some events may have got lost");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenint imap_client_notify_newmails(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_fetch_context *fetch_ctx = client->notify_ctx->fetch_ctx;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mailbox_status status;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_search_args *search_args;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct mail_search_arg *arg;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(client->mailbox != NULL);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (fetch_ctx == NULL) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* FETCH notifications not enabled in this session */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (client->notify_ctx->notifying)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return imap_client_notify_more(client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_ctx->notifying = TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(!fetch_ctx->state.fetching);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_get_open_status(client->mailbox, STATUS_UIDNEXT, &status);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen search_args = mail_search_build_init();
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen arg = mail_search_build_add(search_args, SEARCH_UIDSET);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen p_array_init(&arg->value.seqset, search_args->pool, 1);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen seq_range_array_add_range(&arg->value.seqset,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_uidnext, status.uidnext-1);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_uidnext = status.uidnext;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_fetch_begin(fetch_ctx, client->mailbox, search_args);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_search_args_unref(&search_args);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return imap_client_notify_more(client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenvoid imap_client_notify_finished(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (client->notify_ctx != NULL)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_ctx->notifying = FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
ffe330e26377fe1f3661586b7edf6520e11f52daAki Tuomistatic void notify_callback(struct imap_notify_namespace *notify_ns)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen o_stream_cork(notify_ns->ctx->client->output);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_client_notify_ns(notify_ns);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen o_stream_uncork(notify_ns->ctx->client->output);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic enum mailbox_list_notify_event
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_events_to_notify(enum imap_notify_event events)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mailbox_list_notify_event ret = 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_APPENDS |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_EXPUNGES |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_CREATE |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_DELETE |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen MAILBOX_LIST_NOTIFY_RENAME;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen if ((events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen ret |= MAILBOX_LIST_NOTIFY_SUBSCRIBE |
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
24acd68c82dc137b88bb3ba3258b9d1f7ebcb44dTimo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void imap_notify_callback(struct mailbox *box, struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct client_command_context *cmd;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mailbox_sync_flags sync_flags = 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(client->command_queue_size == 0);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(box == client->mailbox);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* create a fake command to handle this */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cmd = client_command_alloc(client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cmd->tag = "*";
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen cmd->name = "NOTIFY-CALLBACK";
1c02804cdc5f1ad830fec081100e951bc67204b4Timo Sirainen client_command_init_finished(cmd);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (!client->notify_ctx->selected_immediate_expunges)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen sync_flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (cmd_sync(cmd, sync_flags, 0, NULL))
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_unreached();
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen (void)cmd_sync_delayed(client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void imap_notify_watch_selected_mailbox(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen i_assert(client->command_queue_size == 0);
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (client->mailbox == NULL) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* mailbox not selected */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (client->notify_ctx == NULL || !client->notify_ctx->selected_set) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* client doesn't want selected mailbox notifications */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_notify_changes(client->mailbox, imap_notify_callback, client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_ctx->watching_mailbox = TRUE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void imap_notify_watch_timeout(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen timeout_remove(&client->notify_ctx->to_watch);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_notify_watch_selected_mailbox(client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenvoid imap_client_notify_command_freed(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen struct imap_notify_context *ctx = client->notify_ctx;
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen if (ctx == NULL)
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen return;
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen if (client->command_queue_size > 0) {
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen /* don't add it until all commands are finished */
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen i_assert(ctx->to_watch == NULL);
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen return;
4693a58116ae794e43fa59f301b2f2f703c6f929Timo Sirainen }
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen /* add mailbox watch back after a small delay. if another command
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen is started this timeout is aborted. */
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen ctx->to_watch = timeout_add(IMAP_NOTIFY_WATCH_ADD_DELAY_MSECS,
906a651134bead2be605f2be6c47bd91a4cb94beTimo Sirainen imap_notify_watch_timeout, client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
0081ed0d90d302027ed4a53cb617c0179c246868Timo Sirainenvoid imap_client_notify_command_allocated(struct client *client)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
0081ed0d90d302027ed4a53cb617c0179c246868Timo Sirainen struct imap_notify_context *ctx = client->notify_ctx;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx == NULL)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* remove mailbox watcher before starting any commands */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->watching_mailbox) {
0081ed0d90d302027ed4a53cb617c0179c246868Timo Sirainen mailbox_notify_changes_stop(client->mailbox);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx->watching_mailbox = FALSE;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
d90a924480a061683786e459a2e1c1d0b6e4f1e4Josef 'Jeff' Sipek timeout_remove(&ctx->to_watch);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenint imap_notify_begin(struct imap_notify_context *ctx)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_notify_namespace *notify_ns;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen const struct imap_notify_mailboxes *notify_boxes;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enum mailbox_list_notify_event notify_events;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen int ret = -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen notify_events = 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach(&notify_ns->mailboxes, notify_boxes) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen notify_events |=
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_events_to_notify(notify_boxes->events);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mailbox_list_notify_init(notify_ns->ns->list, notify_events,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen &notify_ns->notify) < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* notifications not supported */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_list_notify_wait(notify_ns->notify,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen notify_callback, notify_ns);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* enable NOTIFY as long as even one namespace supports it,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ignore the rest */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return ret;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenvoid imap_notify_deinit(struct imap_notify_context **_ctx)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_notify_context *ctx = *_ctx;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_notify_namespace *notify_ns;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen *_ctx = NULL;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (notify_ns->notify != NULL)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_list_notify_deinit(&notify_ns->notify);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&ctx->to_watch);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->fetch_ctx != NULL)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_fetch_free(&ctx->fetch_ctx);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen pool_unref(&ctx->pool);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen
369847496787678ee18608754a97f0c2df80a36fTimo Sirainenvoid imap_notify_flush(struct imap_notify_context *ctx)
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen{
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen struct imap_notify_namespace *notify_ns;
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen if (notify_ns->notify != NULL)
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen mailbox_list_notify_flush(notify_ns->notify);
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen }
369847496787678ee18608754a97f0c2df80a36fTimo Sirainen}