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

« back to all changes in this revision

Viewing changes to src/imap/cmd-fetch.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 */
 
1
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "imap-common.h"
4
4
#include "ostream.h"
21
21
};
22
22
 
23
23
static bool
24
 
fetch_parse_args(struct imap_fetch_context *ctx, const struct imap_arg *arg,
25
 
                 const struct imap_arg **next_arg_r)
 
24
imap_fetch_cmd_init_handler(struct imap_fetch_context *ctx,
 
25
                            struct client_command_context *cmd,
 
26
                            const char *name, const struct imap_arg **args)
 
27
{
 
28
        struct imap_fetch_init_context init_ctx;
 
29
 
 
30
        memset(&init_ctx, 0, sizeof(init_ctx));
 
31
        init_ctx.fetch_ctx = ctx;
 
32
        init_ctx.pool = ctx->ctx_pool;
 
33
        init_ctx.name = name;
 
34
        init_ctx.args = *args;
 
35
 
 
36
        if (!imap_fetch_init_handler(&init_ctx)) {
 
37
                i_assert(init_ctx.error != NULL);
 
38
                client_send_command_error(cmd, init_ctx.error);
 
39
                return FALSE;
 
40
        }
 
41
        *args = init_ctx.args;
 
42
        return TRUE;
 
43
}
 
44
 
 
45
static bool
 
46
fetch_parse_args(struct imap_fetch_context *ctx,
 
47
                 struct client_command_context *cmd,
 
48
                 const struct imap_arg *arg, const struct imap_arg **next_arg_r)
26
49
{
27
50
        const char *str, *const *macro;
28
51
 
29
 
        if (ctx->cmd->uid) {
30
 
                if (!imap_fetch_init_handler(ctx, "UID", &arg))
 
52
        if (cmd->uid) {
 
53
                if (!imap_fetch_cmd_init_handler(ctx, cmd, "UID", &arg))
31
54
                        return FALSE;
32
55
        }
33
56
        if (imap_arg_get_atom(arg, &str)) {
43
66
                        macro = full_macro;
44
67
                else {
45
68
                        macro = NULL;
46
 
                        if (!imap_fetch_init_handler(ctx, str, &arg))
 
69
                        if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
47
70
                                return FALSE;
48
71
                }
49
72
                if (macro != NULL) {
50
73
                        while (*macro != NULL) {
51
 
                                if (!imap_fetch_init_handler(ctx, *macro, &arg))
 
74
                                if (!imap_fetch_cmd_init_handler(ctx, cmd, *macro, &arg))
52
75
                                        return FALSE;
53
76
                                macro++;
54
77
                        }
58
81
                *next_arg_r = arg + 1;
59
82
                arg = imap_arg_as_list(arg);
60
83
                if (IMAP_ARG_IS_EOL(arg)) {
61
 
                        client_send_command_error(ctx->cmd,
 
84
                        client_send_command_error(cmd,
62
85
                                                  "FETCH list is empty.");
63
86
                        return FALSE;
64
87
                }
65
88
                while (imap_arg_get_atom(arg, &str)) {
66
89
                        str = t_str_ucase(str);
67
90
                        arg++;
68
 
                        if (!imap_fetch_init_handler(ctx, str, &arg))
 
91
                        if (!imap_fetch_cmd_init_handler(ctx, cmd, str, &arg))
69
92
                                return FALSE;
70
93
                }
71
94
                if (!IMAP_ARG_IS_EOL(arg)) {
72
 
                        client_send_command_error(ctx->cmd,
 
95
                        client_send_command_error(cmd,
73
96
                                "FETCH list contains non-atoms.");
74
97
                        return FALSE;
75
98
                }
79
102
 
80
103
static bool
81
104
fetch_parse_modifier(struct imap_fetch_context *ctx,
82
 
                     const char *name, const struct imap_arg **args)
 
105
                     struct client_command_context *cmd,
 
106
                     struct mail_search_args *search_args,
 
107
                     const char *name, const struct imap_arg **args,
 
108
                     bool *send_vanished)
83
109
{
84
110
        const char *str;
85
111
        uint64_t modseq;
87
113
        if (strcmp(name, "CHANGEDSINCE") == 0) {
88
114
                if (!imap_arg_get_atom(*args, &str) ||
89
115
                    str_to_uint64(str, &modseq) < 0) {
90
 
                        client_send_command_error(ctx->cmd,
 
116
                        client_send_command_error(cmd,
91
117
                                "Invalid CHANGEDSINCE modseq.");
92
118
                        return FALSE;
93
119
                }
94
120
                *args += 1;
95
 
                return imap_fetch_add_changed_since(ctx, modseq);
 
121
                imap_search_add_changed_since(search_args, modseq);
 
122
                imap_fetch_init_nofail_handler(ctx, imap_fetch_modseq_init);
 
123
                return TRUE;
96
124
        }
97
 
        if (strcmp(name, "VANISHED") == 0 && ctx->cmd->uid) {
 
125
        if (strcmp(name, "VANISHED") == 0 && cmd->uid) {
98
126
                if ((ctx->client->enabled_features &
99
127
                     MAILBOX_FEATURE_QRESYNC) == 0) {
100
 
                        client_send_command_error(ctx->cmd,
101
 
                                                  "QRESYNC not enabled");
 
128
                        client_send_command_error(cmd, "QRESYNC not enabled");
102
129
                        return FALSE;
103
130
                }
104
 
                ctx->send_vanished = TRUE;
 
131
                *send_vanished = TRUE;
105
132
                return TRUE;
106
133
        }
107
134
 
108
 
        client_send_command_error(ctx->cmd, "Unknown FETCH modifier");
 
135
        client_send_command_error(cmd, "Unknown FETCH modifier");
109
136
        return FALSE;
110
137
}
111
138
 
112
139
static bool
113
140
fetch_parse_modifiers(struct imap_fetch_context *ctx,
114
 
                      const struct imap_arg *args)
 
141
                      struct client_command_context *cmd,
 
142
                      struct mail_search_args *search_args,
 
143
                      const struct imap_arg *args, bool *send_vanished_r)
115
144
{
116
145
        const char *name;
117
146
 
 
147
        *send_vanished_r = FALSE;
 
148
 
118
149
        while (!IMAP_ARG_IS_EOL(args)) {
119
150
                if (!imap_arg_get_atom(args, &name)) {
120
 
                        client_send_command_error(ctx->cmd,
 
151
                        client_send_command_error(cmd,
121
152
                                "FETCH modifiers contain non-atoms.");
122
153
                        return FALSE;
123
154
                }
124
155
                args++;
125
 
                if (!fetch_parse_modifier(ctx, t_str_ucase(name), &args))
 
156
                if (!fetch_parse_modifier(ctx, cmd, search_args,
 
157
                                          t_str_ucase(name),
 
158
                                          &args, send_vanished_r))
126
159
                        return FALSE;
127
160
        }
128
 
        if (ctx->send_vanished &&
129
 
            (ctx->search_args->args->next == NULL ||
130
 
             ctx->search_args->args->next->type != SEARCH_MODSEQ)) {
131
 
                client_send_command_error(ctx->cmd,
 
161
        if (*send_vanished_r &&
 
162
            (search_args->args->next == NULL ||
 
163
             search_args->args->next->type != SEARCH_MODSEQ)) {
 
164
                client_send_command_error(cmd,
132
165
                        "VANISHED used without CHANGEDSINCE");
133
166
                return FALSE;
134
167
        }
135
168
        return TRUE;
136
169
}
137
170
 
138
 
static bool cmd_fetch_finish(struct imap_fetch_context *ctx)
 
171
static bool cmd_fetch_finish(struct imap_fetch_context *ctx,
 
172
                             struct client_command_context *cmd)
139
173
{
140
174
        static const char *ok_message = "OK Fetch completed.";
141
 
        struct client_command_context *cmd = ctx->cmd;
142
175
        const char *tagged_reply = ok_message;
 
176
        enum mail_error error;
 
177
        bool failed, seen_flags_changed = ctx->state.seen_flags_changed;
143
178
 
144
 
        if (ctx->partial_fetch) {
 
179
        if (ctx->state.skipped_expunged_msgs) {
145
180
                tagged_reply = "OK ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
146
181
                        "Some messages were already expunged.";
147
182
        }
148
183
 
149
 
        if (imap_fetch_deinit(ctx) < 0)
150
 
                ctx->failed = TRUE;
 
184
        failed = imap_fetch_end(ctx) < 0;
 
185
        imap_fetch_free(&ctx);
151
186
 
152
 
        if (ctx->failed) {
 
187
        if (failed) {
153
188
                const char *errstr;
154
189
 
155
 
                if (ctx->client->output->closed) {
 
190
                if (cmd->client->output->closed) {
156
191
                        client_disconnect(cmd->client, "Disconnected");
157
192
                        return TRUE;
158
193
                }
159
194
 
160
 
                errstr = mailbox_get_last_error(cmd->client->mailbox, NULL);
161
 
 
162
 
                /* We never want to reply NO to FETCH requests,
163
 
                   BYE is preferrable (see imap-ml for reasons). */
164
 
                client_disconnect_with_error(cmd->client, errstr);
165
 
                return TRUE;
 
195
                errstr = mailbox_get_last_error(cmd->client->mailbox, &error);
 
196
                if (error == MAIL_ERROR_CONVERSION) {
 
197
                        /* BINARY found unsupported Content-Transfer-Encoding */
 
198
                        tagged_reply = t_strdup_printf(
 
199
                                "NO ["IMAP_RESP_CODE_UNKNOWN_CTE"] %s", errstr);
 
200
                } else {
 
201
                        /* We never want to reply NO to FETCH requests,
 
202
                           BYE is preferrable (see imap-ml for reasons). */
 
203
                        client_disconnect_with_error(cmd->client, errstr);
 
204
                        return TRUE;
 
205
                }
166
206
        }
167
207
 
168
208
        return cmd_sync(cmd,
169
 
                        (ctx->seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) |
 
209
                        (seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) |
170
210
                        (cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES), 0,
171
211
                        tagged_reply);
172
212
}
175
215
{
176
216
        struct imap_fetch_context *ctx = cmd->context;
177
217
 
178
 
        if (imap_fetch_more(ctx) == 0) {
 
218
        if (imap_fetch_more(ctx, cmd) == 0) {
179
219
                /* unfinished */
180
220
                return FALSE;
181
221
        }
182
 
        return cmd_fetch_finish(ctx);
 
222
        return cmd_fetch_finish(ctx, cmd);
183
223
}
184
224
 
185
225
bool cmd_fetch(struct client_command_context *cmd)
188
228
        struct imap_fetch_context *ctx;
189
229
        const struct imap_arg *args, *next_arg, *list_arg;
190
230
        struct mail_search_args *search_args;
 
231
        struct imap_fetch_qresync_args qresync_args;
191
232
        const char *messageset;
 
233
        bool send_vanished = FALSE;
192
234
        int ret;
193
235
 
194
236
        if (!client_read_args(cmd, 0, 0, &args))
211
253
        if (ret <= 0)
212
254
                return ret < 0;
213
255
 
214
 
        ctx = imap_fetch_init(cmd, client->mailbox);
215
 
        if (ctx == NULL) {
 
256
        ctx = imap_fetch_alloc(client, cmd->pool);
 
257
 
 
258
        if (!fetch_parse_args(ctx, cmd, &args[1], &next_arg) ||
 
259
            (imap_arg_get_list(next_arg, &list_arg) &&
 
260
             !fetch_parse_modifiers(ctx, cmd, search_args, list_arg,
 
261
                                    &send_vanished))) {
 
262
                imap_fetch_free(&ctx);
216
263
                mail_search_args_unref(&search_args);
217
264
                return TRUE;
218
265
        }
219
 
        ctx->search_args = search_args;
220
 
 
221
 
        if (!fetch_parse_args(ctx, &args[1], &next_arg) ||
222
 
            (imap_arg_get_list(next_arg, &list_arg) &&
223
 
             !fetch_parse_modifiers(ctx, list_arg))) {
224
 
                imap_fetch_deinit(ctx);
225
 
                return TRUE;
226
 
        }
227
 
 
228
 
        if (imap_fetch_begin(ctx) == 0) {
229
 
                if (imap_fetch_more(ctx) == 0) {
230
 
                        /* unfinished */
231
 
                        cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
232
 
 
233
 
                        cmd->func = cmd_fetch_continue;
234
 
                        cmd->context = ctx;
235
 
                        return FALSE;
 
266
 
 
267
        if (send_vanished) {
 
268
                memset(&qresync_args, 0, sizeof(qresync_args));
 
269
                if (imap_fetch_send_vanished(client, client->mailbox,
 
270
                                             search_args, &qresync_args) < 0) {
 
271
                        mail_search_args_unref(&search_args);
 
272
                        return cmd_fetch_finish(ctx, cmd);
236
273
                }
237
274
        }
238
 
        return cmd_fetch_finish(ctx);
 
275
 
 
276
        imap_fetch_begin(ctx, client->mailbox, search_args);
 
277
        mail_search_args_unref(&search_args);
 
278
 
 
279
        if (imap_fetch_more(ctx, cmd) == 0) {
 
280
                /* unfinished */
 
281
                cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
 
282
 
 
283
                cmd->func = cmd_fetch_continue;
 
284
                cmd->context = ctx;
 
285
                return FALSE;
 
286
        }
 
287
        return cmd_fetch_finish(ctx, cmd);
239
288
}