Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4973:ec41129cd0ef HEAD
When client fetches message data that has already been expunged, reply with
dummy NIL and such values for the message. Don't disconnect the client
anymore.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 28 Dec 2006 20:40:29 +0200 |
parents | 0103df03b5d4 |
children | 4654603f24f6 |
files | src/imap/cmd-fetch.c src/imap/imap-fetch-body.c src/imap/imap-fetch.c src/imap/imap-fetch.h |
diffstat | 4 files changed, 94 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-fetch.c Thu Dec 28 20:37:25 2006 +0200 +++ b/src/imap/cmd-fetch.c Thu Dec 28 20:40:29 2006 +0200 @@ -72,15 +72,11 @@ { struct client_command_context *cmd = ctx->cmd; static const char *ok_message = "OK Fetch completed."; - bool failed, partial; - - partial = ctx->partial_fetch; - failed = ctx->failed; if (imap_fetch_deinit(ctx) < 0) - failed = TRUE; + ctx->failed = TRUE; - if (failed || (partial && !cmd->uid)) { + if (ctx->failed) { struct mail_storage *storage; const char *error; bool syntax, temporary_error; @@ -96,10 +92,6 @@ if (!syntax) { /* We never want to reply NO to FETCH requests, BYE is preferrable (see imap-ml for reasons). */ - if (partial) { - error = "Out of sync: " - "Trying to fetch expunged message"; - } client_disconnect_with_error(cmd->client, error); } else { /* user error, we'll reply with BAD */
--- a/src/imap/imap-fetch-body.c Thu Dec 28 20:37:25 2006 +0200 +++ b/src/imap/imap-fetch-body.c Thu Dec 28 20:40:29 2006 +0200 @@ -83,6 +83,17 @@ return size <= body->max_size ? size : body->max_size; } +static const char *get_body_name(const struct imap_fetch_body_data *body) +{ + string_t *str; + + str = t_str_new(128); + str_printfa(str, "BODY[%s]", body->section); + if (body->skip_set) + str_printfa(str, "<%"PRIuUOFF_T">", body->skip); + return str_c(str); +} + static string_t *get_prefix(struct imap_fetch_context *ctx, const struct imap_fetch_body_data *body, uoff_t size) @@ -95,9 +106,7 @@ else str_append_c(str, ' '); - str_printfa(str, "BODY[%s]", body->section); - if (body->skip_set) - str_printfa(str, "<%"PRIuUOFF_T">", body->skip); + str_append(str, get_body_name(body)); if (size != (uoff_t)-1) str_printfa(str, " {%"PRIuUOFF_T"}\r\n", size); @@ -583,16 +592,17 @@ struct imap_fetch_body_data *body, const char *section) { - const char *const *arr; + const char *const *arr, *name; if (!fetch_body_header_fields_check(section)) return FALSE; + name = get_body_name(body); if ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0) { /* we'll need to open the file anyway, don't try to get the headers from cache. */ - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_body_header_partial, body); return TRUE; } @@ -605,7 +615,7 @@ } body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields); - imap_fetch_add_handler(ctx, FALSE, TRUE, + imap_fetch_add_handler(ctx, FALSE, TRUE, name, "NIL", fetch_body_header_fields, body); t_pop(); return TRUE; @@ -614,18 +624,21 @@ static bool fetch_body_section_name_init(struct imap_fetch_context *ctx, struct imap_fetch_body_data *body) { - const char *section = body->section; + const char *name, *section = body->section; + name = get_body_name(body); if (*section == '\0') { ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, body); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", + fetch_body, body); return TRUE; } if (strcmp(section, "TEXT") == 0) { ctx->fetch_data |= MAIL_FETCH_STREAM_BODY; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, body); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", + fetch_body, body); return TRUE; } @@ -633,7 +646,7 @@ /* exact header matches could be cached */ if (section[6] == '\0') { ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER; - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_body, body); return TRUE; } @@ -644,7 +657,7 @@ if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 && fetch_body_header_fields_check(section+18)) { - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_body_header_partial, body); return TRUE; } @@ -663,7 +676,7 @@ fetch_body_header_fields_check(section+14)) || (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 && fetch_body_header_fields_check(section+18))) { - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_body_mime, body); return TRUE; } @@ -927,26 +940,27 @@ ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY; ctx->flags_update_seen = TRUE; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_rfc822, NULL); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", + fetch_rfc822, NULL); return TRUE; } if (strcmp(name+6, ".SIZE") == 0) { ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE; - imap_fetch_add_handler(ctx, TRUE, FALSE, + imap_fetch_add_handler(ctx, TRUE, FALSE, name, "0", fetch_rfc822_size, NULL); return TRUE; } if (strcmp(name+6, ".HEADER") == 0) { ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER; - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_rfc822_header, NULL); return TRUE; } if (strcmp(name+6, ".TEXT") == 0) { ctx->fetch_data |= MAIL_FETCH_STREAM_BODY; ctx->flags_update_seen = TRUE; - imap_fetch_add_handler(ctx, FALSE, FALSE, + imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL", fetch_rfc822_text, NULL); return TRUE; }
--- a/src/imap/imap-fetch.c Thu Dec 28 20:37:25 2006 +0200 +++ b/src/imap/imap-fetch.c Thu Dec 28 20:40:29 2006 +0200 @@ -15,6 +15,9 @@ #include <stdlib.h> +#define BODY_NIL_REPLY \ + "\"text\" \"plain\" NIL NIL NIL \"7bit\" 0 0 NIL NIL NIL" + const struct imap_fetch_handler default_handlers[7]; static buffer_t *fetch_handlers = NULL; @@ -102,6 +105,7 @@ #undef imap_fetch_add_handler void imap_fetch_add_handler(struct imap_fetch_context *ctx, bool buffered, bool want_deinit, + const char *name, const char *nil_reply, imap_fetch_handler_t *handler, void *context) { /* partially because of broken clients, but also partially because @@ -134,6 +138,8 @@ h.context = context; h.buffered = buffered; h.want_deinit = want_deinit; + h.name = p_strdup(ctx->cmd->pool, name); + h.nil_reply = p_strdup(ctx->cmd->pool, nil_reply); if (!buffered) array_append(&ctx->handlers, &h, 1); @@ -183,8 +189,6 @@ const unsigned char *data; size_t len; - i_assert(ctx->first); - data = str_data(ctx->cur_str); len = str_len(ctx->cur_str); @@ -202,11 +206,29 @@ return 0; } +static int imap_fetch_send_nil_reply(struct imap_fetch_context *ctx) +{ + const struct imap_fetch_context_handler *handler; + + if (!ctx->first) + str_append_c(ctx->cur_str, ' '); + + handler = array_idx(&ctx->handlers, ctx->cur_handler); + str_printfa(ctx->cur_str, "%s %s ", + handler->name, handler->nil_reply); + + if (!handler->buffered) { + if (imap_fetch_flush_buffer(ctx) < 0) + return -1; + } + return 0; +} + int imap_fetch(struct imap_fetch_context *ctx) { struct client *client = ctx->client; const struct imap_fetch_context_handler *handlers; - unsigned int size; + unsigned int count; int ret; if (ctx->cont_handler != NULL) { @@ -215,10 +237,14 @@ return 0; if (ret < 0) { + if (ctx->client->output->closed) + return -1; + if (ctx->cur_mail->expunged) { /* not an error, just lost it. */ ctx->partial_fetch = TRUE; - ctx->partial_fetch = TRUE; + if (imap_fetch_send_nil_reply(ctx) < 0) + return -1; } else { return -1; } @@ -234,7 +260,7 @@ client->output_lock == ctx->cmd); client->output_lock = ctx->cmd; - handlers = array_get(&ctx->handlers, &size); + handlers = array_get(&ctx->handlers, &count); for (;;) { if (o_stream_get_buffer_used_size(client->output) >= CLIENT_OUTPUT_OPTIMAL_SIZE) { @@ -266,7 +292,7 @@ ctx->line_finished = FALSE; } - for (; ctx->cur_handler < size; ctx->cur_handler++) { + for (; ctx->cur_handler < count; ctx->cur_handler++) { if (str_len(ctx->cur_str) > 0 && !handlers[ctx->cur_handler].buffered) { /* first non-buffered handler. @@ -294,6 +320,8 @@ if (ctx->cur_mail->expunged) { /* not an error, just lost it. */ ctx->partial_fetch = TRUE; + if (imap_fetch_send_nil_reply(ctx) < 0) + return -1; } else { i_assert(ret < 0 || ctx->cont_handler != NULL); @@ -393,7 +421,8 @@ { if (name[4] == '\0') { ctx->fetch_data |= MAIL_FETCH_IMAP_BODY; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, NULL); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, + "("BODY_NIL_REPLY")", fetch_body, NULL); return TRUE; } return fetch_body_section_init(ctx, name, args); @@ -424,11 +453,13 @@ } static bool fetch_bodystructure_init(struct imap_fetch_context *ctx, - const char *name __attr_unused__, + const char *name, struct imap_arg **args __attr_unused__) { ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_bodystructure, NULL); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, + "("BODY_NIL_REPLY" NIL NIL NIL NIL)", + fetch_bodystructure, NULL); return TRUE; } @@ -456,11 +487,13 @@ } static bool fetch_envelope_init(struct imap_fetch_context *ctx, - const char *name __attr_unused__, + const char *name, struct imap_arg **args __attr_unused__) { ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE; - imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_envelope, NULL); + imap_fetch_add_handler(ctx, FALSE, FALSE, name, + "(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)", + fetch_envelope, NULL); return TRUE; } @@ -489,12 +522,12 @@ } static bool fetch_flags_init(struct imap_fetch_context *ctx, - const char *name __attr_unused__, + const char *name, struct imap_arg **args __attr_unused__) { ctx->flags_have_handler = TRUE; ctx->fetch_data |= MAIL_FETCH_FLAGS; - imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_flags, NULL); + imap_fetch_add_handler(ctx, TRUE, FALSE, name, "()", fetch_flags, NULL); return TRUE; } @@ -512,13 +545,14 @@ return 1; } - static bool fetch_internaldate_init(struct imap_fetch_context *ctx, - const char *name __attr_unused__, + const char *name, struct imap_arg **args __attr_unused__) { ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE; - imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_internaldate, NULL); + imap_fetch_add_handler(ctx, TRUE, FALSE, name, + "\"01-01-1970 00:00:00 +0000\"", + fetch_internaldate, NULL); return TRUE; } @@ -530,10 +564,10 @@ } static bool fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__, - const char *name __attr_unused__, + const char *name, struct imap_arg **args __attr_unused__) { - imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_uid, NULL); + imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL, fetch_uid, NULL); return TRUE; }
--- a/src/imap/imap-fetch.h Thu Dec 28 20:37:25 2006 +0200 +++ b/src/imap/imap-fetch.h Thu Dec 28 20:40:29 2006 +0200 @@ -20,6 +20,9 @@ imap_fetch_handler_t *handler; void *context; + const char *name; + const char *nil_reply; + unsigned int buffered:1; unsigned int want_deinit:1; }; @@ -68,16 +71,19 @@ void imap_fetch_add_handler(struct imap_fetch_context *ctx, bool buffered, bool want_deinit, + const char *name, const char *nil_reply, imap_fetch_handler_t *handler, void *context); #ifdef CONTEXT_TYPE_SAFETY -# define imap_fetch_add_handler(ctx, buffered, want_deinit, handler, context) \ +# define imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \ + handler, context) \ ({(void)(1 ? 0 : handler((struct imap_fetch_context *)NULL, \ (struct mail *)NULL, context)); \ - imap_fetch_add_handler(ctx, buffered, want_deinit, \ + imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \ (imap_fetch_handler_t *)handler, context); }) #else -# define imap_fetch_add_handler(ctx, buffered, want_deinit, handler, context) \ - imap_fetch_add_handler(ctx, buffered, want_deinit, \ +# define imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \ + handler, context) \ + imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \ (imap_fetch_handler_t *)handler, context) #endif