Mercurial > dovecot > core-2.2
changeset 14887:0c73a42c194e
imap: FETCH API cleanup: keep fetch state in a separate struct.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 13 Aug 2012 01:47:54 +0300 |
parents | 42cc4c4c4891 |
children | cf79ab812651 |
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, 175 insertions(+), 161 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-fetch.c Mon Aug 13 01:25:12 2012 +0300 +++ b/src/imap/cmd-fetch.c Mon Aug 13 01:47:54 2012 +0300 @@ -144,19 +144,20 @@ static const char *ok_message = "OK Fetch completed."; const char *tagged_reply = ok_message; enum mail_error error; + bool seen_flags_changed = ctx->state.seen_flags_changed; - if (ctx->skipped_expunged_msgs) { + if (ctx->state.skipped_expunged_msgs) { tagged_reply = "OK ["IMAP_RESP_CODE_EXPUNGEISSUED"] " "Some messages were already expunged."; } if (imap_fetch_deinit(ctx) < 0) - ctx->failed = TRUE; + ctx->state.failed = TRUE; - if (ctx->failed) { + if (ctx->state.failed) { const char *errstr; - if (ctx->client->output->closed) { + if (cmd->client->output->closed) { client_disconnect(cmd->client, "Disconnected"); return TRUE; } @@ -175,7 +176,7 @@ } return cmd_sync(cmd, - (ctx->seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) | + (seen_flags_changed ? 0 : MAILBOX_SYNC_FLAG_FAST) | (cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES), 0, tagged_reply); }
--- a/src/imap/imap-fetch-body.c Mon Aug 13 01:25:12 2012 +0300 +++ b/src/imap/imap-fetch-body.c Mon Aug 13 01:47:54 2012 +0300 @@ -30,11 +30,13 @@ static void fetch_read_error(struct imap_fetch_context *ctx) { - errno = ctx->cur_input->stream_errno; + struct imap_fetch_state *state = &ctx->state; + + errno = state->cur_input->stream_errno; mail_storage_set_critical(ctx->box->storage, "read(%s) failed: %m (FETCH for mailbox %s UID %u)", - i_stream_get_name(ctx->cur_input), - mailbox_get_vname(ctx->cur_mail->box), ctx->cur_mail->uid); + i_stream_get_name(state->cur_input), + mailbox_get_vname(state->cur_mail->box), state->cur_mail->uid); } static const char *get_body_name(const struct imap_fetch_body_data *body) @@ -63,8 +65,8 @@ string_t *str; str = t_str_new(128); - if (ctx->first) - ctx->first = FALSE; + if (ctx->state.cur_first) + ctx->state.cur_first = FALSE; else str_append_c(str, ' '); @@ -81,31 +83,34 @@ static int fetch_stream_continue(struct imap_fetch_context *ctx) { + struct imap_fetch_state *state = &ctx->state; off_t ret; o_stream_set_max_buffer_size(ctx->client->output, 0); - ret = o_stream_send_istream(ctx->client->output, ctx->cur_input); + ret = o_stream_send_istream(ctx->client->output, state->cur_input); o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1); if (ret > 0) - ctx->cur_offset += ret; + state->cur_offset += ret; - if (ctx->cur_offset != ctx->cur_size) { + if (state->cur_offset != state->cur_size) { /* unfinished */ - if (ctx->cur_input->stream_errno != 0) { + if (state->cur_input->stream_errno != 0) { fetch_read_error(ctx); client_disconnect(ctx->client, "FETCH failed"); return -1; } - if (!i_stream_have_bytes_left(ctx->cur_input)) { + if (!i_stream_have_bytes_left(state->cur_input)) { /* Input stream gave less data than expected */ i_error("FETCH %s for mailbox %s UID %u " "got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, - ctx->cur_name, mailbox_get_vname(ctx->cur_mail->box), - ctx->cur_mail->uid, ctx->cur_offset, ctx->cur_size); - mail_set_cache_corrupted(ctx->cur_mail, - ctx->cur_size_field); + state->cur_human_name, + mailbox_get_vname(state->cur_mail->box), + state->cur_mail->uid, + state->cur_offset, state->cur_size); + mail_set_cache_corrupted(state->cur_mail, + state->cur_size_field); client_disconnect(ctx->client, "FETCH failed"); return -1; } @@ -128,17 +133,18 @@ if (imap_msgpart_open(mail, body->msgpart, &result) < 0) return -1; - ctx->cur_input = result.input; - ctx->cur_size = result.size; - ctx->cur_size_field = result.size_field; - ctx->cur_name = p_strconcat(ctx->pool, "[", body->section, "]", NULL); + ctx->state.cur_input = result.input; + ctx->state.cur_size = result.size; + ctx->state.cur_size_field = result.size_field; + ctx->state.cur_human_name = + p_strconcat(ctx->pool, "[", body->section, "]", NULL); - str = get_prefix(ctx, body, ctx->cur_size, + str = get_prefix(ctx, body, ctx->state.cur_size, result.binary_decoded_input_has_nuls); o_stream_nsend(ctx->client->output, str_data(str), str_len(str)); - ctx->cont_handler = fetch_stream_continue; - return ctx->cont_handler(ctx); + ctx->state.cont_handler = fetch_stream_continue; + return ctx->state.cont_handler(ctx); } static int fetch_binary_size(struct imap_fetch_context *ctx, struct mail *mail, @@ -151,8 +157,8 @@ return -1; str = t_str_new(128); - if (ctx->first) - ctx->first = FALSE; + if (ctx->state.cur_first) + ctx->state.cur_first = FALSE; else str_append_c(str, ' '); str_printfa(str, "%s %"PRIuUOFF_T, get_body_name(body), size); @@ -412,7 +418,7 @@ if (mail_get_virtual_size(mail, &size) < 0) return -1; - str_printfa(ctx->cur_str, "RFC822.SIZE %"PRIuUOFF_T" ", size); + str_printfa(ctx->state.cur_str, "RFC822.SIZE %"PRIuUOFF_T" ", size); return 1; } @@ -427,10 +433,10 @@ imap_msgpart_free(_msgpart); if (ret < 0) return -1; - ctx->cur_input = result.input; - ctx->cur_size = result.size; - ctx->cur_size_field = result.size_field; - ctx->cont_handler = fetch_stream_continue; + ctx->state.cur_input = result.input; + ctx->state.cur_size = result.size; + ctx->state.cur_size_field = result.size_field; + ctx->state.cont_handler = fetch_stream_continue; return 0; } @@ -445,14 +451,15 @@ if (fetch_and_free_msgpart(ctx, mail, &msgpart) < 0) return -1; - str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n", ctx->cur_size); - if (ctx->first) { - str++; ctx->first = FALSE; + str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n", + ctx->state.cur_size); + if (ctx->state.cur_first) { + str++; ctx->state.cur_first = FALSE; } o_stream_nsend_str(ctx->client->output, str); - ctx->cur_name = "RFC822"; - return ctx->cont_handler(ctx); + ctx->state.cur_human_name = "RFC822"; + return ctx->state.cont_handler(ctx); } static int ATTR_NULL(3) @@ -467,14 +474,14 @@ return -1; str = t_strdup_printf(" RFC822.HEADER {%"PRIuUOFF_T"}\r\n", - ctx->cur_size); - if (ctx->first) { - str++; ctx->first = FALSE; + ctx->state.cur_size); + if (ctx->state.cur_first) { + str++; ctx->state.cur_first = FALSE; } o_stream_nsend_str(ctx->client->output, str); - ctx->cur_name = "RFC822.HEADER"; - return ctx->cont_handler(ctx); + ctx->state.cur_human_name = "RFC822.HEADER"; + return ctx->state.cont_handler(ctx); } static int ATTR_NULL(3) @@ -489,14 +496,14 @@ return -1; str = t_strdup_printf(" RFC822.TEXT {%"PRIuUOFF_T"}\r\n", - ctx->cur_size); - if (ctx->first) { - str++; ctx->first = FALSE; + ctx->state.cur_size); + if (ctx->state.cur_first) { + str++; ctx->state.cur_first = FALSE; } o_stream_nsend_str(ctx->client->output, str); - ctx->cur_name = "RFC822.TEXT"; - return ctx->cont_handler(ctx); + ctx->state.cur_human_name = "RFC822.TEXT"; + return ctx->state.cont_handler(ctx); } bool imap_fetch_rfc822_init(struct imap_fetch_init_context *ctx)
--- a/src/imap/imap-fetch.c Mon Aug 13 01:25:12 2012 +0300 +++ b/src/imap/imap-fetch.c Mon Aug 13 01:47:54 2012 +0300 @@ -105,12 +105,12 @@ ctx->pool = cmd->pool; ctx->box = box; - ctx->cur_str = str_new(default_pool, 8192); + ctx->state.cur_str = str_new(default_pool, 8192); p_array_init(&ctx->all_headers, cmd->pool, 64); p_array_init(&ctx->handlers, cmd->pool, 16); p_array_init(&ctx->tmp_keywords, cmd->pool, client->keywords.announce_count + 8); - ctx->line_finished = TRUE; + ctx->state.line_finished = TRUE; return ctx; } @@ -140,8 +140,8 @@ /* partially because of broken clients, but also partially because it potentially can make client implementations faster, we have a buffered parameter which basically means that the handler promises - to write the output in fetch_ctx->cur_str. The cur_str is then sent - to client before calling any non-buffered handlers. + to write the output in fetch_ctx->state.cur_str. The cur_str is then + sent to client before calling any non-buffered handlers. We try to keep the handler registration order the same as the client requested them. This is especially useful to get UID @@ -327,11 +327,12 @@ int imap_fetch_begin(struct imap_fetch_context *ctx) { + struct mailbox_header_lookup_ctx *wanted_headers = NULL; const void *data; if (ctx->send_vanished) { if (imap_fetch_send_vanished(ctx) < 0) { - ctx->failed = TRUE; + ctx->state.failed = TRUE; return -1; } } @@ -351,24 +352,25 @@ array_append_zero(&ctx->all_headers); data = array_idx(&ctx->all_headers, 0); - ctx->all_headers_ctx = - mailbox_header_lookup_init(ctx->box, data); + wanted_headers = mailbox_header_lookup_init(ctx->box, data); } if ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0) ctx->fetch_data |= MAIL_FETCH_NUL_STATE; - ctx->trans = mailbox_transaction_begin(ctx->box, + ctx->state.trans = mailbox_transaction_begin(ctx->box, MAILBOX_TRANSACTION_FLAG_HIDE | MAILBOX_TRANSACTION_FLAG_REFRESH); /* Delayed uidset -> seqset conversion. VANISHED needs the uidset. */ mail_search_args_init(ctx->search_args, ctx->box, TRUE, &ctx->client->search_saved_uidset); - ctx->search_ctx = - mailbox_search_init(ctx->trans, ctx->search_args, NULL, - ctx->fetch_data, ctx->all_headers_ctx); + ctx->state.search_ctx = + mailbox_search_init(ctx->state.trans, ctx->search_args, NULL, + ctx->fetch_data, wanted_headers); + if (wanted_headers != NULL) + mailbox_header_lookup_unref(&wanted_headers); return 0; } @@ -377,8 +379,8 @@ const unsigned char *data; size_t len; - data = str_data(ctx->cur_str); - len = str_len(ctx->cur_str); + data = str_data(ctx->state.cur_str); + len = str_len(ctx->state.cur_str); if (len == 0) return 0; @@ -387,13 +389,13 @@ to buffer */ if (data[len-1] == ' ') { len--; - ctx->first = FALSE; + ctx->state.cur_first = FALSE; } if (o_stream_send(ctx->client->output, data, len) < 0) return -1; - str_truncate(ctx->cur_str, 0); + str_truncate(ctx->state.cur_str, 0); return 0; } @@ -401,11 +403,11 @@ { const struct imap_fetch_context_handler *handler; - if (!ctx->first) - str_append_c(ctx->cur_str, ' '); + if (!ctx->state.cur_first) + str_append_c(ctx->state.cur_str, ' '); - handler = array_idx(&ctx->handlers, ctx->cur_handler); - str_printfa(ctx->cur_str, "%s %s ", + handler = array_idx(&ctx->handlers, ctx->state.cur_handler); + str_printfa(ctx->state.cur_str, "%s %s ", handler->name, handler->nil_reply); if (!handler->buffered) { @@ -418,13 +420,14 @@ static int imap_fetch_more_int(struct imap_fetch_context *ctx, struct client_command_context *cmd) { + struct imap_fetch_state *state = &ctx->state; struct client *client = ctx->client; const struct imap_fetch_context_handler *handlers; unsigned int count; int ret; - if (ctx->cont_handler != NULL) { - ret = ctx->cont_handler(ctx); + if (state->cont_handler != NULL) { + ret = state->cont_handler(ctx); if (ret == 0) return 0; @@ -432,9 +435,9 @@ if (client->output->closed) return -1; - if (ctx->cur_mail->expunged) { + if (state->cur_mail->expunged) { /* not an error, just lost it. */ - ctx->skipped_expunged_msgs = TRUE; + state->skipped_expunged_msgs = TRUE; if (imap_fetch_send_nil_reply(ctx) < 0) return -1; } else { @@ -442,11 +445,11 @@ } } - ctx->cont_handler = NULL; - ctx->cur_offset = 0; - ctx->cur_handler++; - if (ctx->cur_input != NULL) - i_stream_unref(&ctx->cur_input); + state->cont_handler = NULL; + state->cur_offset = 0; + state->cur_handler++; + if (state->cur_input != NULL) + i_stream_unref(&state->cur_input); } handlers = array_get(&ctx->handlers, &count); @@ -458,36 +461,36 @@ return ret; } - if (ctx->cur_mail == NULL) { + if (state->cur_mail == NULL) { if (cmd->cancel) return 1; - if (!mailbox_search_next(ctx->search_ctx, - &ctx->cur_mail)) + if (!mailbox_search_next(state->search_ctx, + &state->cur_mail)) break; - str_printfa(ctx->cur_str, "* %u FETCH (", - ctx->cur_mail->seq); - ctx->first = TRUE; - ctx->line_finished = FALSE; + str_printfa(state->cur_str, "* %u FETCH (", + state->cur_mail->seq); + state->cur_first = TRUE; + state->line_finished = FALSE; } - for (; ctx->cur_handler < count; ctx->cur_handler++) { - if (str_len(ctx->cur_str) > 0 && - !handlers[ctx->cur_handler].buffered) { + for (; state->cur_handler < count; state->cur_handler++) { + if (str_len(state->cur_str) > 0 && + !handlers[state->cur_handler].buffered) { /* first non-buffered handler. flush the buffer. */ - ctx->line_partial = TRUE; + state->line_partial = TRUE; if (imap_fetch_flush_buffer(ctx) < 0) return -1; } - i_assert(ctx->cur_input == NULL); + i_assert(state->cur_input == NULL); T_BEGIN { const struct imap_fetch_context_handler *h = - &handlers[ctx->cur_handler]; + &handlers[state->cur_handler]; - ret = h->handler(ctx, ctx->cur_mail, + ret = h->handler(ctx, state->cur_mail, h->context); } T_END; @@ -495,37 +498,37 @@ return 0; if (ret < 0) { - if (ctx->cur_mail->expunged) { + if (state->cur_mail->expunged) { /* not an error, just lost it. */ - ctx->skipped_expunged_msgs = TRUE; + state->skipped_expunged_msgs = TRUE; if (imap_fetch_send_nil_reply(ctx) < 0) return -1; } else { i_assert(ret < 0 || - ctx->cont_handler != NULL); + state->cont_handler != NULL); return -1; } } - ctx->cont_handler = NULL; - ctx->cur_offset = 0; - if (ctx->cur_input != NULL) - i_stream_unref(&ctx->cur_input); + state->cont_handler = NULL; + state->cur_offset = 0; + if (state->cur_input != NULL) + i_stream_unref(&state->cur_input); } - if (str_len(ctx->cur_str) > 0) { + if (str_len(state->cur_str) > 0) { /* no non-buffered handlers */ if (imap_fetch_flush_buffer(ctx) < 0) return -1; } - ctx->line_finished = TRUE; - ctx->line_partial = FALSE; + state->line_finished = TRUE; + state->line_partial = FALSE; o_stream_nsend(client->output, ")\r\n", 3); client->last_output = ioloop_time; - ctx->cur_mail = NULL; - ctx->cur_handler = 0; + state->cur_mail = NULL; + state->cur_handler = 0; } return 1; @@ -541,8 +544,8 @@ ret = imap_fetch_more_int(ctx, cmd); if (ret < 0) - ctx->failed = TRUE; - if (ctx->line_partial) { + ctx->state.failed = TRUE; + if (ctx->state.line_partial) { /* nothing can be sent until FETCH is finished */ ctx->client->output_lock = cmd; } @@ -551,6 +554,7 @@ int imap_fetch_deinit(struct imap_fetch_context *ctx) { + struct imap_fetch_state *state = &ctx->state; const struct imap_fetch_context_handler *handler; array_foreach(&ctx->handlers, handler) { @@ -558,33 +562,30 @@ handler->handler(ctx, NULL, handler->context); } - if (!ctx->line_finished) { + if (!state->line_finished) { if (imap_fetch_flush_buffer(ctx) < 0) - ctx->failed = TRUE; + state->failed = TRUE; if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0) - ctx->failed = TRUE; + state->failed = TRUE; } - str_free(&ctx->cur_str); + str_free(&state->cur_str); - if (ctx->cur_input != NULL) - i_stream_unref(&ctx->cur_input); + if (state->cur_input != NULL) + i_stream_unref(&state->cur_input); - mail_search_args_unref(&ctx->search_args); - if (ctx->search_ctx != NULL) { - if (mailbox_search_deinit(&ctx->search_ctx) < 0) - ctx->failed = TRUE; + if (state->search_ctx != NULL) { + if (mailbox_search_deinit(&state->search_ctx) < 0) + state->failed = TRUE; } - if (ctx->all_headers_ctx != NULL) - mailbox_header_lookup_unref(&ctx->all_headers_ctx); - if (ctx->trans != NULL) { + if (state->trans != NULL) { /* even if something failed, we want to commit changes to cache, as well as possible \Seen flag changes for FETCH replies we returned so far. */ - if (mailbox_transaction_commit(&ctx->trans) < 0) - ctx->failed = TRUE; + if (mailbox_transaction_commit(&state->trans) < 0) + state->failed = TRUE; } - return ctx->failed ? -1 : 0; + return state->failed ? -1 : 0; } static int fetch_body(struct imap_fetch_context *ctx, struct mail *mail, @@ -595,8 +596,8 @@ if (mail_get_special(mail, MAIL_FETCH_IMAP_BODY, &body) < 0) return -1; - if (ctx->first) - ctx->first = FALSE; + if (ctx->state.cur_first) + ctx->state.cur_first = FALSE; else { if (o_stream_send(ctx->client->output, " ", 1) < 0) return -1; @@ -629,8 +630,8 @@ &bodystructure) < 0) return -1; - if (ctx->first) - ctx->first = FALSE; + if (ctx->state.cur_first) + ctx->state.cur_first = FALSE; else { if (o_stream_send(ctx->client->output, " ", 1) < 0) return -1; @@ -660,8 +661,8 @@ if (mail_get_special(mail, MAIL_FETCH_IMAP_ENVELOPE, &envelope) < 0) return -1; - if (ctx->first) - ctx->first = FALSE; + if (ctx->state.cur_first) + ctx->state.cur_first = FALSE; else { if (o_stream_send(ctx->client->output, " ", 1) < 0) return -1; @@ -691,7 +692,7 @@ flags = mail_get_flags(mail); if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0) { /* Add \Seen flag */ - ctx->seen_flags_changed = TRUE; + ctx->state.seen_flags_changed = TRUE; flags |= MAIL_SEEN; mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN); } else if (ctx->flags_show_only_seen_changes) { @@ -701,9 +702,9 @@ keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords, mail_get_keyword_indexes(mail)); - str_append(ctx->cur_str, "FLAGS ("); - imap_write_flags(ctx->cur_str, flags, keywords); - str_append(ctx->cur_str, ") "); + str_append(ctx->state.cur_str, "FLAGS ("); + imap_write_flags(ctx->state.cur_str, flags, keywords); + str_append(ctx->state.cur_str, ") "); return 1; } @@ -724,7 +725,7 @@ if (mail_get_received_date(mail, &date) < 0) return -1; - str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ", + str_printfa(ctx->state.cur_str, "INTERNALDATE \"%s\" ", imap_to_datetime(date)); return 1; } @@ -746,7 +747,7 @@ modseq = mail_get_modseq(mail); if (ctx->client->highest_fetch_modseq < modseq) ctx->client->highest_fetch_modseq = modseq; - str_printfa(ctx->cur_str, "MODSEQ (%llu) ", + str_printfa(ctx->state.cur_str, "MODSEQ (%llu) ", (unsigned long long)modseq); return 1; } @@ -762,7 +763,7 @@ static int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail, void *context ATTR_UNUSED) { - str_printfa(ctx->cur_str, "UID %u ", mail->uid); + str_printfa(ctx->state.cur_str, "UID %u ", mail->uid); return 1; } @@ -781,9 +782,9 @@ if (mail_get_special(mail, MAIL_FETCH_GUID, &value) < 0) return -1; - str_append(ctx->cur_str, "X-GUID "); - imap_quote_append_string(ctx->cur_str, value, FALSE); - str_append_c(ctx->cur_str, ' '); + str_append(ctx->state.cur_str, "X-GUID "); + imap_quote_append_string(ctx->state.cur_str, value, FALSE); + str_append_c(ctx->state.cur_str, ' '); return 1; } @@ -808,9 +809,9 @@ if (imap_utf8_to_utf7(name, mutf7_name) < 0) i_panic("FETCH: Mailbox name not UTF-8: %s", name); - str_append(ctx->cur_str, "X-MAILBOX "); - imap_quote_append_string(ctx->cur_str, str_c(mutf7_name), FALSE); - str_append_c(ctx->cur_str, ' '); + str_append(ctx->state.cur_str, "X-MAILBOX "); + imap_quote_append_string(ctx->state.cur_str, str_c(mutf7_name), FALSE); + str_append_c(ctx->state.cur_str, ' '); return 1; } @@ -824,7 +825,7 @@ static int fetch_x_real_uid(struct imap_fetch_context *ctx, struct mail *mail, void *context ATTR_UNUSED) { - str_printfa(ctx->cur_str, "X-REAL-UID %u ", + str_printfa(ctx->state.cur_str, "X-REAL-UID %u ", mail_get_real_mail(mail)->uid); return 1; } @@ -844,7 +845,7 @@ if (mail_get_save_date(mail, &date) < 0) return -1; - str_printfa(ctx->cur_str, "X-SAVEDATE \"%s\" ", + str_printfa(ctx->state.cur_str, "X-SAVEDATE \"%s\" ", imap_to_datetime(date)); return 1; }
--- a/src/imap/imap-fetch.h Mon Aug 13 01:25:12 2012 +0300 +++ b/src/imap/imap-fetch.h Mon Aug 13 01:47:54 2012 +0300 @@ -39,25 +39,13 @@ unsigned int want_deinit:1; }; -struct imap_fetch_context { - struct client *client; - struct mailbox *box; - pool_t pool; - +struct imap_fetch_state { struct mailbox_transaction_context *trans; - struct mail_search_args *search_args; struct mail_search_context *search_ctx; - enum mail_fetch_field fetch_data; - ARRAY_TYPE(const_string) all_headers; - struct mailbox_header_lookup_ctx *all_headers_ctx; - - ARRAY_DEFINE(handlers, struct imap_fetch_context_handler); - unsigned int buffered_handlers_count; - struct mail *cur_mail; unsigned int cur_handler; - const char *cur_name; + const char *cur_human_name; uoff_t cur_size, cur_offset; enum mail_fetch_field cur_size_field; string_t *cur_str; @@ -65,21 +53,38 @@ bool skip_cr; int (*cont_handler)(struct imap_fetch_context *ctx); + unsigned int seen_flags_changed:1; + unsigned int cur_first:1; + unsigned int line_partial:1; + unsigned int line_finished:1; + unsigned int skipped_expunged_msgs:1; + unsigned int failed:1; +}; + +struct imap_fetch_context { + struct client *client; + struct mailbox *box; + pool_t pool; + + struct mail_search_args *search_args; + + enum mail_fetch_field fetch_data; + ARRAY_TYPE(const_string) all_headers; + + ARRAY_DEFINE(handlers, struct imap_fetch_context_handler); + unsigned int buffered_handlers_count; + const ARRAY_TYPE(uint32_t) *qresync_sample_seqset; const ARRAY_TYPE(uint32_t) *qresync_sample_uidset; ARRAY_TYPE(keywords) tmp_keywords; + struct imap_fetch_state state; + unsigned int flags_have_handler:1; unsigned int flags_update_seen:1; - unsigned int seen_flags_changed:1; unsigned int flags_show_only_seen_changes:1; - unsigned int first:1; - unsigned int line_partial:1; - unsigned int line_finished:1; - unsigned int skipped_expunged_msgs:1; unsigned int send_vanished:1; - unsigned int failed:1; }; void imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,