summaryrefslogtreecommitdiffstats
path: root/src/imap/cmd-subscribe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/cmd-subscribe.c')
-rw-r--r--src/imap/cmd-subscribe.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/imap/cmd-subscribe.c b/src/imap/cmd-subscribe.c
new file mode 100644
index 0000000..03c2684
--- /dev/null
+++ b/src/imap/cmd-subscribe.c
@@ -0,0 +1,87 @@
+/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
+
+#include "imap-common.h"
+#include "imap-utf7.h"
+#include "imap-commands.h"
+#include "mail-namespace.h"
+
+static bool
+subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box)
+{
+ enum mailbox_existence existence;
+
+ if (mailbox_exists(box, TRUE, &existence) < 0) {
+ client_send_box_error(cmd, box);
+ return FALSE;
+ }
+ if (existence == MAILBOX_EXISTENCE_NONE) {
+ client_send_tagline(cmd, t_strdup_printf(
+ "NO "MAIL_ERRSTR_MAILBOX_NOT_FOUND,
+ mailbox_get_vname(box)));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bool str_ends_with_char(const char *str, char c)
+{
+ size_t len = strlen(str);
+
+ return len > 0 && str[len-1] == c;
+}
+
+bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
+{
+ struct mail_namespace *ns;
+ struct mailbox *box, *box2;
+ const char *mailbox, *orig_mailbox;
+ bool unsubscribed_mailbox2;
+ char sep;
+
+ /* <mailbox> */
+ if (!client_read_string_args(cmd, 1, &mailbox))
+ return FALSE;
+ orig_mailbox = mailbox;
+
+ ns = client_find_namespace(cmd, &mailbox);
+ if (ns == NULL)
+ return TRUE;
+
+ box = mailbox_alloc(ns->list, mailbox, 0);
+ event_add_str(cmd->global_event, "mailbox", mailbox_get_vname(box));
+ if (subscribe) {
+ if (!subscribe_is_valid_name(cmd, box)) {
+ mailbox_free(&box);
+ return TRUE;
+ }
+ }
+
+ sep = mail_namespace_get_sep(ns);
+ unsubscribed_mailbox2 = FALSE;
+ if (!subscribe &&
+ str_ends_with_char(orig_mailbox, sep) &&
+ !str_ends_with_char(mailbox, sep)) {
+ /* try to unsubscribe both "box" and "box/" */
+ const char *name2 = t_strdup_printf("%s%c", mailbox, sep);
+ box2 = mailbox_alloc(ns->list, name2, 0);
+ if (mailbox_set_subscribed(box2, FALSE) == 0)
+ unsubscribed_mailbox2 = TRUE;
+ mailbox_free(&box2);
+ }
+
+ if (mailbox_set_subscribed(box, subscribe) < 0 &&
+ !unsubscribed_mailbox2) {
+ client_send_box_error(cmd, box);
+ } else {
+ client_send_tagline(cmd, subscribe ?
+ "OK Subscribe completed." :
+ "OK Unsubscribe completed.");
+ }
+ mailbox_free(&box);
+ return TRUE;
+}
+
+bool cmd_subscribe(struct client_command_context *cmd)
+{
+ return cmd_subscribe_full(cmd, TRUE);
+}