index-mail-headers.c revision 96a464e3e417557153272c964fc8a0e9bb6d6b86
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen unsigned int count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int *idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char **name;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainenstatic const enum message_header_parser_flags hdr_parser_flags =
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainenstatic const enum message_parser_flags msg_parser_flags =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int header_line_cmp(const void *p1, const void *p2)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct index_mail_line *l1 = p1, *l2 = p2;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen diff = (int)l1->field_idx - (int)l2->field_idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void index_mail_parse_header_finish(struct index_mail *mail)
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen unsigned int i, j, count, match_idx, match_count;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen lines = array_get_modifiable(&mail->header_lines, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* sort it first so fields are grouped together and ordered by
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen line number */
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen qsort(lines, count, sizeof(*lines), header_line_cmp);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen match = array_get(&mail->header_match, &match_count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header = buffer_get_data(mail->header_data, NULL);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* go through all the header lines we found */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* matches and header lines are both sorted, all matches
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen until lines[i] weren't found */
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen mail_cache_field_can_add(mail->trans->cache_trans,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* this header doesn't exist. remember that. */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* save index to first header line */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_idx_set(&mail->header_match_lines, match_idx, &j);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (!mail_cache_field_can_add(mail->trans->cache_trans,
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen /* header is already cached */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* buffer contains: { uint32_t line_num[], 0, header texts }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen noncontiguous is just a small optimization.. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (; i < j; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, header + lines[i].start_pos,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, header + lines[i].start_pos,
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen index_mail_cache_add_idx(mail, lines[i].field_idx,
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen for (; match_idx < match_count; match_idx++) {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen mail_cache_field_can_add(mail->trans->cache_trans,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen /* this header doesn't exist. remember that. */
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen index_mail_cache_add_idx(mail, match_idx, NULL, 0);
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainenstatic unsigned int
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainenget_header_field_idx(struct index_mailbox *ibox, const char *field)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen header_field.name = t_strconcat("hdr.", field, NULL);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mail_cache_register_fields(ibox->cache, &header_field, 1);
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainenbool index_mail_want_parse_headers(struct index_mail *mail)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if ((mail->data.cache_fetch_fields & MAIL_FETCH_DATE) != 0 &&
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenstatic void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const struct mail_cache_field *all_cache_fields;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen unsigned int i, count;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen mail_cache_register_get_list(mail->ibox->cache,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen for (i = 0; i < count; i++) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (!mail_cache_field_want_add(mail->trans->cache_trans,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen array_idx_set(&mail->header_match, all_cache_fields[i].idx,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid index_mail_parse_header_init(struct index_mail *mail,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen unsigned int i;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen mail->header_data = buffer_create_dynamic(default_pool, 4096);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen mail->header_match_value += HEADER_MATCH_SKIP_COUNT;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen /* wrapped, we'll have to clear the buffer */
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_idx_set(&mail->header_match, headers->idx[i],
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail->wanted_headers != NULL && mail->wanted_headers != headers) {
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_idx_set(&mail->header_match, headers->idx[i],
faa6c140211a8ac8e2f5fcc5bcd79ade640d46a3Timo Sirainen if ((mail->data.cache_fetch_fields & MAIL_FETCH_DATE) != 0 ||
45b2a27617d8475f71fdfc870690e46cd63849f2Timo Sirainen /* register also all the other headers that exist in cache file */
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen index_mail_parse_header_register_all_wanted(mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void index_mail_parse_finish_imap_envelope(struct index_mail *mail)
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen const unsigned int cache_field_envelope =
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen imap_envelope_write_part_data(mail->data.envelope_data, str);
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen if (mail_cache_field_can_add(mail->trans->cache_trans,
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen index_mail_cache_add_idx(mail, cache_field_envelope,
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainenvoid index_mail_parse_header(struct message_part *part,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_bodystructure_parse_header(mail->data_pool, part, hdr);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* end of headers */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen match = array_get_modifiable(&mail->header_match, &count);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen !HEADER_MATCH_USABLE(mail, match[field_idx])) {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen /* we don't want this header. */
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen /* beginning of a line. add the header name. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.start_pos = str_len(mail->header_data);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.line_num = data->parse_line_num;
60576cd64e6a537413cd90104f7e862f71d48c81Timo Sirainen str_append_n(mail->header_data, hdr->middle, hdr->middle_len);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen /* remember that we saw this header so we don't add it to
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen cache as nonexisting. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append_n(mail->header_data, hdr->value, hdr->value_len);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.end_pos = str_len(mail->header_data);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_append(&mail->header_lines, &data->parse_line, 1);
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainenindex_mail_parse_part_header_cb(struct message_part *part,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenindex_mail_parse_header_cb(struct message_header_line *hdr,
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen index_mail_parse_header(mail->data.parts, hdr, mail);
7a54d58280aad8a64f266c61273ea1e8dff511a3Timo Sirainenindex_mail_cache_parse_init(struct mail *_mail, struct istream *input)
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
4d0d535efdfc4aad3bd48b74adfafecf58094e0aTimo Sirainen /* we're doing everything for now, figure out later if we want to
4d0d535efdfc4aad3bd48b74adfafecf58094e0aTimo Sirainen save them. */
dd0dea1fdd913a04bae16e82dd66d67571a5f6c2Timo Sirainenstatic void index_mail_init_parser(struct index_mail *mail)
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen (void)message_parser_deinit(&data->parser_ctx, &parts);
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen data->parser_ctx = message_parser_init(mail->data_pool,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainenint index_mail_parse_headers(struct index_mail *mail,
20195ef995a4eb63a282283db63f1dc0605323e0Timo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0)
1045a1d4c191a14867cde0d5cea9e4ac5e36f85fTimo Sirainen if (data->parts == NULL || data->save_bodystructure_header) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* initialize bodystructure parsing in case we read the whole
96541d31299bb40b5a6efdbf9b4cb3d4f4b4a069Timo Sirainen message_parser_parse_header(data->parser_ctx, &data->hdr_size,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* just read the header */
d96f86fb881c5b106649e8994ead1052acf24030Timo Sirainen message_parse_header(data->stream, &data->hdr_size,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenimap_envelope_parse_callback(struct message_header_line *hdr,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenint index_mail_headers_get_envelope(struct index_mail *mail)
3889d05019a072a602f7a8c1eeb8a6f1c1362720Timo Sirainen const unsigned int cache_field_envelope =
3889d05019a072a602f7a8c1eeb8a6f1c1362720Timo Sirainen mail->ibox->cache_fields[MAIL_CACHE_IMAP_ENVELOPE].idx;
3889d05019a072a602f7a8c1eeb8a6f1c1362720Timo Sirainen if (mail_cache_lookup_field(mail->trans->cache_view, str,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header_ctx = mailbox_header_lookup_init(&mail->ibox->box,
00db1d630a723113609598e28acbae4d416e0cb4Timo Sirainen if (mail_get_header_stream(&mail->mail.mail, header_ctx, &stream) < 0) {
9db263f2b9ab771fbf9a2bff44a245c45eaef218Timo Sirainen if (mail->data.envelope == NULL && stream != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we got the headers from cache - parse them to get the
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen message_parse_header(stream, NULL, hdr_parser_flags,
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenstatic size_t get_header_size(buffer_t *buffer, size_t pos)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen const unsigned char *data;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenstatic int index_mail_header_is_parsed(struct index_mail *mail,
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen unsigned int count;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen match = array_get(&mail->header_match, &count);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (field_idx < count && HEADER_MATCH_USABLE(mail, match[field_idx]))
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen return (match[field_idx] & HEADER_MATCH_FLAG_FOUND) != 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool skip_header(const unsigned char **data, size_t len)
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen const unsigned char *p = *data;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen for (i = 0; i < len; i++) {
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (p[i] == ':')
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen for (i++; i < len; i++) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic const char *const *
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenindex_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen const unsigned char *header, *value_start, *value_end;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const unsigned int *line_idx;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen line_idx = array_idx(&mail->header_match_lines, field_idx);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p_array_init(&header_values, mail->data_pool, 4);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen header = buffer_get_data(mail->header_data, NULL);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen lines = array_get(&mail->header_lines, &lines_count);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen for (i = first_line_idx; i < lines_count; i++) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (lines[i].field_idx != lines[first_line_idx].field_idx)
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen /* skip header: and drop ending LF */
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (skip_header(&value_start, value_end - value_start)) {
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (value_start != value_end && value_end[-1] == '\n')
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen value = p_strndup(mail->data_pool, value_start,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenindex_mail_get_raw_headers(struct index_mail *mail, const char *field,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen const char *const **value_r)
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen struct mailbox_header_lookup_ctx *headers_ctx;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen unsigned char *data;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx = get_header_field_idx(mail->ibox, field);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_lookup_headers(mail->trans->cache_view, dest,
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen /* not in cache / error - first see if it's already parsed */
5dabb8e733a8af2337eb543f782eb6c43ea462dcTimo Sirainen index_mail_header_is_parsed(mail, field_idx) < 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ret = index_mail_parse_headers(mail, headers_ctx);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if ((ret = index_mail_header_is_parsed(mail, field_idx)) <= 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* not found */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *value_r = p_new(mail->data_pool, const char *, 1);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *value_r = index_mail_get_parsed_header(mail, field_idx);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen data = buffer_get_modifiable_data(dest, &len);
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen /* cached as non-existing. */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *value_r = p_new(mail->data_pool, const char *, 1);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p_array_init(&header_values, mail->data_pool, 4);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* cached. skip "header name: " parts in dest. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < len; i++) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* @UNSAFE */
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainenstatic int unfold_header(pool_t pool, const char **_str)
f38854c96aef76e0c859df4e8f7303325b7ae8a1Timo Sirainen unsigned int i, j;
f38854c96aef76e0c859df4e8f7303325b7ae8a1Timo Sirainen /* @UNSAFE */
f38854c96aef76e0c859df4e8f7303325b7ae8a1Timo Sirainen new_str = p_malloc(pool, i + strlen(str+i) + 1);
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen /* corrupted */
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainenindex_mail_headers_decode(struct index_mail *mail, const char *const **_list,
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen unsigned int i, count;
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen decoded_list = p_new(mail->data_pool, const char *, count + 1);
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen for (i = 0; i < count; i++) {
f38854c96aef76e0c859df4e8f7303325b7ae8a1Timo Sirainen if (message_header_decode_utf8((const unsigned char *)input,
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen if (unfold_header(mail->data_pool, &input) < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenint index_mail_get_headers(struct mail *_mail, const char *field,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen bool decode_to_utf8, const char *const **value_r)
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen for (i = 0; i < 2; i++) {
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen if (index_mail_get_raw_headers(mail, field, value_r) < 0)
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen ret = index_mail_headers_decode(mail, value_r, -1U);
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen "Broken header %s for mail UID %u",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenint index_mail_get_first_header(struct mail *_mail, const char *field,
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen const char *const *list;
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen for (i = 0; i < 2; i++) {
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen if (index_mail_get_raw_headers(mail, field, &list) < 0)
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen ret = index_mail_headers_decode(mail, &list, 1);
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen "Broken header %s for mail UID %u",
96a464e3e417557153272c964fc8a0e9bb6d6b86Timo Sirainen return ret < 0 ? -1 : (list[0] != NULL ? 1 : 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void header_cache_callback(struct message_header_line *hdr,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenint index_mail_get_header_stream(struct mail *_mail,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen /* we have to parse the header. */
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen if (index_mail_parse_headers(mail, _headers) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_lookup_headers(mail->trans->cache_view, dest,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* not in cache / error */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0)
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen i_stream_create_header_filter(mail->data.stream,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenindex_header_lookup_init_real(struct mailbox *box, const char *const headers[])
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_cache_field *fields, header_field = {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *const *name;
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen unsigned int i, count;
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen for (count = 0, name = headers; *name != NULL; name++)
042e2b8447b34051f0380baafcf0073704430239Timo Sirainen /* @UNSAFE: headers need to be sorted for filter stream. */
042e2b8447b34051f0380baafcf0073704430239Timo Sirainen memcpy(sorted_headers, headers, count * sizeof(*sorted_headers));
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen qsort(sorted_headers, count, sizeof(*sorted_headers), i_strcasecmp_p);
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen /* @UNSAFE */
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen fields = t_new(struct mail_cache_field, count);
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen for (i = 0; i < count; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header_field.name = t_strconcat("hdr.", headers[i], NULL);
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen mail_cache_register_fields(ibox->cache, fields, count);
0a9ad944630d84066c5c445eb4b657206ad88e80Timo Sirainen pool = pool_alloconly_create("index_header_lookup_ctx", 1024);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx = p_new(pool, struct index_header_lookup_ctx, 1);
cfb86adbda733e4945db44c6be27f8fda142c0a3Timo Sirainen ctx->name = p_new(pool, const char *, count + 1);
042e2b8447b34051f0380baafcf0073704430239Timo Sirainen /* @UNSAFE */
042e2b8447b34051f0380baafcf0073704430239Timo Sirainen for (i = 0; i < count; i++) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenindex_header_lookup_init(struct mailbox *box, const char *const headers[])
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx = index_header_lookup_init_real(box, headers);
f95b3d29bc56f139c18c880aa574a0ca72b0cffbTimo Sirainenvoid index_header_lookup_ref(struct mailbox_header_lookup_ctx *_ctx)