cmd-notify.c revision 5bf4e28d6d2c25c54ee201943ac5398a74481360
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstatic const char *imap_notify_event_names[] = {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn "MessageNew", "MessageExpunge", "FlagChange", "AnnotationChange",
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn "MailboxName", "SubscriptionChange", "MailboxMetadataChange",
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn "ServerMetadataChange"
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyncmd_notify_parse_event(const struct imap_arg *arg,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *str;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn unsigned int i;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (i = 0; i < N_ELEMENTS(imap_notify_event_names); i++) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (strcasecmp(str, imap_notify_event_names[i]) == 0) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyncmd_notify_parse_fetch(struct imap_notify_context *ctx,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn return imap_fetch_att_list_parse(ctx->client, ctx->pool, list,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyncmd_notify_set_selected(struct imap_notify_context *ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn (IMAP_NOTIFY_EVENT_MESSAGE_NEW | IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *str;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* no events for selected mailbox. this is also the default
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn when NOTIFY command doesn't specify it explicitly */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn imap_arg_get_list(&list[1], &fetch_att_list)) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* MessageNew: list of fetch-att */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (cmd_notify_parse_fetch(ctx, fetch_att_list) < 0)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* if MessageNew or MessageExpunge is specified, both of them must */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if ((ctx->selected_events & EV_NEW_OR_EXPUNGE) != 0 &&
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn (ctx->selected_events & EV_NEW_OR_EXPUNGE) != EV_NEW_OR_EXPUNGE) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ctx->error = "MessageNew and MessageExpunge must be together";
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* if FlagChange or AnnotationChange is specified,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn MessageNew and MessageExpunge must also be specified */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn (ctx->selected_events & IMAP_NOTIFY_EVENT_MESSAGE_EXPUNGE) == 0) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ctx->error = "FlagChange requires MessageNew and MessageExpunge";
4759162d078d86628956cae4846c6efccf548e67Serge Hallynimap_notify_namespace_get(struct imap_notify_context *ctx,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn array_foreach_modifiable(&ctx->namespaces, notify_ns) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn notify_ns = array_append_space(&ctx->namespaces);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn p_array_init(¬ify_ns->mailboxes, ctx->pool, 4);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynimap_notify_mailboxes_get(struct imap_notify_namespace *notify_ns,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn array_foreach_modifiable(¬ify_ns->mailboxes, notify_boxes) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn notify_boxes = array_append_space(¬ify_ns->mailboxes);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn p_array_init(¬ify_boxes->names, notify_ns->ctx->pool, 4);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyncmd_notify_add_mailbox(struct imap_notify_context *ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *const *names;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn unsigned int i, count, cur_len, name_len = strlen(name);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* we'll do only case-sensitive comparisons later,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn so sanitize INBOX to be uppercase */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn notify_ns = imap_notify_namespace_get(ctx, ns);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn notify_boxes = imap_notify_mailboxes_get(notify_ns, type, events);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn names = array_get(¬ify_boxes->names, &count);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn for (i = 0; i < count; ) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* exact duplicate, already added */
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* see if one is a subtree of the other */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* already matched in this subtree */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* we're adding a parent, remove the child */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn names = array_get(¬ify_boxes->names, &count);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstatic void cmd_notify_add_personal(struct imap_notify_context *ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn for (ns = ctx->client->user->namespaces; ns != NULL; ns = ns->next) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallynstatic void cmd_notify_add_subscribed(struct imap_notify_context *ctx,
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn for (ns = ctx->client->user->namespaces; ns != NULL; ns = ns->next) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyncmd_notify_add_mailbox_namespaces(struct imap_notify_context *ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *name,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn ns = mail_namespace_find(ctx->client->user->namespaces, name);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn cmd_notify_add_mailbox(ctx, ns, name, type, events);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyncmd_notify_add_mailboxes(struct imap_notify_context *ctx,
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn const char *name;
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn cmd_notify_add_mailbox_namespaces(ctx, name, type, events);
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn cmd_notify_add_mailbox_namespaces(ctx, name, type, events);
4759162d078d86628956cae4846c6efccf548e67Serge Hallyncmd_notify_set(struct imap_notify_context *ctx, const struct imap_arg *args)
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn const struct imap_arg *event_group, *mailboxes, *list;
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* send STATUS replies for all matched mailboxes before
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn NOTIFY's OK reply */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* filter-mailboxes */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (!imap_arg_get_atom(event_group, &filter_mailboxes))
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn if (strcasecmp(filter_mailboxes, "selected") == 0 ||
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn strcasecmp(filter_mailboxes, "selected-delayed") == 0) {
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn /* setting events for selected mailbox.
4759162d078d86628956cae4846c6efccf548e67Serge Hallyn handle specially. */
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (strcasecmp(filter_mailboxes, "selected") == 0)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (cmd_notify_set_selected(ctx, event_group) < 0)
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn if (strcasecmp(filter_mailboxes, "subtree") == 0 ||
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn strcasecmp(filter_mailboxes, "mailboxes") == 0) {
d1458ac8d13880f83fa2d1e08623b97c50d311d7Serge Hallyn /* parse events */
event_mask = 0;
event_mask) < 0)
event_mask) < 0)
mailbox_flags = 0;
IMAP_NOTIFY_EVENT_FLAG_CHANGE)) != 0)
return TRUE;
return FALSE;
const char *str;
int ret = 0;
return FALSE;
if (ret < 0) {
return TRUE;
return TRUE;
return TRUE;
return TRUE;