cmd-subscribe.c revision 1c885b304f060e3ac4fe04195a2f53457d0ac99e
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "imap-common.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "imap-commands.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "mail-namespace.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenstatic bool have_listable_namespace_prefix(struct mail_namespace *ns,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const char *name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen unsigned int name_len = strlen(name);
e54512a5189192fe72d1e2c53927c98c5ac920b4Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (; ns != NULL; ns = ns->next) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen continue;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (ns->prefix_len <= name_len)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen continue;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* if prefix has multiple hierarchies, allow subscribing to
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen any of the hierarchies */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (strncmp(ns->prefix, name, name_len) == 0 &&
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen ns->prefix[name_len] == ns->sep)
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen return TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return FALSE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainenbool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen{
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct mail_namespace *ns, *real_ns;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen const char *mailbox, *verify_name, *real_name;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen /* <mailbox> */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen return FALSE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen verify_name = mailbox;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen real_name = mailbox;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen real_ns = client_find_namespace(cmd, &real_name,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen CLIENT_VERIFY_MAILBOX_NONE);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (real_ns == NULL)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen return TRUE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* now find a namespace where the subscription can be added to */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen &mailbox);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (ns == NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen client_send_tagline(cmd, "NO Unknown subscription namespace.");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return TRUE;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen }
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ns != real_ns) {
8fb1e3e2349c9940732b5bb77a2a4053b8f72a4fTimo Sirainen /* subscription is being written to a different namespace
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen than where the mailbox exists. */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen mailbox = t_strconcat(real_ns->prefix, real_name, NULL);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen /* drop the common prefix */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(strncmp(ns->prefix, mailbox, strlen(ns->prefix)) == 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mailbox += strlen(ns->prefix);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((cmd->client->workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen *mailbox != '\0' && mailbox[strlen(mailbox)-1] ==
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mailbox_list_get_hierarchy_sep(ns->list)) {
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen /* verify the validity without the trailing '/' */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen verify_name = t_strndup(verify_name, strlen(verify_name)-1);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen }
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (have_listable_namespace_prefix(cmd->client->user->namespaces,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen verify_name)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* subscribing to a listable namespace prefix, allow it. */
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen } else if (subscribe) {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (client_find_namespace(cmd, &verify_name,
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen CLIENT_VERIFY_MAILBOX_SHOULD_EXIST) == NULL)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen return TRUE;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen } else {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (client_find_namespace(cmd, &verify_name,
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen CLIENT_VERIFY_MAILBOX_NAME) == NULL)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen return TRUE;
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen }
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mailbox_list_set_subscribed(ns->list, mailbox, subscribe) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen client_send_list_error(cmd, ns->list);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen else {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen client_send_tagline(cmd, subscribe ?
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen "OK Subscribe completed." :
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen "OK Unsubscribe completed.");
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return TRUE;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen}
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenbool cmd_subscribe(struct client_command_context *cmd)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen{
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen return cmd_subscribe_full(cmd, TRUE);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen}
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen