1
/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
1
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
3
3
#include "imap-common.h"
4
5
#include "imap-commands.h"
5
6
#include "mail-namespace.h"
7
static bool have_listable_namespace_prefix(struct mail_namespace *ns,
10
unsigned int name_len = strlen(name);
12
for (; ns != NULL; ns = ns->next) {
13
if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
14
NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
17
if (ns->prefix_len <= name_len)
20
/* if prefix has multiple hierarchies, allow subscribing to
21
any of the hierarchies */
22
if (strncmp(ns->prefix, name, name_len) == 0 &&
23
ns->prefix[name_len] == ns->sep)
9
subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box)
11
enum mailbox_existence existence;
14
if ((ret = mailbox_exists(box, TRUE, &existence)) < 0) {
15
client_send_storage_error(cmd, mailbox_get_storage(box));
18
if (existence == MAILBOX_EXISTENCE_NONE) {
19
client_send_tagline(cmd, t_strdup_printf(
20
"NO "MAIL_ERRSTR_MAILBOX_NOT_FOUND,
21
mailbox_get_vname(box)));
27
static bool str_ends_with_char(const char *str, char c)
29
unsigned int len = strlen(str);
31
return len > 0 && str[len-1] == c;
29
34
bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
31
enum mailbox_name_status status;
32
struct mail_namespace *ns, *box_ns;
33
const char *mailbox, *storage_name, *subs_name, *subs_name2 = NULL;
36
struct mail_namespace *ns;
37
struct mailbox *box, *box2;
38
const char *mailbox, *orig_mailbox;
34
39
bool unsubscribed_mailbox2;
37
43
if (!client_read_string_args(cmd, 1, &mailbox))
40
box_ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
44
/* now find a namespace where the subscription can be added to */
46
ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
49
client_send_tagline(cmd, "NO Unknown subscription namespace.");
54
/* subscription is being written to a different namespace
55
than where the mailbox exists. */
56
subs_name = t_strconcat(box_ns->prefix, storage_name, NULL);
57
/* drop the common prefix */
58
i_assert(strncmp(ns->prefix, subs_name, strlen(ns->prefix)) == 0);
59
subs_name += strlen(ns->prefix);
62
if ((cmd->client->set->parsed_workarounds &
63
WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
65
subs_name[strlen(subs_name)-1] == ns->real_sep) {
66
/* verify the validity without the trailing '/' */
67
mailbox = t_strndup(mailbox, strlen(mailbox)-1);
68
subs_name2 = subs_name;
69
subs_name = t_strndup(subs_name, strlen(subs_name)-1);
72
if (have_listable_namespace_prefix(cmd->client->user->namespaces,
74
/* subscribing to a listable namespace prefix, allow it. */
75
} else if (subscribe) {
76
if (client_find_namespace(cmd, mailbox,
77
&storage_name, &status) == NULL)
80
case MAILBOX_NAME_EXISTS_MAILBOX:
81
case MAILBOX_NAME_EXISTS_DIR:
83
case MAILBOX_NAME_VALID:
84
case MAILBOX_NAME_INVALID:
85
case MAILBOX_NAME_NOINFERIORS:
86
client_fail_mailbox_name_status(cmd, mailbox,
91
if (client_find_namespace(cmd, mailbox,
92
&storage_name, &status) == NULL)
95
case MAILBOX_NAME_EXISTS_MAILBOX:
96
case MAILBOX_NAME_EXISTS_DIR:
97
case MAILBOX_NAME_VALID:
99
case MAILBOX_NAME_INVALID:
100
case MAILBOX_NAME_NOINFERIORS:
101
client_fail_mailbox_name_status(cmd, mailbox,
45
orig_mailbox = mailbox;
47
ns = client_find_namespace(cmd, &mailbox);
51
box = mailbox_alloc(ns->list, mailbox, 0);
53
if (!subscribe_is_valid_name(cmd, box)) {
59
sep = mail_namespace_get_sep(ns);
107
60
unsubscribed_mailbox2 = FALSE;
108
if (!subscribe && subs_name2 != NULL) {
62
str_ends_with_char(orig_mailbox, sep) &&
63
!str_ends_with_char(mailbox, sep)) {
109
64
/* try to unsubscribe both "box" and "box/" */
110
if (mailbox_list_set_subscribed(ns->list, subs_name2,
65
const char *name2 = t_strdup_printf("%s%c", mailbox, sep);
66
box2 = mailbox_alloc(ns->list, name2, 0);
67
if (mailbox_set_subscribed(box2, FALSE) == 0)
112
68
unsubscribed_mailbox2 = TRUE;
115
if (mailbox_list_set_subscribed(ns->list, subs_name, subscribe) < 0 &&
72
if (mailbox_set_subscribed(box, subscribe) < 0 &&
116
73
!unsubscribed_mailbox2) {
117
client_send_list_error(cmd, ns->list);
74
client_send_storage_error(cmd, mailbox_get_storage(box));
119
76
client_send_tagline(cmd, subscribe ?
120
77
"OK Subscribe completed." :
121
78
"OK Unsubscribe completed.");