imap-notify.c revision 1c02804cdc5f1ad830fec081100e951bc67204b4
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "imap-common.h"
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen#include "str.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ostream.h"
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen#include "imap-quote.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "mailbox-list-iter.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mailbox-list-notify.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search.h"
abf015c9682f0f723db87a7c97bc284ef814818fTimo Sirainen#include "mail-search-build.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "imap-commands.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "imap-fetch.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "imap-list.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "imap-status.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "imap-notify.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define IMAP_NOTIFY_WATCH_ADD_DELAY_MSECS 1000
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic int imap_notify_list(struct imap_notify_namespace *notify_ns,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mailbox_list_notify_rec *rec,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mailbox_info_flags flags)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen string_t *str = t_str_new(128);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen char ns_sep = mail_namespace_get_sep(notify_ns->ns);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append(str, "* LIST (");
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen imap_mailbox_flags2str(str, flags);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen str_append(str, ") \"");
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen if (ns_sep == '\\')
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen str_append_c(str, '\\');
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen str_append_c(str, ns_sep);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen str_append(str, "\" ");
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen imap_append_astring(str, rec->vname);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (rec->old_vname != NULL) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen str_append(str, " (\"OLDNAME\" (");
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen imap_append_astring(str, rec->old_vname);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen str_append(str, "))");
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen }
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen return client_send_line_next(notify_ns->ctx->client, str_c(str));
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic int imap_notify_status(struct imap_notify_namespace *notify_ns,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct mailbox_list_notify_rec *rec)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct client *client = notify_ns->ctx->client;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct mailbox *box;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct imap_status_items items;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct imap_status_result result;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen enum mail_error error;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen int ret = 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen i_zero(&items);
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen items.status |= STATUS_HIGHESTMODSEQ;
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, rec->vname, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_set_reason(box, "NOTIFY STATUS");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen items.status |= STATUS_UIDVALIDITY | STATUS_UIDNEXT |
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen STATUS_MESSAGES | STATUS_UNSEEN;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_APPENDS |
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen MAILBOX_LIST_NOTIFY_EXPUNGES)) != 0)
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen items.status |= STATUS_UIDNEXT | STATUS_MESSAGES | STATUS_UNSEEN;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SEEN_CHANGES) != 0)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen items.status |= STATUS_UNSEEN;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* if HIGHESTMODSEQ isn't being sent, don't send anything */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (items.status == 0) {
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen /* don't send anything */
d1bf4ae66b8bf3b9e28df1823d6d4adda2b923b6Timo Sirainen } else if (mailbox_get_status(box, items.status, &result.status) < 0) {
d1bf4ae66b8bf3b9e28df1823d6d4adda2b923b6Timo Sirainen /* hide permission errors from client. we don't want to leak
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen information about existence of mailboxes where user doesn't
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen have access to */
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen (void)mailbox_get_last_error(box, &error);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (error != MAIL_ERROR_PERM)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen ret = -1;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen } else {
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen ret = imap_status_send(client, rec->vname, &items, &result);
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen }
baf97389e203e105b97a8183b2893740691f8c63Timo Sirainen mailbox_free(&box);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen return ret;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen}
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
e438c85a6b0f77889e25913bbbba808d6078282dStephan Boschstatic int
c977ee6ce06cbc0b4668fde1ec34f2f5e1773684Timo Sirainenimap_notify_next(struct imap_notify_namespace *notify_ns,
c977ee6ce06cbc0b4668fde1ec34f2f5e1773684Timo Sirainen const struct mailbox_list_notify_rec *rec)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen enum mailbox_info_flags mailbox_flags;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen int ret;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_CREATE) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen &mailbox_flags) < 0)
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen mailbox_flags = 0;
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) <= 0)
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen return ret;
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_DELETE) != 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, MAILBOX_NONEXISTENT)) < 0)
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen return ret;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_RENAME) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen &mailbox_flags) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_flags = 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return ret;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_SUBSCRIBE) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen &mailbox_flags) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_flags = 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec,
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen mailbox_flags | MAILBOX_SUBSCRIBED)) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UNSUBSCRIBE) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (mailbox_list_mailbox(notify_ns->ns->list, rec->storage_name,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen &mailbox_flags) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_flags = 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((ret = imap_notify_list(notify_ns, rec, mailbox_flags)) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return ret;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_UIDVALIDITY |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen MAILBOX_LIST_NOTIFY_APPENDS |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen MAILBOX_LIST_NOTIFY_EXPUNGES |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
096e109f9f332bc758ca5e22ec64337379c5f231Timo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0) {
096e109f9f332bc758ca5e22ec64337379c5f231Timo Sirainen if ((ret = imap_notify_status(notify_ns, rec)) < 0)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic bool
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenimap_notify_match_event(struct imap_notify_namespace *notify_ns,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen const struct imap_notify_mailboxes *notify_boxes,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen const struct mailbox_list_notify_rec *rec)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen enum imap_notify_event wanted_events = notify_boxes->events;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen struct mailbox *box;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* check for mailbox list events first */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_CREATE |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen MAILBOX_LIST_NOTIFY_DELETE |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen MAILBOX_LIST_NOTIFY_RENAME)) != 0)
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen return TRUE;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen }
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SUBSCRIBE |
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen MAILBOX_LIST_NOTIFY_UNSUBSCRIBE)) != 0)
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen return TRUE;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen }
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* if this is an event for the selected mailbox, ignore it */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen box = notify_ns->ctx->client->mailbox;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (box != NULL && mailbox_equals(box, notify_ns->ns, rec->vname))
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return FALSE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE |
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen IMAP_NOTIFY_EVENT_FLAG_CHANGE)) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_UIDVALIDITY) != 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return TRUE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_APPENDS) != 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return TRUE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen if ((rec->events & MAILBOX_LIST_NOTIFY_EXPUNGES) != 0)
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen return TRUE;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen }
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen if ((rec->events & (MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
79fff45046397ba48c8693d5f37a1fd93096987fTimo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0)
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen return TRUE;
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen }
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen return FALSE;
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen}
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainenbool imap_notify_match_mailbox(struct imap_notify_namespace *notify_ns,
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen const struct imap_notify_mailboxes *notify_boxes,
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen const char *vname)
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen{
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen struct mailbox *box;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen const char *const *namep;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen size_t name_len;
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen char ns_sep;
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen bool ret;
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen switch (notify_boxes->type) {
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen case IMAP_NOTIFY_TYPE_SUBSCRIBED:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen box = mailbox_alloc(notify_ns->ns->list, vname, 0);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_set_reason(box, "NOTIFY is subscribed");
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ret = mailbox_is_subscribed(box);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_free(&box);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return ret;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case IMAP_NOTIFY_TYPE_SUBTREE:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ns_sep = mail_namespace_get_sep(notify_ns->ns);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_foreach(&notify_boxes->names, namep) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen name_len = strlen(*namep);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (name_len == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* everything under root. NOTIFY spec itself
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doesn't define this, but we use it for
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen implementing "personal" */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strncmp(*namep, vname, name_len) == 0 &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (vname[name_len] == '\0' ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen vname[name_len] == ns_sep))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case IMAP_NOTIFY_TYPE_MAILBOX:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_foreach(&notify_boxes->names, namep) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(*namep, vname) == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenimap_notify_match(struct imap_notify_namespace *notify_ns,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mailbox_list_notify_rec *rec)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen{
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen const struct imap_notify_mailboxes *notify_boxes;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_foreach(&notify_ns->mailboxes, notify_boxes) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (imap_notify_match_event(notify_ns, notify_boxes, rec) &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen imap_notify_match_mailbox(notify_ns, notify_boxes, rec->vname))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainenstatic int imap_client_notify_ns(struct imap_notify_namespace *notify_ns)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mailbox_list_notify_rec *rec;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen int ret, ret2 = 1;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (notify_ns->notify == NULL)
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen return 0; /* notifications not supported in this namespace */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen while ((ret = mailbox_list_notify_next(notify_ns->notify, &rec)) > 0) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (imap_notify_match(notify_ns, rec)) T_BEGIN {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen ret2 = imap_notify_next(notify_ns, rec);
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen } T_END;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (ret2 <= 0)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen break;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen }
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (ret < 0) {
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen /* failed to get some notifications */
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen return -1;
e30b9e07f9657c35ca09ac36d57d60cbe2ebbc66Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret2;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen}
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenimap_client_notify_selected(struct client *client)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct imap_fetch_context *fetch_ctx = client->notify_ctx->fetch_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!fetch_ctx->state.fetching)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch if ((ret = imap_fetch_more_no_lock_update(fetch_ctx)) <= 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen /* finished the FETCH */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (imap_fetch_end(fetch_ctx) < 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return -1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return 1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
baf97389e203e105b97a8183b2893740691f8c63Timo Sirainen
baf97389e203e105b97a8183b2893740691f8c63Timo Sirainenstatic int imap_client_notify_more(struct client *client)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen{
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen struct imap_notify_namespace *notify_ns;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch int ret = 1;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch /* send notifications for selected mailbox first. note that it may
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch leave the client's output stream in the middle of a FETCH reply. */
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch if (client->notify_ctx->fetch_ctx != NULL) {
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen if ((ret = imap_client_notify_selected(client)) < 0) {
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen client->notify_ctx->fetch_ctx->state.failed = FALSE;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen ret = -1;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen /* send notifications for non-selected mailboxes */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen array_foreach_modifiable(&client->notify_ctx->namespaces, notify_ns) {
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen if (ret == 0)
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen break;
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen if (imap_client_notify_ns(notify_ns) < 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ret = -1;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen if (ret < 0) {
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen client_send_line(notify_ns->ctx->client,
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen "* NO NOTIFY error, some events may have got lost");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint imap_client_notify_newmails(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct imap_fetch_context *fetch_ctx = client->notify_ctx->fetch_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox_status status;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_search_args *search_args;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct mail_search_arg *arg;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_assert(client->mailbox != NULL);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (fetch_ctx == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* FETCH notifications not enabled in this session */
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen return 1;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->notify_ctx->notifying)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return imap_client_notify_more(client);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch client->notify_ctx->notifying = TRUE;
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen i_assert(!fetch_ctx->state.fetching);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen mailbox_get_open_status(client->mailbox, STATUS_UIDNEXT, &status);
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen search_args = mail_search_build_init();
11120acd01d43973cd504952d691a2ae1c546ee2Timo Sirainen arg = mail_search_build_add(search_args, SEARCH_UIDSET);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen p_array_init(&arg->value.seqset, search_args->pool, 1);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen seq_range_array_add_range(&arg->value.seqset,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen client->notify_uidnext, status.uidnext-1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->notify_uidnext = status.uidnext;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen imap_fetch_begin(fetch_ctx, client->mailbox, search_args);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mail_search_args_unref(&search_args);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return imap_client_notify_more(client);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenvoid imap_client_notify_finished(struct client *client)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (client->notify_ctx != NULL)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen client->notify_ctx->notifying = FALSE;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstatic void notify_callback(struct imap_notify_namespace *notify_ns)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen o_stream_cork(notify_ns->ctx->client->output);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen imap_client_notify_ns(notify_ns);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen o_stream_uncork(notify_ns->ctx->client->output);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic enum mailbox_list_notify_event
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainenimap_events_to_notify(enum imap_notify_event events)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mailbox_list_notify_event ret = 0;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_APPENDS |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_EXPUNGES |
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_SEEN_CHANGES |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_LIST_NOTIFY_UIDVALIDITY;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_CREATE |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_LIST_NOTIFY_DELETE |
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen MAILBOX_LIST_NOTIFY_RENAME;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen ret |= MAILBOX_LIST_NOTIFY_SUBSCRIBE |
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen MAILBOX_LIST_NOTIFY_UNSUBSCRIBE;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic void imap_notify_callback(struct mailbox *box, struct client *client)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen struct client_command_context *cmd;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen enum mailbox_sync_flags sync_flags = 0;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(client->command_queue_size == 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(box == client->mailbox);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* create a fake command to handle this */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen cmd = client_command_alloc(client);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen cmd->tag = "*";
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen cmd->name = "NOTIFY-CALLBACK";
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen client_command_init_finished(cmd);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (!client->notify_ctx->selected_immediate_expunges)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen sync_flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES;
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen if (cmd_sync(cmd, sync_flags, 0, NULL))
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_unreached();
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen (void)cmd_sync_delayed(client);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainenstatic void imap_notify_watch_selected_mailbox(struct client *client)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_assert(client->command_queue_size == 0);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (client->mailbox == NULL) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* mailbox not selected */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (client->notify_ctx == NULL || !client->notify_ctx->selected_set) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* client doesn't want selected mailbox notifications */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mailbox_notify_changes(client->mailbox, imap_notify_callback, client);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen client->notify_ctx->watching_mailbox = TRUE;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenstatic void imap_notify_watch_timeout(struct client *client)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen timeout_remove(&client->notify_ctx->to_watch);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen imap_notify_watch_selected_mailbox(client);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenvoid imap_client_notify_command_freed(struct client *client)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen struct imap_notify_context *ctx = client->notify_ctx;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (ctx == NULL)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (client->command_queue_size > 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* don't add it until all commands are finished */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen i_assert(ctx->to_watch == NULL);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen return;
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen }
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen /* add mailbox watch back after a small delay. if another command
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen is started this timeout is aborted. */
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen ctx->to_watch = timeout_add(IMAP_NOTIFY_WATCH_ADD_DELAY_MSECS,
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch imap_notify_watch_timeout, client);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen}
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainenvoid imap_client_notify_command_allocated(struct client *client)
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen{
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen struct imap_notify_context *ctx = client->notify_ctx;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen if (ctx == NULL)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen return;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen /* remove mailbox watcher before starting any commands */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (ctx->watching_mailbox) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mailbox_notify_changes_stop(client->mailbox);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen ctx->watching_mailbox = FALSE;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen timeout_remove(&ctx->to_watch);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen}
c73ede1a6685975eb21eecf2fb5af79854867f9bTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenint imap_notify_begin(struct imap_notify_context *ctx)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct imap_notify_namespace *notify_ns;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen const struct imap_notify_mailboxes *notify_boxes;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen enum mailbox_list_notify_event notify_events;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen int ret = -1;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen notify_events = 0;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen array_foreach(&notify_ns->mailboxes, notify_boxes) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen notify_events |=
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen imap_events_to_notify(notify_boxes->events);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen }
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (mailbox_list_notify_init(notify_ns->ns->list, notify_events,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen &notify_ns->notify) < 0) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen /* notifications not supported */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen ret = 0;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mailbox_list_notify_wait(notify_ns->notify,
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen notify_callback, notify_ns);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* enable NOTIFY as long as even one namespace supports it,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ignore the rest */
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return ret;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenvoid imap_notify_deinit(struct imap_notify_context **_ctx)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct imap_notify_context *ctx = *_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct imap_notify_namespace *notify_ns;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen *_ctx = NULL;
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (notify_ns->notify != NULL)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen mailbox_list_notify_deinit(&notify_ns->notify);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen timeout_remove(&ctx->to_watch);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (ctx->fetch_ctx != NULL)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen imap_fetch_free(&ctx->fetch_ctx);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen pool_unref(&ctx->pool);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenvoid imap_notify_flush(struct imap_notify_context *ctx)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen struct imap_notify_namespace *notify_ns;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen array_foreach_modifiable(&ctx->namespaces, notify_ns) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (notify_ns->notify != NULL)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen mailbox_list_notify_flush(notify_ns->notify);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen}
216cd45a5f47c9bd46fe67c1b3bd6b1a42f6e39cTimo Sirainen