~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/utf8-namespace.patch/src/imap/imap-commands-util.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-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/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.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
2
 
 
3
 
#include "imap-common.h"
4
 
#include "array.h"
5
 
#include "buffer.h"
6
 
#include "str.h"
7
 
#include "str-sanitize.h"
8
 
#include "imap-resp-code.h"
9
 
#include "imap-parser.h"
10
 
#include "imap-sync.h"
11
 
#include "imap-utf7.h"
12
 
#include "imap-util.h"
13
 
#include "mail-storage.h"
14
 
#include "mail-namespace.h"
15
 
#include "imap-commands-util.h"
16
 
 
17
 
struct mail_namespace *
18
 
client_find_namespace(struct client_command_context *cmd, const char **mailbox)
19
 
{
20
 
        struct mail_namespace *namespaces = cmd->client->user->namespaces;
21
 
        struct mail_namespace *ns;
22
 
        unsigned int name_len;
23
 
        string_t *utf8_name;
24
 
 
25
 
        ns = mail_namespace_find(namespaces, *mailbox);
26
 
        if (ns == NULL) {
27
 
                client_send_tagline(cmd, t_strdup_printf(
28
 
                        "NO Client tried to access nonexistent namespace. "
29
 
                        "(Mailbox name should probably be prefixed with: %s)",
30
 
                        mail_namespace_find_inbox(namespaces)->prefix));
31
 
                return NULL;
32
 
        }
33
 
 
34
 
        name_len = strlen(*mailbox);
35
 
        if ((cmd->client->set->parsed_workarounds &
36
 
                        WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
37
 
            name_len > 0 &&
38
 
            (*mailbox)[name_len-1] == mail_namespace_get_sep(ns)) {
39
 
                /* drop the extra trailing hierarchy separator */
40
 
                *mailbox = t_strndup(*mailbox, name_len-1);
41
 
        }
42
 
 
43
 
        utf8_name = t_str_new(64);
44
 
        if (imap_utf7_to_utf8(*mailbox, utf8_name) < 0) {
45
 
                client_send_tagline(cmd, "NO Mailbox name is not valid mUTF-7");
46
 
                return NULL;
47
 
        }
48
 
        *mailbox = str_c(utf8_name);
49
 
        return ns;
50
 
}
51
 
 
52
 
bool client_verify_open_mailbox(struct client_command_context *cmd)
53
 
{
54
 
        if (cmd->client->mailbox != NULL)
55
 
                return TRUE;
56
 
        else {
57
 
                client_send_tagline(cmd, "BAD No mailbox selected.");
58
 
                return FALSE;
59
 
        }
60
 
}
61
 
 
62
 
int client_open_save_dest_box(struct client_command_context *cmd,
63
 
                              const char *name, struct mailbox **destbox_r)
64
 
{
65
 
        struct mail_namespace *ns;
66
 
        struct mailbox *box;
67
 
        const char *error_string;
68
 
        enum mail_error error;
69
 
 
70
 
        ns = client_find_namespace(cmd, &name);
71
 
        if (ns == NULL)
72
 
                return -1;
73
 
 
74
 
        if (cmd->client->mailbox != NULL &&
75
 
            mailbox_equals(cmd->client->mailbox, ns, name)) {
76
 
                *destbox_r = cmd->client->mailbox;
77
 
                return 0;
78
 
        }
79
 
        box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_SAVEONLY);
80
 
        if (mailbox_open(box) < 0) {
81
 
                error_string = mailbox_get_last_error(box, &error);
82
 
                if (error == MAIL_ERROR_NOTFOUND) {
83
 
                        client_send_tagline(cmd,  t_strdup_printf(
84
 
                                "NO [TRYCREATE] %s", error_string));
85
 
                } else {
86
 
                        client_send_storage_error(cmd, mailbox_get_storage(box));
87
 
                }
88
 
                mailbox_free(&box);
89
 
                return -1;
90
 
        }
91
 
        if (cmd->client->enabled_features != 0) {
92
 
                if (mailbox_enable(box, cmd->client->enabled_features) < 0) {
93
 
                        client_send_storage_error(cmd, mailbox_get_storage(box));
94
 
                        mailbox_free(&box);
95
 
                        return -1;
96
 
                }
97
 
        }
98
 
        *destbox_r = box;
99
 
        return 0;
100
 
}
101
 
 
102
 
const char *
103
 
imap_get_error_string(struct client_command_context *cmd,
104
 
                      const char *error_string, enum mail_error error)
105
 
{
106
 
        const char *resp_code = NULL;
107
 
 
108
 
        switch (error) {
109
 
        case MAIL_ERROR_NONE:
110
 
                break;
111
 
        case MAIL_ERROR_TEMP:
112
 
                resp_code = IMAP_RESP_CODE_SERVERBUG;
113
 
                break;
114
 
        case MAIL_ERROR_NOTPOSSIBLE:
115
 
        case MAIL_ERROR_PARAMS:
116
 
                resp_code = IMAP_RESP_CODE_CANNOT;
117
 
                break;
118
 
        case MAIL_ERROR_PERM:
119
 
                resp_code = IMAP_RESP_CODE_NOPERM;
120
 
                break;
121
 
        case MAIL_ERROR_NOSPACE:
122
 
                resp_code = IMAP_RESP_CODE_OVERQUOTA;
123
 
                break;
124
 
        case MAIL_ERROR_NOTFOUND:
125
 
                if ((cmd->cmd_flags & COMMAND_FLAG_USE_NONEXISTENT) != 0)
126
 
                        resp_code = IMAP_RESP_CODE_NONEXISTENT;
127
 
                break;
128
 
        case MAIL_ERROR_EXISTS:
129
 
                resp_code = IMAP_RESP_CODE_ALREADYEXISTS;
130
 
                break;
131
 
        case MAIL_ERROR_EXPUNGED:
132
 
                resp_code = IMAP_RESP_CODE_EXPUNGEISSUED;
133
 
                break;
134
 
        case MAIL_ERROR_INUSE:
135
 
                resp_code = IMAP_RESP_CODE_INUSE;
136
 
                break;
137
 
        }
138
 
        if (resp_code == NULL || *error_string == '[')
139
 
                return t_strconcat("NO ", error_string, NULL);
140
 
        else
141
 
                return t_strdup_printf("NO [%s] %s", resp_code, error_string);
142
 
}
143
 
 
144
 
void client_send_list_error(struct client_command_context *cmd,
145
 
                            struct mailbox_list *list)
146
 
{
147
 
        const char *error_string;
148
 
        enum mail_error error;
149
 
 
150
 
        error_string = mailbox_list_get_last_error(list, &error);
151
 
        client_send_tagline(cmd, imap_get_error_string(cmd, error_string,
152
 
                                                       error));
153
 
}
154
 
 
155
 
void client_send_storage_error(struct client_command_context *cmd,
156
 
                               struct mail_storage *storage)
157
 
{
158
 
        const char *error_string;
159
 
        enum mail_error error;
160
 
 
161
 
        if (cmd->client->mailbox != NULL &&
162
 
            mailbox_is_inconsistent(cmd->client->mailbox)) {
163
 
                /* we can't do forced CLOSE, so have to disconnect */
164
 
                client_disconnect_with_error(cmd->client,
165
 
                        "IMAP session state is inconsistent, please relogin.");
166
 
                return;
167
 
        }
168
 
 
169
 
        error_string = mail_storage_get_last_error(storage, &error);
170
 
        client_send_tagline(cmd, imap_get_error_string(cmd, error_string,
171
 
                                                       error));
172
 
}
173
 
 
174
 
void client_send_untagged_storage_error(struct client *client,
175
 
                                        struct mail_storage *storage)
176
 
{
177
 
        const char *error_string;
178
 
        enum mail_error error;
179
 
 
180
 
        if (client->mailbox != NULL &&
181
 
            mailbox_is_inconsistent(client->mailbox)) {
182
 
                /* we can't do forced CLOSE, so have to disconnect */
183
 
                client_disconnect_with_error(client,
184
 
                        "IMAP session state is inconsistent, please relogin.");
185
 
                return;
186
 
        }
187
 
 
188
 
        error_string = mail_storage_get_last_error(storage, &error);
189
 
        client_send_line(client, t_strconcat("* NO ", error_string, NULL));
190
 
}
191
 
 
192
 
bool client_parse_mail_flags(struct client_command_context *cmd,
193
 
                             const struct imap_arg *args,
194
 
                             enum mail_flags *flags_r,
195
 
                             const char *const **keywords_r)
196
 
{
197
 
        const char *atom;
198
 
        enum mail_flags flag;
199
 
        ARRAY_DEFINE(keywords, const char *);
200
 
 
201
 
        *flags_r = 0;
202
 
        *keywords_r = NULL;
203
 
        p_array_init(&keywords, cmd->pool, 16);
204
 
 
205
 
        while (!IMAP_ARG_IS_EOL(args)) {
206
 
                if (!imap_arg_get_atom(args, &atom)) {
207
 
                        client_send_command_error(cmd,
208
 
                                "Flags list contains non-atoms.");
209
 
                        return FALSE;
210
 
                }
211
 
 
212
 
                if (*atom == '\\') {
213
 
                        /* system flag */
214
 
                        atom = t_str_ucase(atom);
215
 
                        flag = imap_parse_system_flag(atom);
216
 
                        if (flag != 0 && flag != MAIL_RECENT)
217
 
                                *flags_r |= flag;
218
 
                        else {
219
 
                                client_send_tagline(cmd, t_strconcat(
220
 
                                        "BAD Invalid system flag ",
221
 
                                        atom, NULL));
222
 
                                return FALSE;
223
 
                        }
224
 
                } else {
225
 
                        /* keyword validity checks are done by lib-storage */
226
 
                        array_append(&keywords, &atom, 1);
227
 
                }
228
 
 
229
 
                args++;
230
 
        }
231
 
 
232
 
        if (array_count(&keywords) == 0)
233
 
                *keywords_r = NULL;
234
 
        else {
235
 
                (void)array_append_space(&keywords); /* NULL-terminate */
236
 
                *keywords_r = array_idx(&keywords, 0);
237
 
        }
238
 
        return TRUE;
239
 
}
240
 
 
241
 
void client_send_mailbox_flags(struct client *client, bool selecting)
242
 
{
243
 
        struct mailbox_status status;
244
 
        unsigned int count = array_count(client->keywords.names);
245
 
        const char *const *keywords;
246
 
        string_t *str;
247
 
 
248
 
        if (!selecting && count == client->keywords.announce_count) {
249
 
                /* no changes to keywords and we're not selecting a mailbox */
250
 
                return;
251
 
        }
252
 
 
253
 
        client->keywords.announce_count = count;
254
 
        mailbox_get_open_status(client->mailbox, STATUS_PERMANENT_FLAGS,
255
 
                                &status);
256
 
 
257
 
        keywords = count == 0 ? NULL :
258
 
                array_idx(client->keywords.names, 0);
259
 
        str = t_str_new(128);
260
 
        str_append(str, "* FLAGS (");
261
 
        imap_write_flags(str, MAIL_FLAGS_NONRECENT, keywords);
262
 
        str_append_c(str, ')');
263
 
        client_send_line(client, str_c(str));
264
 
 
265
 
        if (!status.permanent_keywords)
266
 
                keywords = NULL;
267
 
 
268
 
        str_truncate(str, 0);
269
 
        str_append(str, "* OK [PERMANENTFLAGS (");
270
 
        imap_write_flags(str, status.permanent_flags, keywords);
271
 
        if (status.allow_new_keywords) {
272
 
                if (status.permanent_flags != 0 || keywords != NULL)
273
 
                        str_append_c(str, ' ');
274
 
                str_append(str, "\\*");
275
 
        }
276
 
        str_append(str, ")] ");
277
 
 
278
 
        if (mailbox_is_readonly(client->mailbox))
279
 
                str_append(str, "Read-only mailbox.");
280
 
        else
281
 
                str_append(str, "Flags permitted.");
282
 
        client_send_line(client, str_c(str));
283
 
}
284
 
 
285
 
void client_update_mailbox_flags(struct client *client,
286
 
                                 const ARRAY_TYPE(keywords) *keywords)
287
 
{
288
 
        client->keywords.names = keywords;
289
 
        client->keywords.announce_count = 0;
290
 
}
291
 
 
292
 
const char *const *
293
 
client_get_keyword_names(struct client *client, ARRAY_TYPE(keywords) *dest,
294
 
                         const ARRAY_TYPE(keyword_indexes) *src)
295
 
{
296
 
        const unsigned int *kw_indexes;
297
 
        const char *const *all_names;
298
 
        unsigned int all_count;
299
 
 
300
 
        client_send_mailbox_flags(client, FALSE);
301
 
 
302
 
        /* convert indexes to names */
303
 
        all_names = array_get(client->keywords.names, &all_count);
304
 
        array_clear(dest);
305
 
        array_foreach(src, kw_indexes) {
306
 
                unsigned int kw_index = *kw_indexes;
307
 
 
308
 
                i_assert(kw_index < all_count);
309
 
                array_append(dest, &all_names[kw_index], 1);
310
 
        }
311
 
 
312
 
        (void)array_append_space(dest);
313
 
        return array_idx(dest, 0);
314
 
}
315
 
 
316
 
bool mailbox_equals(const struct mailbox *box1,
317
 
                    const struct mail_namespace *ns2, const char *name2)
318
 
{
319
 
        struct mail_namespace *ns1 = mailbox_get_namespace(box1);
320
 
        const char *name1;
321
 
 
322
 
        if (ns1 != ns2)
323
 
                return FALSE;
324
 
 
325
 
        name1 = mailbox_get_vname(box1);
326
 
        if (strcmp(name1, name2) == 0)
327
 
                return TRUE;
328
 
 
329
 
        return strcasecmp(name1, "INBOX") == 0 &&
330
 
                strcasecmp(name2, "INBOX") == 0;
331
 
}
332
 
 
333
 
void msgset_generator_init(struct msgset_generator_context *ctx, string_t *str)
334
 
{
335
 
        memset(ctx, 0, sizeof(*ctx));
336
 
        ctx->str = str;
337
 
        ctx->last_uid = (uint32_t)-1;
338
 
}
339
 
 
340
 
void msgset_generator_next(struct msgset_generator_context *ctx, uint32_t uid)
341
 
{
342
 
        if (uid != ctx->last_uid+1) {
343
 
                if (ctx->first_uid == 0)
344
 
                        ;
345
 
                else if (ctx->first_uid == ctx->last_uid)
346
 
                        str_printfa(ctx->str, "%u,", ctx->first_uid);
347
 
                else {
348
 
                        str_printfa(ctx->str, "%u:%u,",
349
 
                                    ctx->first_uid, ctx->last_uid);
350
 
                }
351
 
                ctx->first_uid = uid;
352
 
        }
353
 
        ctx->last_uid = uid;
354
 
}
355
 
 
356
 
void msgset_generator_finish(struct msgset_generator_context *ctx)
357
 
{
358
 
        if (ctx->first_uid == ctx->last_uid)
359
 
                str_printfa(ctx->str, "%u", ctx->first_uid);
360
 
        else
361
 
                str_printfa(ctx->str, "%u:%u", ctx->first_uid, ctx->last_uid);
362
 
}