45
44
return strcmp(name, h->name);
48
bool imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *name,
49
const struct imap_arg **args)
47
bool imap_fetch_init_handler(struct imap_fetch_init_context *init_ctx)
51
49
const struct imap_fetch_handler *handler;
52
50
const char *lookup_name, *p;
54
for (p = name; i_isalnum(*p) || *p == '-'; p++) ;
55
lookup_name = t_strdup_until(name, p);
52
for (p = init_ctx->name; i_isalnum(*p) || *p == '-'; p++) ;
53
lookup_name = t_strdup_until(init_ctx->name, p);
57
55
handler = array_bsearch(&fetch_handlers, lookup_name,
58
56
imap_fetch_handler_bsearch);
59
57
if (handler == NULL) {
60
client_send_command_error(ctx->cmd,
61
t_strconcat("Unknown parameter ", name, NULL));
65
return handler->init(ctx, name, args);
58
init_ctx->error = t_strdup_printf("Unknown parameter: %s",
62
if (!handler->init(init_ctx)) {
63
i_assert(init_ctx->error != NULL);
69
void imap_fetch_init_nofail_handler(struct imap_fetch_context *ctx,
70
bool (*init)(struct imap_fetch_init_context *))
72
struct imap_fetch_init_context init_ctx;
74
memset(&init_ctx, 0, sizeof(init_ctx));
75
init_ctx.fetch_ctx = ctx;
76
init_ctx.pool = ctx->ctx_pool;
82
int imap_fetch_att_list_parse(struct client *client, pool_t pool,
83
const struct imap_arg *list,
84
struct imap_fetch_context **fetch_ctx_r,
87
struct imap_fetch_init_context init_ctx;
90
memset(&init_ctx, 0, sizeof(init_ctx));
91
init_ctx.fetch_ctx = imap_fetch_alloc(client, pool);
95
while (imap_arg_get_atom(init_ctx.args, &str)) {
96
init_ctx.name = t_str_ucase(str);
98
if (!imap_fetch_init_handler(&init_ctx)) {
99
*error_r = t_strconcat("Invalid fetch-att list: ",
100
init_ctx.error, NULL);
101
imap_fetch_free(&init_ctx.fetch_ctx);
105
if (!IMAP_ARG_IS_EOL(init_ctx.args)) {
106
*error_r = "fetch-att list contains non-atoms.";
107
imap_fetch_free(&init_ctx.fetch_ctx);
110
*fetch_ctx_r = init_ctx.fetch_ctx;
68
114
struct imap_fetch_context *
69
imap_fetch_init(struct client_command_context *cmd, struct mailbox *box)
115
imap_fetch_alloc(struct client *client, pool_t pool)
71
struct client *client = cmd->client;
72
117
struct imap_fetch_context *ctx;
74
ctx = p_new(cmd->pool, struct imap_fetch_context, 1);
119
ctx = p_new(pool, struct imap_fetch_context, 1);
75
120
ctx->client = client;
121
ctx->ctx_pool = pool;
79
ctx->cur_str = str_new(default_pool, 8192);
80
p_array_init(&ctx->all_headers, cmd->pool, 64);
81
p_array_init(&ctx->handlers, cmd->pool, 16);
82
p_array_init(&ctx->tmp_keywords, cmd->pool,
124
p_array_init(&ctx->all_headers, pool, 64);
125
p_array_init(&ctx->handlers, pool, 16);
126
p_array_init(&ctx->tmp_keywords, pool,
83
127
client->keywords.announce_count + 8);
84
ctx->line_finished = TRUE;
88
bool imap_fetch_add_changed_since(struct imap_fetch_context *ctx,
91
struct mail_search_arg *search_arg;
93
search_arg = p_new(ctx->search_args->pool, struct mail_search_arg, 1);
94
search_arg->type = SEARCH_MODSEQ;
95
search_arg->value.modseq =
96
p_new(ctx->cmd->pool, struct mail_search_modseq, 1);
97
search_arg->value.modseq->modseq = modseq + 1;
99
search_arg->next = ctx->search_args->args->next;
100
ctx->search_args->args->next = search_arg;
102
return imap_fetch_init_handler(ctx, "MODSEQ", NULL);
105
131
#undef imap_fetch_add_handler
106
void imap_fetch_add_handler(struct imap_fetch_context *ctx,
107
bool buffered, bool want_deinit,
108
const char *name, const char *nil_reply,
132
void imap_fetch_add_handler(struct imap_fetch_init_context *ctx,
133
enum imap_fetch_handler_flags flags,
134
const char *nil_reply,
109
135
imap_fetch_handler_t *handler, void *context)
111
137
/* partially because of broken clients, but also partially because
112
138
it potentially can make client implementations faster, we have a
113
139
buffered parameter which basically means that the handler promises
114
to write the output in ctx->cur_str. The cur_str is then sent to
115
client before calling any non-buffered handlers.
140
to write the output in fetch_ctx->state.cur_str. The cur_str is then
141
sent to client before calling any non-buffered handlers.
117
143
We try to keep the handler registration order the same as the
118
144
client requested them. This is especially useful to get UID
133
159
memset(&h, 0, sizeof(h));
134
160
h.handler = handler;
135
161
h.context = context;
136
h.buffered = buffered;
137
h.want_deinit = want_deinit;
138
h.name = p_strdup(ctx->cmd->pool, name);
139
h.nil_reply = p_strdup(ctx->cmd->pool, nil_reply);
162
h.buffered = (flags & IMAP_FETCH_HANDLER_FLAG_BUFFERED) != 0;
163
h.want_deinit = (flags & IMAP_FETCH_HANDLER_FLAG_WANT_DEINIT) != 0;
164
h.name = p_strdup(ctx->pool, ctx->name);
165
h.nil_reply = p_strdup(ctx->pool, nil_reply);
142
array_append(&ctx->handlers, &h, 1);
168
array_append(&ctx->fetch_ctx->handlers, &h, 1);
144
array_insert(&ctx->handlers, ctx->buffered_handlers_count,
146
ctx->buffered_handlers_count++;
170
array_insert(&ctx->fetch_ctx->handlers,
171
ctx->fetch_ctx->buffered_handlers_count, &h, 1);
172
ctx->fetch_ctx->buffered_handlers_count++;
151
expunges_drop_known(struct imap_fetch_context *ctx,
177
expunges_drop_known(struct mailbox *box,
178
const struct imap_fetch_qresync_args *qresync_args,
152
179
struct mailbox_transaction_context *trans,
153
180
ARRAY_TYPE(seq_range) *expunged_uids)
249
278
uid_filter[i].seq2);
252
mailbox_get_open_status(ctx->box, STATUS_UIDNEXT, &status);
281
mailbox_get_open_status(box, STATUS_UIDNEXT, &status);
253
282
seq_range_array_remove_range(expunged_uids, status.uidnext,
256
285
if (mailbox_search_deinit(&search_ctx) < 0)
259
if (ret == 0 && ctx->qresync_sample_seqset != NULL &&
260
array_is_created(ctx->qresync_sample_seqset))
261
expunges_drop_known(ctx, trans, expunged_uids);
288
if (ret == 0 && qresync_args->qresync_sample_seqset != NULL &&
289
array_is_created(qresync_args->qresync_sample_seqset))
290
expunges_drop_known(box, qresync_args, trans, expunged_uids);
263
292
(void)mailbox_transaction_commit(&trans);
268
imap_fetch_send_vanished(struct imap_fetch_context *ctx)
296
int imap_fetch_send_vanished(struct client *client, struct mailbox *box,
297
const struct mail_search_args *search_args,
298
const struct imap_fetch_qresync_args *qresync_args)
270
const struct mail_search_arg *uidarg = ctx->search_args->args;
300
const struct mail_search_arg *uidarg = search_args->args;
271
301
const struct mail_search_arg *modseqarg = uidarg->next;
272
const ARRAY_TYPE(seq_range) *uid_filter = &uidarg->value.seqset;
273
uint64_t modseq = modseqarg->value.modseq->modseq - 1;
302
const ARRAY_TYPE(seq_range) *uid_filter;
274
304
ARRAY_TYPE(seq_range) expunged_uids_range;
308
i_assert(uidarg->type == SEARCH_UIDSET);
309
i_assert(modseqarg->type == SEARCH_MODSEQ);
311
uid_filter = &uidarg->value.seqset;
312
modseq = modseqarg->value.modseq->modseq - 1;
278
314
i_array_init(&expunged_uids_range, array_count(uid_filter));
279
if (!mailbox_get_expunged_uids(ctx->box, modseq, uid_filter, &expunged_uids_range)) {
315
if (!mailbox_get_expunged_uids(box, modseq, uid_filter, &expunged_uids_range)) {
280
316
/* return all expunged UIDs */
281
if (get_expunges_fallback(ctx, uid_filter,
317
if (get_expunges_fallback(box, qresync_args, uid_filter,
282
318
&expunged_uids_range) < 0) {
283
319
array_clear(&expunged_uids_range);
289
325
str_append(str, "* VANISHED (EARLIER) ");
290
326
imap_write_seq_range(str, &expunged_uids_range);
291
327
str_append(str, "\r\n");
292
o_stream_send(ctx->client->output, str_data(str), str_len(str));
328
o_stream_nsend(client->output, str_data(str), str_len(str));
295
331
array_free(&expunged_uids_range);
299
int imap_fetch_begin(struct imap_fetch_context *ctx)
303
if (ctx->send_vanished) {
304
if (imap_fetch_send_vanished(ctx) < 0) {
310
if (ctx->flags_update_seen) {
311
if (mailbox_is_readonly(ctx->box))
312
ctx->flags_update_seen = FALSE;
313
else if (!ctx->flags_have_handler) {
314
ctx->flags_show_only_seen_changes = TRUE;
315
(void)imap_fetch_init_handler(ctx, "FLAGS", NULL);
335
static void imap_fetch_init(struct imap_fetch_context *ctx)
337
if (ctx->initialized)
339
ctx->initialized = TRUE;
341
if (ctx->flags_update_seen && !ctx->flags_have_handler) {
342
ctx->flags_show_only_seen_changes = TRUE;
343
imap_fetch_init_nofail_handler(ctx, imap_fetch_flags_init);
345
if ((ctx->fetch_data &
346
(MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0)
347
ctx->fetch_data |= MAIL_FETCH_NUL_STATE;
350
void imap_fetch_begin(struct imap_fetch_context *ctx, struct mailbox *box,
351
struct mail_search_args *search_args)
353
struct mailbox_header_lookup_ctx *wanted_headers = NULL;
354
const char *const *headers;
356
i_assert(!ctx->state.fetching);
358
imap_fetch_init(ctx);
359
memset(&ctx->state, 0, sizeof(ctx->state));
319
361
if (array_count(&ctx->all_headers) > 0 &&
320
362
((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
321
363
MAIL_FETCH_STREAM_BODY)) == 0)) {
322
(void)array_append_space(&ctx->all_headers);
364
array_append_zero(&ctx->all_headers);
324
data = array_idx(&ctx->all_headers, 0);
325
ctx->all_headers_ctx =
326
mailbox_header_lookup_init(ctx->box, data);
366
headers = array_idx(&ctx->all_headers, 0);
367
wanted_headers = mailbox_header_lookup_init(box, headers);
368
array_delete(&ctx->all_headers,
369
array_count(&ctx->all_headers)-1, 1);
329
if ((ctx->fetch_data &
330
(MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0)
331
ctx->fetch_data |= MAIL_FETCH_NUL_STATE;
333
ctx->trans = mailbox_transaction_begin(ctx->box,
372
ctx->state.trans = mailbox_transaction_begin(box,
334
373
MAILBOX_TRANSACTION_FLAG_HIDE |
335
374
MAILBOX_TRANSACTION_FLAG_REFRESH);
336
ctx->select_counter = ctx->client->select_counter;
338
/* Delayed uidset -> seqset conversion. VANISHED needs the uidset. */
339
mail_search_args_init(ctx->search_args, ctx->box, TRUE,
340
&ctx->cmd->client->search_saved_uidset);
342
mailbox_search_init(ctx->trans, ctx->search_args, NULL,
343
ctx->fetch_data, ctx->all_headers_ctx);
376
mail_search_args_init(search_args, box, TRUE,
377
&ctx->client->search_saved_uidset);
378
ctx->state.search_ctx =
379
mailbox_search_init(ctx->state.trans, search_args, NULL,
380
ctx->fetch_data, wanted_headers);
381
ctx->state.cur_str = str_new(default_pool, 8192);
382
ctx->state.fetching = TRUE;
383
ctx->state.line_finished = TRUE;
385
if (wanted_headers != NULL)
386
mailbox_header_lookup_unref(&wanted_headers);
347
389
static int imap_fetch_flush_buffer(struct imap_fetch_context *ctx)
432
if (ctx->cur_mail == NULL) {
433
if (ctx->cmd->cancel)
475
if (state->cur_mail == NULL) {
436
if (!mailbox_search_next(ctx->search_ctx,
479
if (!mailbox_search_next(state->search_ctx,
440
str_printfa(ctx->cur_str, "* %u FETCH (",
443
ctx->line_finished = FALSE;
483
str_printfa(state->cur_str, "* %u FETCH (",
484
state->cur_mail->seq);
485
state->cur_first = TRUE;
486
state->line_finished = FALSE;
446
for (; ctx->cur_handler < count; ctx->cur_handler++) {
447
if (str_len(ctx->cur_str) > 0 &&
448
!handlers[ctx->cur_handler].buffered) {
489
for (; state->cur_handler < count; state->cur_handler++) {
490
if (str_len(state->cur_str) > 0 &&
491
!handlers[state->cur_handler].buffered) {
449
492
/* first non-buffered handler.
450
493
flush the buffer. */
451
ctx->line_partial = TRUE;
494
state->line_partial = TRUE;
452
495
if (imap_fetch_flush_buffer(ctx) < 0)
456
i_assert(ctx->cur_input == NULL);
499
i_assert(state->cur_input == NULL);
458
501
const struct imap_fetch_context_handler *h =
459
&handlers[ctx->cur_handler];
502
&handlers[state->cur_handler];
461
ret = h->handler(ctx, ctx->cur_mail,
504
ret = h->handler(ctx, state->cur_mail,
469
if (ctx->cur_mail->expunged) {
512
if (state->cur_mail->expunged) {
470
513
/* not an error, just lost it. */
471
ctx->partial_fetch = TRUE;
514
state->skipped_expunged_msgs = TRUE;
472
515
if (imap_fetch_send_nil_reply(ctx) < 0)
475
518
i_assert(ret < 0 ||
476
ctx->cont_handler != NULL);
519
state->cont_handler != NULL);
481
ctx->cont_handler = NULL;
483
if (ctx->cur_input != NULL)
484
i_stream_unref(&ctx->cur_input);
524
state->cont_handler = NULL;
525
state->cur_offset = 0;
526
if (state->cur_input != NULL)
527
i_stream_unref(&state->cur_input);
487
if (str_len(ctx->cur_str) > 0) {
530
if (str_len(state->cur_str) > 0) {
488
531
/* no non-buffered handlers */
489
532
if (imap_fetch_flush_buffer(ctx) < 0)
493
ctx->line_finished = TRUE;
494
ctx->line_partial = FALSE;
495
if (o_stream_send(client->output, ")\r\n", 3) < 0)
536
state->line_finished = TRUE;
537
state->line_partial = FALSE;
538
o_stream_nsend(client->output, ")\r\n", 3);
497
539
client->last_output = ioloop_time;
499
ctx->cur_mail = NULL;
500
ctx->cur_handler = 0;
541
state->cur_mail = NULL;
542
state->cur_handler = 0;
506
int imap_fetch_more(struct imap_fetch_context *ctx)
548
int imap_fetch_more(struct imap_fetch_context *ctx,
549
struct client_command_context *cmd)
510
i_assert(ctx->client->output_lock == NULL ||
511
ctx->client->output_lock == ctx->cmd);
553
i_assert(ctx->client->output_cmd_lock == NULL ||
554
ctx->client->output_cmd_lock == cmd);
513
ret = imap_fetch_more_int(ctx);
556
ret = imap_fetch_more_int(ctx, cmd->cancel);
516
if (ctx->line_partial) {
558
ctx->state.failed = TRUE;
559
if (ctx->state.line_partial) {
517
560
/* nothing can be sent until FETCH is finished */
518
ctx->client->output_lock = ctx->cmd;
523
int imap_fetch_deinit(struct imap_fetch_context *ctx)
561
ctx->client->output_cmd_lock = cmd;
563
if (cmd->cancel && ctx->client->output_cmd_lock != NULL) {
564
/* canceling didn't really work. we must not output
566
if (!ctx->client->destroyed)
567
client_disconnect(ctx->client, "Failed to cancel FETCH");
568
ctx->client->output_cmd_lock = NULL;
573
int imap_fetch_more_no_lock_update(struct imap_fetch_context *ctx)
577
ret = imap_fetch_more_int(ctx, FALSE);
579
ctx->state.failed = TRUE;
580
if (!ctx->state.line_finished) {
581
client_disconnect(ctx->client,
582
"NOTIFY failed in the middle of FETCH reply");
588
int imap_fetch_end(struct imap_fetch_context *ctx)
590
struct imap_fetch_state *state = &ctx->state;
592
if (ctx->state.fetching) {
593
ctx->state.fetching = FALSE;
594
if (!state->line_finished) {
595
if (imap_fetch_flush_buffer(ctx) < 0)
596
state->failed = TRUE;
597
if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
598
state->failed = TRUE;
601
ctx->client->output_cmd_lock = NULL;
603
if (state->cur_str != NULL)
604
str_free(&state->cur_str);
606
if (state->cur_input != NULL)
607
i_stream_unref(&state->cur_input);
609
if (state->search_ctx != NULL) {
610
if (mailbox_search_deinit(&state->search_ctx) < 0)
611
state->failed = TRUE;
614
if (state->trans != NULL) {
615
/* even if something failed, we want to commit changes to
616
cache, as well as possible \Seen flag changes for FETCH
617
replies we returned so far. */
618
if (mailbox_transaction_commit(&state->trans) < 0)
619
state->failed = TRUE;
621
return state->failed ? -1 : 0;
624
void imap_fetch_free(struct imap_fetch_context **_ctx)
626
struct imap_fetch_context *ctx = *_ctx;
525
627
const struct imap_fetch_context_handler *handler;
631
(void)imap_fetch_end(ctx);
527
633
array_foreach(&ctx->handlers, handler) {
528
634
if (handler->want_deinit)
529
635
handler->handler(ctx, NULL, handler->context);
532
if (!ctx->line_finished) {
533
if (imap_fetch_flush_buffer(ctx) < 0)
535
if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
538
str_free(&ctx->cur_str);
540
if (ctx->cur_input != NULL)
541
i_stream_unref(&ctx->cur_input);
543
mail_search_args_unref(&ctx->search_args);
544
if (ctx->search_ctx != NULL) {
545
if (mailbox_search_deinit(&ctx->search_ctx) < 0)
548
if (ctx->all_headers_ctx != NULL)
549
mailbox_header_lookup_unref(&ctx->all_headers_ctx);
551
if (ctx->trans != NULL) {
552
/* even if something failed, we want to commit changes to
553
cache, as well as possible \Seen flag changes for FETCH
554
replies we returned so far. */
555
if (mailbox_transaction_commit(&ctx->trans) < 0)
558
return ctx->failed ? -1 : 0;
637
pool_unref(&ctx->ctx_pool);
561
640
static int fetch_body(struct imap_fetch_context *ctx, struct mail *mail,
678
752
keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
679
753
mail_get_keyword_indexes(mail));
681
str_append(ctx->cur_str, "FLAGS (");
682
imap_write_flags(ctx->cur_str, flags, keywords);
683
str_append(ctx->cur_str, ") ");
755
str_append(ctx->state.cur_str, "FLAGS (");
756
imap_write_flags(ctx->state.cur_str, flags, keywords);
757
str_append(ctx->state.cur_str, ") ");
688
fetch_flags_init(struct imap_fetch_context *ctx, const char *name,
689
const struct imap_arg **args ATTR_UNUSED)
761
bool imap_fetch_flags_init(struct imap_fetch_init_context *ctx)
691
ctx->flags_have_handler = TRUE;
692
ctx->fetch_data |= MAIL_FETCH_FLAGS;
693
imap_fetch_add_handler(ctx, TRUE, FALSE, name, "()", fetch_flags, NULL);
763
ctx->fetch_ctx->flags_have_handler = TRUE;
764
ctx->fetch_ctx->fetch_data |= MAIL_FETCH_FLAGS;
765
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
766
"()", fetch_flags, NULL);
702
775
if (mail_get_received_date(mail, &date) < 0)
705
str_printfa(ctx->cur_str, "INTERNALDATE \"%s\" ",
778
str_printfa(ctx->state.cur_str, "INTERNALDATE \"%s\" ",
706
779
imap_to_datetime(date));
711
fetch_internaldate_init(struct imap_fetch_context *ctx, const char *name,
712
const struct imap_arg **args ATTR_UNUSED)
783
static bool fetch_internaldate_init(struct imap_fetch_init_context *ctx)
714
ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
715
imap_fetch_add_handler(ctx, TRUE, FALSE, name,
785
ctx->fetch_ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
786
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
716
787
"\"01-Jan-1970 00:00:00 +0000\"",
717
788
fetch_internaldate, NULL);
726
797
modseq = mail_get_modseq(mail);
727
798
if (ctx->client->highest_fetch_modseq < modseq)
728
799
ctx->client->highest_fetch_modseq = modseq;
729
str_printfa(ctx->cur_str, "MODSEQ (%llu) ",
800
str_printfa(ctx->state.cur_str, "MODSEQ (%llu) ",
730
801
(unsigned long long)modseq);
735
fetch_modseq_init(struct imap_fetch_context *ctx, const char *name,
736
const struct imap_arg **args ATTR_UNUSED)
805
bool imap_fetch_modseq_init(struct imap_fetch_init_context *ctx)
738
(void)client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
739
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
807
(void)client_enable(ctx->fetch_ctx->client, MAILBOX_FEATURE_CONDSTORE);
808
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
809
NULL, fetch_modseq, NULL);
744
813
static int fetch_uid(struct imap_fetch_context *ctx, struct mail *mail,
745
814
void *context ATTR_UNUSED)
747
str_printfa(ctx->cur_str, "UID %u ", mail->uid);
816
str_printfa(ctx->state.cur_str, "UID %u ", mail->uid);
752
fetch_uid_init(struct imap_fetch_context *ctx ATTR_UNUSED, const char *name,
753
const struct imap_arg **args ATTR_UNUSED)
820
bool imap_fetch_uid_init(struct imap_fetch_init_context *ctx)
755
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL, fetch_uid, NULL);
822
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
823
NULL, fetch_uid, NULL);
764
832
if (mail_get_special(mail, MAIL_FETCH_GUID, &value) < 0)
767
str_append(ctx->cur_str, "X-GUID ");
768
imap_quote_append_string(ctx->cur_str, value, FALSE);
769
str_append_c(ctx->cur_str, ' ');
835
str_append(ctx->state.cur_str, "X-GUID ");
836
imap_append_astring(ctx->state.cur_str, value);
837
str_append_c(ctx->state.cur_str, ' ');
774
fetch_guid_init(struct imap_fetch_context *ctx ATTR_UNUSED, const char *name,
775
const struct imap_arg **args ATTR_UNUSED)
841
static bool fetch_guid_init(struct imap_fetch_init_context *ctx)
777
ctx->fetch_data |= MAIL_FETCH_GUID;
778
imap_fetch_add_handler(ctx, TRUE, FALSE, name, "", fetch_guid, NULL);
843
ctx->fetch_ctx->fetch_data |= MAIL_FETCH_GUID;
844
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
845
"", fetch_guid, NULL);
792
859
if (imap_utf8_to_utf7(name, mutf7_name) < 0)
793
860
i_panic("FETCH: Mailbox name not UTF-8: %s", name);
795
str_append(ctx->cur_str, "X-MAILBOX ");
796
imap_quote_append_string(ctx->cur_str, str_c(mutf7_name), FALSE);
797
str_append_c(ctx->cur_str, ' ');
862
str_append(ctx->state.cur_str, "X-MAILBOX ");
863
imap_append_astring(ctx->state.cur_str, str_c(mutf7_name));
864
str_append_c(ctx->state.cur_str, ' ');
802
fetch_x_mailbox_init(struct imap_fetch_context *ctx ATTR_UNUSED,
804
const struct imap_arg **args ATTR_UNUSED)
868
static bool fetch_x_mailbox_init(struct imap_fetch_init_context *ctx)
806
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
807
fetch_x_mailbox, NULL);
870
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
871
NULL, fetch_x_mailbox, NULL);
811
875
static int fetch_x_real_uid(struct imap_fetch_context *ctx, struct mail *mail,
812
876
void *context ATTR_UNUSED)
814
str_printfa(ctx->cur_str, "X-REAL-UID %u ",
878
str_printfa(ctx->state.cur_str, "X-REAL-UID %u ",
815
879
mail_get_real_mail(mail)->uid);
820
fetch_x_real_uid_init(struct imap_fetch_context *ctx ATTR_UNUSED,
822
const struct imap_arg **args ATTR_UNUSED)
883
static bool fetch_x_real_uid_init(struct imap_fetch_init_context *ctx)
824
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
825
fetch_x_real_uid, NULL);
885
imap_fetch_add_handler(ctx, IMAP_FETCH_HANDLER_FLAG_BUFFERED,
886
NULL, fetch_x_real_uid, NULL);
853
912
static const struct imap_fetch_handler
854
913
imap_fetch_default_handlers[] = {
914
{ "BINARY", imap_fetch_binary_init },
855
915
{ "BODY", fetch_body_init },
856
916
{ "BODYSTRUCTURE", fetch_bodystructure_init },
857
917
{ "ENVELOPE", fetch_envelope_init },
858
{ "FLAGS", fetch_flags_init },
918
{ "FLAGS", imap_fetch_flags_init },
859
919
{ "INTERNALDATE", fetch_internaldate_init },
860
{ "MODSEQ", fetch_modseq_init },
861
{ "RFC822", fetch_rfc822_init },
862
{ "UID", fetch_uid_init },
920
{ "MODSEQ", imap_fetch_modseq_init },
921
{ "RFC822", imap_fetch_rfc822_init },
922
{ "UID", imap_fetch_uid_init },
863
923
{ "X-GUID", fetch_guid_init },
864
924
{ "X-MAILBOX", fetch_x_mailbox_init },
865
925
{ "X-REAL-UID", fetch_x_real_uid_init },