index-mail-headers.c revision bb92096bdd934cc19def61b5fb4644af6351b62d
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen/* Copyright (C) 2003 Timo Sirainen */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "lib.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "istream.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "buffer.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "str.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "message-date.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "message-parser.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "istream-header-filter.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "imap-envelope.h"
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen#include "imap-bodystructure.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "index-storage.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "index-mail.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include <stdlib.h>
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct index_header_lookup_ctx {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mailbox_header_lookup_ctx ctx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pool_t pool;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen unsigned int count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int *idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char **name;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen};
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int header_line_cmp(const void *p1, const void *p2)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const struct index_mail_line *l1 = p1, *l2 = p2;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int diff;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen diff = (int)l1->field_idx - (int)l2->field_idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return diff != 0 ? diff :
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (int)l1->line_num - (int)l2->line_num;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void index_mail_parse_header_finish(struct index_mail *mail)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail_line *lines;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const unsigned char *header, *data;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const uint8_t *match;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_t *buf;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen size_t data_size;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen unsigned int i, j, count, match_idx, match_count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int noncontiguous;
8fb1e3e2349c9940732b5bb77a2a4053b8f72a4fTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_push();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen lines = array_get_modifyable(&mail->header_lines, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
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);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* go through all the header lines we found */
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen for (i = match_idx = 0; i < count; i = j) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* matches and header lines are both sorted, all matches
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen until lines[i] weren't found */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen while (match_idx < lines[i].field_idx &&
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen match_idx < match_count) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* if match[] doesn't have header_match_value,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen it belongs to some older header parsing and we
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen just want to ignore it. */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i_assert(match[match_idx] !=
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen mail->header_match_value + 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (match[match_idx] == mail->header_match_value) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* this header doesn't exist. remember that. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_add(mail->trans->cache_trans,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.seq, match_idx,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen NULL, 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen match_idx++;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (match_idx < match_count) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* save index to first header line */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen j = i + 1;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_idx_set(&mail->header_match_lines, match_idx, &j);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen match_idx++;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* buffer contains: { uint32_t line_num[], 0, header texts }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen noncontiguous is just a small optimization.. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_set_used_size(buf, 0);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, &lines[i].line_num,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen sizeof(lines[i].line_num));
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen noncontiguous = FALSE;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen for (j = i+1; j < count; j++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (lines[j].field_idx != lines[i].field_idx)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen break;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (lines[j].start_pos != lines[j-1].end_pos)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen noncontiguous = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, &lines[j].line_num,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen sizeof(lines[j].line_num));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen buffer_append_zero(buf, sizeof(uint32_t));
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (noncontiguous) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (; i < j; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, header + lines[i].start_pos,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen lines[i].end_pos -
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen lines[i].start_pos);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen i--;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } else {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_append(buf, header + lines[i].start_pos,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen lines[j-1].end_pos - lines[i].start_pos);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data = buffer_get_data(buf, &data_size);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_add(mail->trans->cache_trans, mail->data.seq,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen lines[i].field_idx, data, data_size);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen for (; match_idx < match_count; match_idx++) {
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen if (match[match_idx] == mail->header_match_value) {
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen /* this header doesn't exist. remember that. */
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen mail_cache_add(mail->trans->cache_trans,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen mail->data.seq, match_idx, NULL, 0);
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen }
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen }
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_pop();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid index_mail_parse_header_init(struct index_mail *mail,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mailbox_header_lookup_ctx *_headers)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_header_lookup_ctx *headers =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (struct index_header_lookup_ctx *)_headers;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen size_t i;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen mail->header_seq = mail->data.seq;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail->header_data == NULL) {
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen mail->header_data = buffer_create_dynamic(default_pool, 4096);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen ARRAY_CREATE(&mail->header_lines, default_pool,
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen struct index_mail_line, 32);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen ARRAY_CREATE(&mail->header_match, default_pool, uint8_t, 32);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen ARRAY_CREATE(&mail->header_match_lines, default_pool,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen unsigned int, 32);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } else {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen buffer_set_used_size(mail->header_data, 0);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_clear(&mail->header_lines);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_clear(&mail->header_match_lines);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen mail->header_match_value += 2;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (mail->header_match_value == 0) {
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen /* @UNSAFE: wrapped, we'll have to clear the buffer */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_clear(&mail->header_match);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen mail->header_match_value = 2;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (headers != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < headers->count; i++) {
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_idx_set(&mail->header_match, headers->idx[i],
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen &mail->header_match_value);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail->wanted_headers != NULL && mail->wanted_headers != headers) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen headers = mail->wanted_headers;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < headers->count; i++) {
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_idx_set(&mail->header_match, headers->idx[i],
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen &mail->header_match_value);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void index_mail_parse_finish_imap_envelope(struct index_mail *mail)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen string_t *str;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen str = str_new(mail->data_pool, 256);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen imap_envelope_write_part_data(mail->data.envelope_data, str);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.envelope = str_c(str);
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_add(mail->trans->cache_trans, mail->data.seq,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen MAIL_CACHE_ENVELOPE, str_data(str), str_len(str));
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainenint index_mail_parse_header(struct message_part *part,
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen struct message_header_line *hdr,
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen struct index_mail *mail)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct index_mail_data *data = &mail->data;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mail_cache_decision_type decision;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *cache_field_name;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen unsigned int field_idx, count;
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen uint8_t *match;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen int timezone;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line_num++;
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (data->save_bodystructure_header) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(part != NULL);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_bodystructure_parse_header(mail->data_pool, part, hdr);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (data->save_envelope) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_envelope_parse_header(mail->data_pool,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen &data->envelope_data, hdr);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (hdr == NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen index_mail_parse_finish_imap_envelope(mail);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (hdr == NULL) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* end of headers */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (data->save_sent_date) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* not found */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen data->sent_date.time = 0;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen data->sent_date.timezone = 0;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen data->save_sent_date = FALSE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (data->sent_date.time != (time_t)-1) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen mail_cache_add(mail->trans->cache_trans, data->seq,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen MAIL_CACHE_SENT_DATE, &data->sent_date,
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen sizeof(data->sent_date));
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen index_mail_parse_header_finish(mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->save_bodystructure_header = FALSE;
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen return TRUE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (data->save_sent_date && strcasecmp(hdr->name, "Date") == 0) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (hdr->continues)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen hdr->use_full_value = TRUE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen else {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (!message_date_parse(hdr->full_value,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen hdr->full_value_len,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen &data->sent_date.time,
bb8937e0c503b49a752858f00445646062b6f06eTimo Sirainen &timezone)) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* 0 == parse error */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen data->sent_date.time = 0;
bb8937e0c503b49a752858f00445646062b6f06eTimo Sirainen timezone = 0;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
bb8937e0c503b49a752858f00445646062b6f06eTimo Sirainen data->sent_date.timezone = timezone;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen data->save_sent_date = FALSE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!hdr->continued) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_push();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen cache_field_name = t_strconcat("hdr.", hdr->name, NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.field_idx =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_register_lookup(mail->ibox->cache,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen cache_field_name);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_pop();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx = data->parse_line.field_idx;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (field_idx == (unsigned int)-1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we don't want this field */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!hdr->continued) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen decision = mail_cache_field_get_decision(mail->ibox->cache,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.cache =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (decision & ~MAIL_CACHE_DECISION_FORCED) !=
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen MAIL_CACHE_DECISION_NO;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (data->parse_line.cache &&
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_field_exists(mail->trans->cache_view,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->seq, field_idx) > 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* already cached */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.cache = FALSE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen match = array_get_modifyable(&mail->header_match, &count);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen if (field_idx < count && match[field_idx] == mail->header_match_value) {
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen /* first header */
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen match[field_idx]++;
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen } else if (!data->parse_line.cache &&
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen (field_idx >= count ||
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen (match[field_idx] & ~1) != mail->header_match_value)) {
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen /* we don't need to do anything with this header */
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen return TRUE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!hdr->continued) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.start_pos = str_len(mail->header_data);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.line_num = data->parse_line_num;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append(mail->header_data, hdr->name);
60576cd64e6a537413cd90104f7e862f71d48c81Timo Sirainen str_append_n(mail->header_data, hdr->middle, hdr->middle_len);
203560029e3ad8687c2c759e6a81ecdb8b37ebe6Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append_n(mail->header_data, hdr->value, hdr->value_len);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!hdr->no_newline)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append(mail->header_data, "\n");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!hdr->continues) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_line.end_pos = str_len(mail->header_data);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_append(&mail->header_lines, &data->parse_line, 1);
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen return TRUE;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenindex_mail_parse_header_cb(struct message_part *part,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct message_header_line *hdr, void *context)
80cdfe47daf6129410bafcecbe5c9faf09f2721bTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = context;
80cdfe47daf6129410bafcecbe5c9faf09f2721bTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (void)index_mail_parse_header(part, hdr, mail);
80cdfe47daf6129410bafcecbe5c9faf09f2721bTimo Sirainen}
80cdfe47daf6129410bafcecbe5c9faf09f2721bTimo Sirainen
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainenint index_mail_parse_headers(struct index_mail *mail,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen struct mailbox_header_lookup_ctx *headers)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct index_mail_data *data = &mail->data;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (mail_get_stream(&mail->mail.mail, NULL, NULL) == NULL)
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen return -1;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen index_mail_parse_header_init(mail, headers);
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (data->parts == NULL && data->parser_ctx == NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* initialize bodystructure parsing in case we read the whole
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen message. */
96541d31299bb40b5a6efdbf9b4cb3d4f4b4a069Timo Sirainen data->parser_ctx =
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen message_parser_init(mail->data_pool, data->stream);
96541d31299bb40b5a6efdbf9b4cb3d4f4b4a069Timo Sirainen message_parser_parse_header(data->parser_ctx, &data->hdr_size,
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen index_mail_parse_header_cb, mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen } else {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* just read the header */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen message_parse_header(data->parts, data->stream, &data->hdr_size,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen index_mail_parse_header_cb, mail);
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen }
96541d31299bb40b5a6efdbf9b4cb3d4f4b4a069Timo Sirainen data->hdr_size_set = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen data->parse_header = FALSE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen return 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenimap_envelope_parse_callback(struct message_part *part __attr_unused__,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct message_header_line *hdr, void *context)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = context;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_envelope_parse_header(mail->data_pool,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen &mail->data.envelope_data, hdr);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (hdr == NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen index_mail_parse_finish_imap_envelope(mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid index_mail_headers_get_envelope(struct index_mail *mail)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mailbox_header_lookup_ctx *header_ctx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct istream *stream;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
36977c4a74e164f7d81eb4785f0a5d3ff436fd19Timo Sirainen mail->data.save_envelope = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header_ctx = mailbox_header_lookup_init(&mail->ibox->box,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen imap_envelope_headers);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen stream = mail_get_header_stream(&mail->mail.mail, header_ctx);
9db263f2b9ab771fbf9a2bff44a245c45eaef218Timo Sirainen if (mail->data.envelope == NULL && stream != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we got the headers from cache - parse them to get the
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen envelope */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen message_parse_header(NULL, stream, NULL,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen imap_envelope_parse_callback, mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.save_envelope = FALSE;
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mailbox_header_lookup_deinit(header_ctx);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic unsigned int
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenget_header_field_idx(struct index_mailbox *ibox, const char *field)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_cache_field header_field = {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen NULL, 0, MAIL_CACHE_FIELD_HEADER, 0,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen MAIL_CACHE_DECISION_TEMP
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen };
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *cache_field_name;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int field_idx;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_push();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen cache_field_name = t_strconcat("hdr.", field, NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx = mail_cache_register_lookup(ibox->cache, cache_field_name);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (field_idx == (unsigned int)-1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header_field.name = cache_field_name;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_cache_register_fields(ibox->cache, &header_field, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx = header_field.idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_pop();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return field_idx;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenstatic size_t get_header_size(buffer_t *buffer, size_t pos)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen{
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen const unsigned char *data;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen size_t i, size;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen data = buffer_get_data(buffer, &size);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen i_assert(pos <= size);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen for (i = pos; i < size; i++) {
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (data[i] == '\n') {
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (i+1 == size ||
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen (data[i+1] != ' ' && data[i+1] != '\t'))
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return i - pos;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen }
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen }
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return size - pos;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen}
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenstatic int index_mail_header_is_parsed(struct index_mail *mail,
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen unsigned int field_idx)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen{
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen const uint8_t *match;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen unsigned int count;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen match = array_get(&mail->header_match, &count);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen if (field_idx >= count)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return -1;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (match[field_idx] == mail->header_match_value)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return 0;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen else if (match[field_idx] == mail->header_match_value + 1)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return 1;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return -1;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen}
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainenstatic int skip_header(const unsigned char **data, size_t len)
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen{
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen const unsigned char *p = *data;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen size_t i;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen for (i = 0; i < len; i++) {
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (p[i] == ':')
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen break;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen }
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (i == len)
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen return FALSE;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen for (i++; i < len; i++) {
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen if (!IS_LWSP(p[i]))
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen break;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen }
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen *data = p + i;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen return TRUE;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen}
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic const char *const *
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainenindex_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen{
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_t ARRAY_DEFINE(header_values, const char *);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const struct index_mail_line *lines;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen const unsigned char *header, *value_start, *value_end;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const unsigned int *line_idx;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const char *value;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen unsigned int i, lines_count, first_line_idx;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen line_idx = array_idx(&mail->header_match_lines, field_idx);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i_assert(*line_idx != 0);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen first_line_idx = *line_idx - 1;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen ARRAY_CREATE(&header_values, mail->data_pool, const char *, 4);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen header = buffer_get_data(mail->header_data, NULL);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
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)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen break;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen /* skip header: and drop ending LF */
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen value_start = header + lines[i].start_pos;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen value_end = header + lines[i].end_pos;
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_end--;
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen value = p_strndup(mail->data_pool, value_start,
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen value_end - value_start);
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen array_append(&header_values, &value, 1);
1e242794e7a4f653f18fbb8edfe9ccec489a3a08Timo Sirainen }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen }
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen value = NULL;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_append(&header_values, &value, sizeof(value));
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return array_idx(&header_values, 0);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen}
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenconst char *const *index_mail_get_headers(struct mail *_mail, const char *field)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const char *headers[2], *value;
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen struct mailbox_header_lookup_ctx *headers_ctx;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen unsigned char *data;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int field_idx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen string_t *dest;
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen size_t i, len;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen int ret;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_t ARRAY_DEFINE(header_values, const char *);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen field_idx = get_header_field_idx(mail->ibox, field);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dest = str_new(mail->data_pool, 128);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_lookup_headers(mail->trans->cache_view, dest,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.seq, &field_idx, 1) <= 0) {
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen /* not in cache / error - first see if it's already parsed */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen p_free(mail->data_pool, dest);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (mail->header_seq == mail->data.seq) {
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen ret = index_mail_header_is_parsed(mail, field_idx);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen if (ret != -1) {
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return ret == 0 ? NULL :
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen index_mail_get_parsed_header(mail,
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen field_idx);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen }
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen }
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen /* parse */
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen headers[0] = field; headers[1] = NULL;
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen headers_ctx = mailbox_header_lookup_init(&mail->ibox->box,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen headers);
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen ret = index_mail_parse_headers(mail, headers_ctx);
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen mailbox_header_lookup_deinit(headers_ctx);
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen if (ret < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return NULL;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen ret = index_mail_header_is_parsed(mail, field_idx);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen i_assert(ret != -1);
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen return ret == 0 ? NULL :
98dd8e6e81f11f1e6040ca72f4916242d246c863Timo Sirainen index_mail_get_parsed_header(mail, field_idx);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen data = buffer_get_modifyable_data(dest, &len);
8f61542ca70f3f0dda15630447a00877b132efa8Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (len == 0) {
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen /* cached as non-existing. */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return p_new(mail->data_pool, const char *, 1);
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen }
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen ARRAY_CREATE(&header_values, mail->data_pool, const char *, 4);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* cached. skip "header name: " parts in dest. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < len; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (data[i] == ':') {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (i+1 != len && data[++i] == ' ') i++;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* @UNSAFE */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen len = get_header_size(dest, i);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen data[i + len] = '\0';
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen value = (const char *)data + i;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i += len + 1;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_append(&header_values, &value, sizeof(value));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen value = NULL;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen array_append(&header_values, &value, sizeof(value));
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return array_idx(&header_values, 0);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen}
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenconst char *index_mail_get_first_header(struct mail *mail, const char *field)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen{
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const char *const *list = index_mail_get_headers(mail, field);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen return list == NULL ? NULL : list[0];
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void header_cache_callback(struct message_header_line *hdr,
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen int *matched, void *context)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = context;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen if (hdr != NULL && hdr->eoh)
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen *matched = FALSE;
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (void)index_mail_parse_header(NULL, hdr, mail);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct istream *
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenindex_mail_get_header_stream(struct mail *_mail,
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen struct mailbox_header_lookup_ctx *_headers)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_header_lookup_ctx *headers =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (struct index_header_lookup_ctx *)_headers;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen string_t *dest;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen if (mail->data.save_bodystructure_header) {
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen /* we have to parse the header. */
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen if (index_mail_parse_headers(mail, _headers) < 0)
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen return NULL;
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen }
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dest = str_new(mail->data_pool, 256);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_cache_lookup_headers(mail->trans->cache_view, dest,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.seq, headers->idx,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen headers->count) > 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return i_stream_create_from_data(mail->data_pool,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_data(dest), str_len(dest));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* not in cache / error */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen p_free(mail->data_pool, dest);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (mail_get_stream(&mail->mail.mail, NULL, NULL) == NULL)
a24b0595f0f7d3925d4c9ac26fa503ff87c43e43Timo Sirainen return NULL;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail->data.filter_stream != NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_stream_unref(mail->data.filter_stream);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen index_mail_parse_header_init(mail, _headers);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail->data.filter_stream =
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen i_stream_create_header_filter(mail->data.stream,
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen HEADER_FILTER_INCLUDE |
185ed0142fbbfb86e7a98519e7c6f11ec00723cdTimo Sirainen HEADER_FILTER_HIDE_BODY,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen headers->name, headers->count,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen header_cache_callback, mail);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mail->data.filter_stream;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct mailbox_header_lookup_ctx *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenindex_header_lookup_init(struct mailbox *box, const char *const headers[])
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_cache_field *fields, header_field = {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen NULL, 0, MAIL_CACHE_FIELD_HEADER, 0,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen MAIL_CACHE_DECISION_TEMP
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen };
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_header_lookup_ctx *ctx;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *const *name;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char **sorted_headers;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pool_t pool;
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen unsigned int i, count;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen for (count = 0, name = headers; *name != NULL; name++)
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen count++;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_push();
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen if (count > 0) {
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen /* @UNSAFE: headers need to be sorted for filter stream. */
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen sorted_headers = t_new(const char *, count);
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen memcpy(sorted_headers, headers,
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen count * sizeof(*sorted_headers));
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen qsort(sorted_headers, count, sizeof(*sorted_headers),
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen strcasecmp_p);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen headers = sorted_headers;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
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 fields[i] = header_field;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen mail_cache_register_fields(ibox->cache, fields, count);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
bb92096bdd934cc19def61b5fb4644af6351b62dTimo Sirainen pool = pool_alloconly_create("index_header_lookup_ctx", 512);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx = p_new(pool, struct index_header_lookup_ctx, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx->ctx.box = box;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx->pool = pool;
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen ctx->count = count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen if (count > 0) {
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen ctx->idx = p_new(pool, unsigned int, count);
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen ctx->name = p_new(pool, const char *, count);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* @UNSAFE */
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen for (i = 0; i < count; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx->idx[i] = fields[i].idx;
d6a1fe8633cf50cdf9441a7f4c2171bbd562ca9bTimo Sirainen ctx->name[i] = p_strdup(pool, headers[i]);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen t_pop();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return &ctx->ctx;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid index_header_lookup_deinit(struct mailbox_header_lookup_ctx *_ctx)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct index_header_lookup_ctx *ctx =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen (struct index_header_lookup_ctx *)_ctx;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen pool_unref(ctx->pool);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen}