imap-notify.c revision 4693a58116ae794e43fa59f301b2f2f703c6f929
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenstatic int imap_notify_list(struct imap_notify_namespace *notify_ns,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen char ns_sep = mail_namespace_get_sep(notify_ns->ns);
92f5ea24e989266539e97c6fe59ede0565aec6fdTimo Sirainen return client_send_line_next(notify_ns->ctx->client, str_c(str));
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic int imap_notify_status(struct imap_notify_namespace *notify_ns,
47daf6e810a4c2dd52640092092900dbcb12f265Timo Sirainen struct client *client = notify_ns->ctx->client;
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
cc23ad7b8ab96d93d5ab5139c431fcdd8d9e1d72Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen /* if HIGHESTMODSEQ isn't being sent, don't send anything */
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen /* don't send anything */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen } else if (mailbox_get_status(box, items.status, &result.status) < 0) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* hide permission errors from client. we don't want to leak
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen information about existence of mailboxes where user doesn't
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen have access to */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen ret = imap_status_send(client, rec->vname, &items, &result);
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainenimap_notify_next(struct imap_notify_namespace *notify_ns,
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_CREATE) != 0) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) <= 0)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_DELETE) != 0) {
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT)) < 0)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_RENAME) != 0) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SUBSCRIBE) != 0) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UNSUBSCRIBE) != 0) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_UIDVALIDITY |
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if ((ret = imap_notify_status(notify_ns, rec)) < 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenimap_notify_match_event(struct imap_notify_namespace *notify_ns,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const struct imap_notify_mailboxes *notify_boxes,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen enum imap_notify_event wanted_events = notify_boxes->events;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* check for mailbox list events first */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_CREATE |
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
92f9871ac981201fe0a47f6c909f790cce14b240Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* if this is an event for the selected mailbox, ignore it */
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen if (box != NULL && mailbox_equals(box, notify_ns->ns, rec->vname))
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0)
387f9e3b4120273ad0213206a0e9cc2dc0e62ccaTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_EXPUNGES) != 0)
387f9e3b4120273ad0213206a0e9cc2dc0e62ccaTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
632018810af689442569cbb0139c55868923ccfeTimo Sirainenbool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen const struct imap_notify_mailboxes *notify_boxes,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen const char *const *namep;
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, vname, 0);
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen mailbox_set_reason(box, "NOTIFY is subscribed");
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen ns_sep = mail_namespace_get_sep(notify_ns->ns);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* everything under root. NOTIFY spec itself
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen doesn't define this, but we use it for
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen implementing "personal" */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenimap_notify_match(struct imap_notify_namespace *notify_ns,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen const struct imap_notify_mailboxes *notify_boxes;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen array_foreach(¬ify_ns->mailboxes, notify_boxes) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (imap_notify_match_event(notify_ns, notify_boxes, rec) &&
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen imap_notify_match_mailbox(notify_ns, notify_boxes, rec->vname))
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic int imap_client_notify_ns(struct imap_notify_namespace *notify_ns)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return 0; /* notifications not supported in this namespace */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen while ((ret = mailbox_list_notify_next(notify_ns->notify, &rec)) > 0) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (imap_notify_match(notify_ns, rec)) T_BEGIN {
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen /* failed to get some notifications */
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainenimap_client_notify_selected(struct client *client)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct imap_fetch_context *fetch_ctx = client->notify_ctx->fetch_ctx;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if ((ret = imap_fetch_more_no_lock_update(fetch_ctx)) <= 0)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* finished the FETCH */
if (ret == 0)
if (ret < 0) {
return ret;
static enum mailbox_list_notify_event
return ret;
i_unreached();
client);
if (!notify_hook_registered) {
notify_events = 0;
ret = 0;
return ret;