index-mail-headers.c revision 8b5b1f6cb19253dfd7821fcef8e9b7e95e6caf3a
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose/* Copyright (c) 2003-2016 Dovecot authors, see the included COPYING file */
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek#include "lib.h"
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#include "istream.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "array.h"
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include "buffer.h"
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include "str.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "message-date.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "message-parser.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "message-header-decode.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "istream-tee.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "istream-header-filter.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "imap-envelope.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "imap-bodystructure.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "index-storage.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "index-mail.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const enum message_header_parser_flags hdr_parser_flags =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MESSAGE_HEADER_PARSER_FLAG_DROP_CR;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const enum message_parser_flags msg_parser_flags =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int header_line_cmp(const struct index_mail_line *l1,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct index_mail_line *l2)
d921c1eba437662437847279f251a0a5d8f70127Maxim{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int diff;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher diff = (int)l1->field_idx - (int)l2->field_idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return diff != 0 ? diff :
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (int)l1->line_num - (int)l2->line_num;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void index_mail_parse_header_finish(struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher struct mail *_mail = &mail->mail.mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct index_mail_line *lines;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned char *header, *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const uint8_t *match;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_t *buf;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t data_size;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, j, count, match_idx, match_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool noncontiguous;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* sort it first so fields are grouped together and ordered by
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher line number */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_sort(&mail->header_lines, header_line_cmp);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher lines = array_get(&mail->header_lines, &count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match = array_get(&mail->header_match, &match_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header = buffer_get_data(mail->header_data, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buf = buffer_create_dynamic(pool_datastack_create(), 256);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* go through all the header lines we found */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = match_idx = 0; i < count; i = j) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* matches and header lines are both sorted, all matches
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher until lines[i] weren't found */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (match_idx < lines[i].field_idx &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match_idx < match_count) {
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny mail_cache_field_can_add(_mail->transaction->cache_trans,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, match_idx)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* this header doesn't exist. remember that. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((match[match_idx] &
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher HEADER_MATCH_FLAG_FOUND) == 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_add_idx(mail, match_idx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "", 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match_idx++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (match_idx < match_count) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* save index to first header line */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(match_idx == lines[i].field_idx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher j = i + 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_idx_set(&mail->header_match_lines, match_idx, &j);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match_idx++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!mail_cache_field_can_add(_mail->transaction->cache_trans,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, lines[i].field_idx)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* header is already cached. skip over all the
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header lines. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (j = i+1; j < count; j++) {
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (lines[j].field_idx != lines[i].field_idx)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher break;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* buffer contains: { uint32_t line_num[], 0, header texts }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher noncontiguous is just a small optimization.. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_set_used_size(buf, 0);
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher buffer_append(buf, &lines[i].line_num,
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher sizeof(lines[i].line_num));
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek noncontiguous = FALSE;
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek for (j = i+1; j < count; j++) {
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher if (lines[j].field_idx != lines[i].field_idx)
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher if (lines[j].start_pos != lines[j-1].end_pos)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher noncontiguous = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(buf, &lines[j].line_num,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sizeof(lines[j].line_num));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append_zero(buf, sizeof(uint32_t));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (noncontiguous) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; i < j; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(buf, header + lines[i].start_pos,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lines[i].end_pos -
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lines[i].start_pos);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i--;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(buf, header + lines[i].start_pos,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lines[j-1].end_pos - lines[i].start_pos);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data = buffer_get_data(buf, &data_size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_add_idx(mail, lines[i].field_idx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data, data_size);
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek for (; match_idx < match_count; match_idx++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_field_can_add(_mail->transaction->cache_trans,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, match_idx)) {
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* this header doesn't exist. remember that. */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek i_assert((match[match_idx] &
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher HEADER_MATCH_FLAG_FOUND) == 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_add_idx(mail, match_idx, "", 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.dont_cache_field_idx = UINT_MAX;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.header_parser_initialized = FALSE;
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher}
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic unsigned int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherget_header_field_idx(struct mailbox *box, const char *field,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_cache_decision_type decision)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_cache_field header_field;
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek memset(&header_field, 0, sizeof(header_field));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header_field.type = MAIL_CACHE_FIELD_HEADER;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header_field.decision = decision;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header_field.name = t_strconcat("hdr.", field, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_register_fields(box->cache, &header_field, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return header_field.idx;
15b266d9f14dad26da8678a79019749d0f69532eStephen Gallagher}
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozekbool index_mail_want_parse_headers(struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher if (mail->data.wanted_headers != NULL ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.save_bodystructure_header)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((mail->data.cache_fetch_fields & MAIL_FETCH_DATE) != 0 &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher !mail->data.sent_date_parsed)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *_mail = &mail->mail.mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct mail_cache_field *all_cache_fields;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher all_cache_fields =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_register_get_list(_mail->box->cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_datastack_create(), &count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!mail_cache_field_want_add(_mail->transaction->cache_trans,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, i))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_idx_set(&mail->header_match, all_cache_fields[i].idx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &mail->header_match_value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid index_mail_parse_header_init(struct index_mail *mail,
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose struct mailbox_header_lookup_ctx *headers)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail_data *data = &mail->data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const uint8_t *match;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, field_idx, match_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->header_seq = data->seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->header_data == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->header_data = buffer_create_dynamic(default_pool, 4096);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_array_init(&mail->header_lines, 32);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_array_init(&mail->header_match, 32);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_array_init(&mail->header_match_lines, 32);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_set_used_size(mail->header_data, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_clear(&mail->header_lines);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_clear(&mail->header_match_lines);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->header_match_value += HEADER_MATCH_SKIP_COUNT;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((mail->header_match_value &
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (HEADER_MATCH_SKIP_COUNT-1)) == 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->header_match_value == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* wrapped, we'll have to clear the buffer */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_clear(&mail->header_match);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (headers != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < headers->count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_idx_set(&mail->header_match, headers->idx[i],
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &mail->header_match_value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data->wanted_headers != NULL && data->wanted_headers != headers) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher headers = data->wanted_headers;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < headers->count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_idx_set(&mail->header_match, headers->idx[i],
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &mail->header_match_value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* register also all the other headers that exist in cache file */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_register_all_wanted(mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* if we want sent date, it doesn't mean that we also want to cache
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher Date: header. if we have Date field's index set at this point we
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher know that we want it. otherwise add it and remember that we don't
126c9338cf12a3e4404c36bbe4ec14b18f23537cMaxim want it cached. */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher field_idx = get_header_field_idx(mail->mail.mail.box, "Date",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_CACHE_DECISION_NO);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match = array_get(&mail->header_match, &match_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (field_idx < match_count &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match[field_idx] == mail->header_match_value) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* cache Date: header */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if ((data->cache_fetch_fields & MAIL_FETCH_DATE) != 0 ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->save_sent_date) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* parse Date: header, but don't cache it. */
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek data->dont_cache_field_idx = field_idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_idx_set(&mail->header_match, field_idx,
126c9338cf12a3e4404c36bbe4ec14b18f23537cMaxim &mail->header_match_value);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.header_parser_initialized = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.parse_line_num = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher memset(&mail->data.parse_line, 0, sizeof(mail->data.parse_line));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void index_mail_parse_finish_imap_envelope(struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *_mail = &mail->mail.mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned int cache_field_envelope =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *str;
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str = str_new(mail->mail.data_pool, 256);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_envelope_write_part_data(mail->data.envelope_data, str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.envelope = str_c(str);
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_cache_field_can_add(_mail->transaction->cache_trans,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, cache_field_envelope)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_add_idx(mail, cache_field_envelope,
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek str_data(str), str_len(str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid index_mail_parse_header(struct message_part *part,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct message_header_line *hdr,
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *_mail = &mail->mail.mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail_data *data = &mail->data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int field_idx, count;
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek uint8_t *match;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(data->header_parser_initialized);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parse_line_num++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data->save_bodystructure_header) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(part != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_bodystructure_parse_header(mail->mail.data_pool, part, hdr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher if (data->save_envelope) {
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher imap_envelope_parse_header(mail->mail.data_pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &data->envelope_data, hdr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (hdr == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_finish_imap_envelope(mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (hdr == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* end of headers */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->data.save_sent_date)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.sent_date_parsed = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_finish(mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data->save_bodystructure_header) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(!data->save_bodystructure_body ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parser_ctx != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->save_bodystructure_header = FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!hdr->continued) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *cache_field_name =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_strconcat("hdr.", hdr->name, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parse_line.field_idx =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_register_lookup(_mail->box->cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher cache_field_name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher field_idx = data->parse_line.field_idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match = array_get_modifiable(&mail->header_match, &count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (field_idx >= count ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher !HEADER_MATCH_USABLE(mail, match[field_idx])) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we don't want this header. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek if (!hdr->continued) {
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek /* beginning of a line. add the header name. */
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek data->parse_line.start_pos = str_len(mail->header_data);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher data->parse_line.line_num = data->parse_line_num;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_append(mail->header_data, hdr->name);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_append_n(mail->header_data, hdr->middle, hdr->middle_len);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* remember that we saw this header so we don't add it to
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher cache as nonexistent. */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher match[field_idx] |= HEADER_MATCH_FLAG_FOUND;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_append_n(mail->header_data, hdr->value, hdr->value_len);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!hdr->no_newline)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_append(mail->header_data, "\n");
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!hdr->continues) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher data->parse_line.end_pos = str_len(mail->header_data);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher array_append(&mail->header_lines, &data->parse_line, 1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherstatic void
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherindex_mail_parse_part_header_cb(struct message_part *part,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct message_header_line *hdr,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct index_mail *mail)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher index_mail_parse_header(part, hdr, mail);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherstatic void
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherindex_mail_parse_header_cb(struct message_header_line *hdr,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct index_mail *mail)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher index_mail_parse_header(mail->data.parts, hdr, mail);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherstruct istream *
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherindex_mail_cache_parse_init(struct mail *_mail, struct istream *input)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail *mail = (struct index_mail *)_mail;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher struct istream *input2;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher i_assert(mail->data.tee_stream == NULL);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher i_assert(mail->data.parser_ctx == NULL);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher /* we're doing everything for now, figure out later if we want to
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher save them. */
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mail->data.save_sent_date = TRUE;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mail->data.save_bodystructure_header = TRUE;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mail->data.save_bodystructure_body = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.tee_stream = tee_i_stream_create(input);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher input = tee_i_stream_create_child(mail->data.tee_stream);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher input2 = tee_i_stream_create_child(mail->data.tee_stream);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_init(mail, NULL);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher mail->data.parser_input = input;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.parser_ctx =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_parser_init(mail->mail.data_pool, input,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher hdr_parser_flags, msg_parser_flags);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_stream_unref(&input);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return input2;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void index_mail_init_parser(struct index_mail *mail)
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail_data *data = &mail->data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct message_part *parts;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *error;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (data->parser_ctx != NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parser_input = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (message_parser_deinit_from_parts(&data->parser_ctx, &parts, &error) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_set_cache_corrupted_reason(&mail->mail.mail,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_FETCH_MESSAGE_PARTS, t_strdup_printf(
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Cached MIME parts don't match message during parsing: %s", error));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parts = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (data->parts == NULL) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher data->parser_input = data->stream;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parser_ctx = message_parser_init(mail->mail.data_pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->stream,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hdr_parser_flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher msg_parser_flags);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parser_ctx =
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher message_parser_init_from_parts(data->parts,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher data->stream,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher hdr_parser_flags,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher msg_parser_flags);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
4b0309363dbfb9a1409e082b3a84f17b53a751c1Stephen Gallagherint index_mail_parse_headers(struct index_mail *mail,
4b0309363dbfb9a1409e082b3a84f17b53a751c1Stephen Gallagher struct mailbox_header_lookup_ctx *headers)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek struct index_mail_data *data = &mail->data;
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek struct istream *input;
52e0894fd65bff4715c88330eb62b28e1635228fStephen Gallagher uoff_t old_offset;
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek if (mail_get_hdr_stream(&mail->mail.mail, NULL, &input) < 0)
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_init(mail, headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data->parts == NULL || data->save_bodystructure_header) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* initialize bodystructure parsing in case we read the whole
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_init_parser(mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_parser_parse_header(data->parser_ctx, &data->hdr_size,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_part_header_cb,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* just read the header */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(!data->save_bodystructure_body ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->parser_ctx != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_parse_header(data->stream, &data->hdr_size,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hdr_parser_flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_cb, mail);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (index_mail_stream_check_failure(mail) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->hdr_size_set = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data->access_part &= ~PARSE_HDR;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_seek(data->stream, old_offset);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherimap_envelope_parse_callback(struct message_header_line *hdr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail *mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_envelope_parse_header(mail->mail.data_pool,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher &mail->data.envelope_data, hdr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (hdr == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_finish_imap_envelope(mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint index_mail_headers_get_envelope(struct index_mail *mail)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned int cache_field_envelope =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_header_lookup_ctx *header_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct istream *stream;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uoff_t old_offset;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *str;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str = str_new(mail->mail.data_pool, 256);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (index_mail_cache_lookup_field(mail, str,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher cache_field_envelope) > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.envelope = str_c(str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_free(&str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher old_offset = mail->data.stream == NULL ? 0 :
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.stream->v_offset;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.save_envelope = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header_ctx = mailbox_header_lookup_init(mail->mail.mail.box,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher imap_envelope_headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_get_header_stream(&mail->mail.mail, header_ctx, &stream) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_header_lookup_unref(&header_ctx);
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny return -1;
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny }
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny mailbox_header_lookup_unref(&header_ctx);
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (mail->data.envelope == NULL && stream != NULL) {
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny /* we got the headers from cache - parse them to get the
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny envelope */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_parse_header(stream, NULL, hdr_parser_flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_envelope_parse_callback, mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (stream->stream_errno != 0) {
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose index_mail_stream_log_failure_for(mail, stream);
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose return -1;
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose }
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose mail->data.save_envelope = FALSE;
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose }
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->data.stream != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_seek(mail->data.stream, old_offset);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic size_t get_header_size(buffer_t *buffer, size_t pos)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned char *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t i, size;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data = buffer_get_data(buffer, &size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(pos <= size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher for (i = pos; i < size; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data[i] == '\n') {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (i+1 == size ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (data[i+1] != ' ' && data[i+1] != '\t'))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return i - pos;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return size - pos;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int index_mail_header_is_parsed(struct index_mail *mail,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int field_idx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const uint8_t *match;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match = array_get(&mail->header_match, &count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (field_idx < count && HEADER_MATCH_USABLE(mail, match[field_idx]))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return (match[field_idx] & HEADER_MATCH_FLAG_FOUND) != 0;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool skip_header(const unsigned char **data, size_t len)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned char *p = *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t i;
5843ad321944a028f6dee7e1fd4f9381c4953d07Sumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < len; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (p[i] == ':')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (i == len)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i++; i < len; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!IS_LWSP(p[i]))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
c8b8901b05da9e31dba320f305ec20301e928cfbSumit Bose }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher *data = p + i;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const char *const *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherindex_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY(const char *) header_values;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct index_mail_line *lines;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned char *header, *value_start, *value_end;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const unsigned int *line_idx;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher const char *value;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, lines_count, first_line_idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher line_idx = array_idx(&mail->header_match_lines, field_idx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(*line_idx != 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher first_line_idx = *line_idx - 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p_array_init(&header_values, mail->mail.data_pool, 4);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header = buffer_get_data(mail->header_data, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lines = array_get(&mail->header_lines, &lines_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = first_line_idx; i < lines_count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (lines[i].field_idx != lines[first_line_idx].field_idx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* skip header: and drop ending LF */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value_start = header + lines[i].start_pos;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value_end = header + lines[i].end_pos;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (skip_header(&value_start, value_end - value_start)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (value_start != value_end && value_end[-1] == '\n')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value_end--;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value = p_strndup(mail->mail.data_pool, value_start,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value_end - value_start);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&header_values, &value, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append_zero(&header_values);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return array_idx(&header_values, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherindex_mail_get_raw_headers(struct index_mail *mail, const char *field,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const **value_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *_mail = &mail->mail.mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *headers[2], *value;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_header_lookup_ctx *headers_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned char *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int field_idx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *dest;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t i, len, len2;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY(const char *) header_values;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(field != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher field_idx = get_header_field_idx(_mail->box, field,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_CACHE_DECISION_TEMP);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dest = str_new(mail->mail.data_pool, 128);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_cache_lookup_headers(_mail->transaction->cache_view, dest,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher _mail->seq, &field_idx, 1) <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* not in cache / error - first see if it's already parsed */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p_free(mail->mail.data_pool, dest);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->header_seq != mail->data.seq ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_header_is_parsed(mail, field_idx) < 0) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* parse */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher headers[0] = field; headers[1] = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher headers_ctx = mailbox_header_lookup_init(_mail->box,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = index_mail_parse_headers(mail, headers_ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_header_lookup_unref(&headers_ctx);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (ret < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((ret = index_mail_header_is_parsed(mail, field_idx)) <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* not found */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(ret != -1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher *value_r = p_new(mail->mail.data_pool, const char *, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *value_r = index_mail_get_parsed_header(mail, field_idx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher _mail->transaction->stats.cache_hit_count++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data = buffer_get_modifiable_data(dest, &len);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (len == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* cached as nonexistent. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *value_r = p_new(mail->mail.data_pool, const char *, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p_array_init(&header_values, mail->mail.data_pool, 4);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* cached. skip "header name: " parts in dest. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < len; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (data[i] == ':') {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (i < len && IS_LWSP(data[i])) i++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* @UNSAFE */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher len2 = get_header_size(dest, i);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data[i + len2] = '\0';
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value = (const char *)data + i;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i += len2 + 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&header_values, &value, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append_zero(&header_values);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *value_r = array_idx(&header_values, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int unfold_header(pool_t pool, const char **_str)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *str = *_str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char *new_str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, j;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; str[i] != '\0'; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str[i] == '\n')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str[i] == '\0')
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return 0;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* @UNSAFE */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher new_str = p_malloc(pool, i + strlen(str+i) + 1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher memcpy(new_str, str, i);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (j = i; str[i] != '\0'; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str[i] == '\n') {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher new_str[j++] = ' ';
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str[i] == '\0')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (str[i] != ' ' && str[i] != '\t') {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* corrupted */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek return -1;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek } else {
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek new_str[j++] = str[i];
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek }
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek new_str[j] = '\0';
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek *_str = new_str;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return 0;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek}
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozekstatic void str_replace_nuls(string_t *str)
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek{
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek char *data = str_c_modifiable(str);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher unsigned int i, len = str_len(str);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher for (i = 0; i < len; i++) {
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (data[i] == '\0')
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher data[i] = ' ';
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher }
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher}
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic int
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherindex_mail_headers_decode(struct index_mail *mail, const char *const **_list,
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher unsigned int max_count)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *list = *_list;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char **decoded_list, *input;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int i, count;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher string_t *str;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count = str_array_length(list);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (count > max_count)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count = max_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher decoded_list = p_new(mail->mail.data_pool, const char *, count + 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str = t_str_new(512);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_truncate(str, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher input = list[i];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* unfold all lines into a single line */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (unfold_header(mail->mail.data_pool, &input) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* decode MIME encoded-words. decoding may also add new LFs. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher message_header_decode_utf8((const unsigned char *)input,
f1ac7d7859b26f0f36f5e8ffacda609f8ece80e5Stephen Gallagher strlen(input), str, NULL);
f1ac7d7859b26f0f36f5e8ffacda609f8ece80e5Stephen Gallagher if (strcmp(str_c(str), input) != 0) {
f128b7b865062da662127712935dcc58bd022384Stephen Gallagher if (strlen(str_c(str)) != str_len(str)) {
f128b7b865062da662127712935dcc58bd022384Stephen Gallagher /* replace NULs with spaces */
f128b7b865062da662127712935dcc58bd022384Stephen Gallagher str_replace_nuls(str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher input = p_strdup(mail->mail.data_pool, str_c(str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher decoded_list[i] = input;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *_list = decoded_list;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint index_mail_get_headers(struct mail *_mail, const char *field,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool decode_to_utf8, const char *const **value_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail *mail = (struct index_mail *)_mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool retry = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (;; retry = FALSE) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (index_mail_get_raw_headers(mail, field, value_r) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!decode_to_utf8 || **value_r == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = index_mail_headers_decode(mail, value_r, UINT_MAX);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 && retry) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_set_corrupted(_mail->box->cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Broken header %s for mail UID %u",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher field, _mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
619bd403265ce0880989ba6f8324b010949851bcSumit Bose break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_panic("BUG: Broken header %s for mail UID %u "
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "wasn't fixed by re-parsing the header",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher field, _mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
619bd403265ce0880989ba6f8324b010949851bcSumit Bose return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint index_mail_get_first_header(struct mail *_mail, const char *field,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool decode_to_utf8, const char **value_r)
93109c5f1d85c028ce5cf6e31e2249ca90a7f746Jakub Hrozek{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail *mail = (struct index_mail *)_mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *const *list;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool retry = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (;; retry = FALSE) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (index_mail_get_raw_headers(mail, field, &list) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!decode_to_utf8 || list[0] == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = 0;
88aeed9a31b734a92630d5e881c960c5f77ba0ceJakub Hrozek break;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = index_mail_headers_decode(mail, &list, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 && retry) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_cache_set_corrupted(_mail->box->cache,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Broken header %s for mail UID %u",
04feeade1f6259368a6b23c6b3ecbad261161659Sumit Bose field, _mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* retry by parsing the full header */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
c355f8df3eabf3c59af3a506fbffb8b0e4ff9fb7Sumit Bose }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_panic("BUG: Broken header %s for mail UID %u "
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher "wasn't fixed by re-parsing the header",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher field, _mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *value_r = list[0];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return list[0] != NULL ? 1 : 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherheader_cache_callback(struct header_filter_istream *input ATTR_UNUSED,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct message_header_line *hdr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool *matched ATTR_UNUSED, struct index_mail *mail)
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header(NULL, hdr, mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint index_mail_get_header_stream(struct mail *_mail,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_header_lookup_ctx *headers,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct istream **stream_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct index_mail *mail = (struct index_mail *)_mail;
f3f9ce8024d7610439d6c70ddafab1ab025cf8a8Sumit Bose struct istream *input;
7d436b1bd6bcca29aa9874adc11bdfb862139cd8Sumit Bose string_t *dest;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
1e29e68388c2e9c5da9cb0afe997bc1b4e6933beSumit Bose i_assert(headers->box == _mail->box);
b87233035e26cee919dcf46adaec29ba7fdaa51eSumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail->data.save_bodystructure_header) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we have to parse the header. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (index_mail_parse_headers(mail, headers) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dest = str_new(mail->mail.data_pool, 256);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_cache_lookup_headers(_mail->transaction->cache_view, dest,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->seq, headers->idx,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher headers->count) > 0) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_append(dest, "\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher _mail->transaction->stats.cache_hit_count++;
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher if (mail->data.filter_stream != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_destroy(&mail->data.filter_stream);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.filter_stream =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_create_from_data(str_data(dest),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_len(dest));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *stream_r = mail->data.filter_stream;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* not in cache / error */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p_free(mail->mail.data_pool, dest);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher if (mail_get_hdr_stream(_mail, NULL, &input) < 0)
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher return -1;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher if (mail->data.filter_stream != NULL)
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher i_stream_destroy(&mail->data.filter_stream);
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_parse_header_init(mail, headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail->data.filter_stream =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_create_header_filter(mail->data.stream,
619bd403265ce0880989ba6f8324b010949851bcSumit Bose HEADER_FILTER_INCLUDE |
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher HEADER_FILTER_ADD_MISSING_EOH |
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher HEADER_FILTER_HIDE_BODY,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher headers->name, headers->count,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher header_cache_callback, mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *stream_r = mail->data.filter_stream;
619bd403265ce0880989ba6f8324b010949851bcSumit Bose return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher