imap-notify.c revision e27db67b4549773e5015643e776bda9e7025719f
/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
#include "imap-common.h"
#include "str.h"
#include "ostream.h"
#include "imap-quote.h"
#include "mailbox-list-iter.h"
#include "mailbox-list-notify.h"
#include "mail-search.h"
#include "mail-search-build.h"
#include "imap-commands.h"
#include "imap-fetch.h"
#include "imap-list.h"
#include "imap-status.h"
#include "imap-notify.h"
#define IMAP_NOTIFY_WATCH_ADD_DELAY_MSECS 1000
static bool notify_hook_registered;
const struct mailbox_list_notify_rec *rec,
enum mailbox_info_flags flags)
{
if (ns_sep == '\\')
}
}
const struct mailbox_list_notify_rec *rec)
{
struct imap_status_items items;
struct imap_status_result result;
enum mail_error error;
int ret = 1;
}
MAILBOX_LIST_NOTIFY_EXPUNGES)) != 0)
/* if HIGHESTMODSEQ isn't being sent, don't send anything */
}
/* don't send anything */
/* hide permission errors from client. we don't want to leak
information about existence of mailboxes where user doesn't
have access to */
if (error != MAIL_ERROR_PERM)
ret = -1;
} else {
}
mailbox_free(&box);
return ret;
}
static int
const struct mailbox_list_notify_rec *rec)
{
int ret;
&mailbox_flags) < 0)
mailbox_flags = 0;
return ret;
}
return ret;
}
&mailbox_flags) < 0)
mailbox_flags = 0;
return ret;
}
&mailbox_flags) < 0)
mailbox_flags = 0;
mailbox_flags | MAILBOX_SUBSCRIBED)) < 0)
return ret;
}
&mailbox_flags) < 0)
mailbox_flags = 0;
return ret;
}
MAILBOX_LIST_NOTIFY_MODSEQ_CHANGES)) != 0) {
return ret;
}
return 1;
}
static bool
const struct imap_notify_mailboxes *notify_boxes,
const struct mailbox_list_notify_rec *rec)
{
/* check for mailbox list events first */
if ((wanted_events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
MAILBOX_LIST_NOTIFY_RENAME)) != 0)
return TRUE;
}
if ((wanted_events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
MAILBOX_LIST_NOTIFY_UNSUBSCRIBE)) != 0)
return TRUE;
}
/* if this is an event for the selected mailbox, ignore it */
return FALSE;
if ((wanted_events & (IMAP_NOTIFY_EVENT_MESSAGE_NEW |
IMAP_NOTIFY_EVENT_FLAG_CHANGE)) != 0) {
return TRUE;
}
if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
return TRUE;
}
if ((wanted_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
return TRUE;
}
if ((wanted_events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
return TRUE;
}
return FALSE;
}
const struct imap_notify_mailboxes *notify_boxes,
const char *vname)
{
const char *const *namep;
unsigned int name_len;
char ns_sep;
bool ret;
switch (notify_boxes->type) {
mailbox_free(&box);
return ret;
case IMAP_NOTIFY_TYPE_SUBTREE:
if (name_len == 0) {
/* everything under root. NOTIFY spec itself
doesn't define this, but we use it for
implementing "personal" */
return TRUE;
}
return TRUE;
}
break;
case IMAP_NOTIFY_TYPE_MAILBOX:
return TRUE;
}
break;
}
return FALSE;
}
static bool
const struct mailbox_list_notify_rec *rec)
{
const struct imap_notify_mailboxes *notify_boxes;
return TRUE;
}
return FALSE;
}
{
const struct mailbox_list_notify_rec *rec;
} T_END;
if (ret2 <= 0)
break;
}
if (ret < 0) {
/* failed to get some notifications */
return -1;
}
return ret2;
}
static int
{
int ret;
return 1;
return ret;
/* finished the FETCH */
if (imap_fetch_end(fetch_ctx) < 0)
return -1;
return 1;
}
{
struct imap_notify_namespace *notify_ns;
int ret = 1;
/* send notifications for selected mailbox first. note that it may
leave the client's output stream in the middle of a FETCH reply. */
ret = -1;
}
}
/* send notifications for non-selected mailboxes */
if (ret == 0)
break;
if (imap_client_notify_ns(notify_ns) < 0)
ret = -1;
}
if (ret < 0) {
"* NO NOTIFY error, some events may have got lost");
}
return ret;
}
{
struct mailbox_status status;
struct mail_search_args *search_args;
struct mail_search_arg *arg;
/* FETCH notifications not enabled in this session */
return 1;
}
return imap_client_notify_more(client);
return imap_client_notify_more(client);
}
{
}
static void notify_callback(void *context)
{
}
static enum mailbox_list_notify_event
{
enum mailbox_list_notify_event ret = 0;
if ((events & IMAP_NOTIFY_EVENT_MESSAGE_NEW) != 0) {
}
if ((events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) != 0) {
}
if ((events & IMAP_NOTIFY_EVENT_FLAG_CHANGE) != 0) {
}
if ((events & IMAP_NOTIFY_EVENT_MAILBOX_NAME) != 0) {
}
if ((events & IMAP_NOTIFY_EVENT_SUBSCRIPTION_CHANGE) != 0) {
}
return ret;
}
{
struct client_command_context *cmd;
enum mailbox_sync_flags sync_flags = 0;
/* create a fake command to handle this */
i_unreached();
(void)cmd_sync_delayed(client);
}
{
if (client->command_queue_size > 0) {
/* don't add it until all commands are finished */
return;
}
/* mailbox not selected */
return;
}
/* client doesn't want selected mailbox notifications */
return;
}
}
{
}
{
}
{
return;
/* remove mailbox watcher before starting any commands */
if (ctx->watching_mailbox) {
}
}
{
return;
/* add mailbox watched back after a small delay */
else {
}
}
{
struct imap_notify_namespace *notify_ns;
const struct imap_notify_mailboxes *notify_boxes;
int ret = -1;
if (!notify_hook_registered) {
}
notify_events = 0;
}
/* notifications not supported */
} else {
ret = 0;
}
}
/* enable NOTIFY as long as even one namespace supports it,
ignore the rest */
return ret;
}
{
struct imap_notify_namespace *notify_ns;
}
}