~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/imap/cmd-subscribe.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "imap-common.h"
 
4
#include "imap-utf7.h"
4
5
#include "imap-commands.h"
5
6
#include "mail-namespace.h"
6
7
 
7
 
static bool have_listable_namespace_prefix(struct mail_namespace *ns,
8
 
                                           const char *name)
9
 
{
10
 
        unsigned int name_len = strlen(name);
11
 
 
12
 
        for (; ns != NULL; ns = ns->next) {
13
 
                if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
14
 
                                  NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
15
 
                        continue;
16
 
 
17
 
                if (ns->prefix_len <= name_len)
18
 
                        continue;
19
 
 
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)
24
 
                        return TRUE;
25
 
        }
26
 
        return FALSE;
 
8
static bool
 
9
subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box)
 
10
{
 
11
        enum mailbox_existence existence;
 
12
        int ret;
 
13
 
 
14
        if ((ret = mailbox_exists(box, TRUE, &existence)) < 0) {
 
15
                client_send_storage_error(cmd, mailbox_get_storage(box));
 
16
                return FALSE;
 
17
        }
 
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)));
 
22
                return FALSE;
 
23
        }
 
24
        return TRUE;
 
25
}
 
26
 
 
27
static bool str_ends_with_char(const char *str, char c)
 
28
{
 
29
        unsigned int len = strlen(str);
 
30
 
 
31
        return len > 0 && str[len-1] == c;
27
32
}
28
33
 
29
34
bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
30
35
{
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;
 
40
        char sep;
35
41
 
36
42
        /* <mailbox> */
37
43
        if (!client_read_string_args(cmd, 1, &mailbox))
38
44
                return FALSE;
39
 
 
40
 
        box_ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
41
 
        if (box_ns == NULL)
42
 
                return TRUE;
43
 
 
44
 
        /* now find a namespace where the subscription can be added to */
45
 
        subs_name = mailbox;
46
 
        ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
47
 
                                              &subs_name);
48
 
        if (ns == NULL) {
49
 
                client_send_tagline(cmd, "NO Unknown subscription namespace.");
50
 
                return TRUE;
51
 
        }
52
 
 
53
 
        if (ns != box_ns) {
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);
60
 
        }
61
 
 
62
 
        if ((cmd->client->set->parsed_workarounds &
63
 
             WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
64
 
            *subs_name != '\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);
70
 
        }
71
 
 
72
 
        if (have_listable_namespace_prefix(cmd->client->user->namespaces,
73
 
                                           mailbox)) {
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)
78
 
                        return TRUE;
79
 
                switch (status) {
80
 
                case MAILBOX_NAME_EXISTS_MAILBOX:
81
 
                case MAILBOX_NAME_EXISTS_DIR:
82
 
                        break;
83
 
                case MAILBOX_NAME_VALID:
84
 
                case MAILBOX_NAME_INVALID:
85
 
                case MAILBOX_NAME_NOINFERIORS:
86
 
                        client_fail_mailbox_name_status(cmd, mailbox,
87
 
                                                        NULL, status);
88
 
                        return TRUE;
89
 
                }
90
 
        } else {
91
 
                if (client_find_namespace(cmd, mailbox,
92
 
                                          &storage_name, &status) == NULL)
93
 
                        return TRUE;
94
 
                switch (status) {
95
 
                case MAILBOX_NAME_EXISTS_MAILBOX:
96
 
                case MAILBOX_NAME_EXISTS_DIR:
97
 
                case MAILBOX_NAME_VALID:
98
 
                        break;
99
 
                case MAILBOX_NAME_INVALID:
100
 
                case MAILBOX_NAME_NOINFERIORS:
101
 
                        client_fail_mailbox_name_status(cmd, mailbox,
102
 
                                                        NULL, status);
103
 
                        return TRUE;
104
 
                }
105
 
        }
106
 
 
 
45
        orig_mailbox = mailbox;
 
46
 
 
47
        ns = client_find_namespace(cmd, &mailbox);
 
48
        if (ns == NULL)
 
49
                return TRUE;
 
50
 
 
51
        box = mailbox_alloc(ns->list, mailbox, 0);
 
52
        if (subscribe) {
 
53
                if (!subscribe_is_valid_name(cmd, box)) {
 
54
                        mailbox_free(&box);
 
55
                        return TRUE;
 
56
                }
 
57
        }
 
58
 
 
59
        sep = mail_namespace_get_sep(ns);
107
60
        unsubscribed_mailbox2 = FALSE;
108
 
        if (!subscribe && subs_name2 != NULL) {
 
61
        if (!subscribe &&
 
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,
111
 
                                                FALSE) == 0)
 
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;
 
69
                mailbox_free(&box2);
113
70
        }
114
71
 
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));
118
75
        } else {
119
76
                client_send_tagline(cmd, subscribe ?
120
77
                                    "OK Subscribe completed." :
121
78
                                    "OK Unsubscribe completed.");
122
79
        }
 
80
        mailbox_free(&box);
123
81
        return TRUE;
124
82
}
125
83