index-mail-headers.c (dovecot-2.3.16) | : | index-mail-headers.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
#include "imap-bodystructure.h" | #include "imap-bodystructure.h" | |||
#include "index-storage.h" | #include "index-storage.h" | |||
#include "index-mail.h" | #include "index-mail.h" | |||
static const struct message_parser_settings msg_parser_set = { | static const struct message_parser_settings msg_parser_set = { | |||
.hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | | .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP | | |||
MESSAGE_HEADER_PARSER_FLAG_DROP_CR, | MESSAGE_HEADER_PARSER_FLAG_DROP_CR, | |||
.flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, | .flags = MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK, | |||
}; | }; | |||
static void index_mail_filter_stream_destroy(struct index_mail *mail); | ||||
static int header_line_cmp(const struct index_mail_line *l1, | static int header_line_cmp(const struct index_mail_line *l1, | |||
const struct index_mail_line *l2) | const struct index_mail_line *l2) | |||
{ | { | |||
int diff; | int diff; | |||
diff = (int)l1->field_idx - (int)l2->field_idx; | diff = (int)l1->field_idx - (int)l2->field_idx; | |||
return diff != 0 ? diff : | return diff != 0 ? diff : | |||
(int)l1->line_num - (int)l2->line_num; | (int)l1->line_num - (int)l2->line_num; | |||
} | } | |||
void index_mail_parse_header_deinit(struct index_mail *mail) | ||||
{ | ||||
mail->data.header_parser_initialized = FALSE; | ||||
} | ||||
static void index_mail_parse_header_finish(struct index_mail *mail) | static void index_mail_parse_header_finish(struct index_mail *mail) | |||
{ | { | |||
struct mail *_mail = &mail->mail.mail; | struct mail *_mail = &mail->mail.mail; | |||
const struct index_mail_line *lines; | const struct index_mail_line *lines; | |||
const unsigned char *header; | const unsigned char *header; | |||
const uint8_t *match; | const uint8_t *match; | |||
buffer_t *buf; | buffer_t *buf; | |||
unsigned int i, j, count, match_idx, match_count; | unsigned int i, j, count, match_idx, match_count; | |||
bool noncontiguous; | bool noncontiguous; | |||
skipping to change at line 137 | skipping to change at line 144 | |||
mail_cache_field_can_add(_mail->transaction->cache_trans, | mail_cache_field_can_add(_mail->transaction->cache_trans, | |||
_mail->seq, match_idx)) { | _mail->seq, match_idx)) { | |||
/* this header doesn't exist. remember that. */ | /* this header doesn't exist. remember that. */ | |||
i_assert((match[match_idx] & | i_assert((match[match_idx] & | |||
HEADER_MATCH_FLAG_FOUND) == 0); | HEADER_MATCH_FLAG_FOUND) == 0); | |||
index_mail_cache_add_idx(mail, match_idx, "", 0); | index_mail_cache_add_idx(mail, match_idx, "", 0); | |||
} | } | |||
} | } | |||
mail->data.dont_cache_field_idx = UINT_MAX; | mail->data.dont_cache_field_idx = UINT_MAX; | |||
mail->data.header_parser_initialized = FALSE; | index_mail_parse_header_deinit(mail); | |||
} | } | |||
static unsigned int | static unsigned int | |||
get_header_field_idx(struct mailbox *box, const char *field) | get_header_field_idx(struct mailbox *box, const char *field) | |||
{ | { | |||
struct mail_cache_field header_field; | struct mail_cache_field header_field; | |||
i_zero(&header_field); | i_zero(&header_field); | |||
header_field.type = MAIL_CACHE_FIELD_HEADER; | header_field.type = MAIL_CACHE_FIELD_HEADER; | |||
/* Always register with NO decision. The field should be added soon | /* Always register with NO decision. The field should be added soon | |||
skipping to change at line 198 | skipping to change at line 205 | |||
} | } | |||
} | } | |||
void index_mail_parse_header_init(struct index_mail *mail, | void index_mail_parse_header_init(struct index_mail *mail, | |||
struct mailbox_header_lookup_ctx *headers) | struct mailbox_header_lookup_ctx *headers) | |||
{ | { | |||
struct index_mail_data *data = &mail->data; | struct index_mail_data *data = &mail->data; | |||
const uint8_t *match; | const uint8_t *match; | |||
unsigned int i, field_idx, match_count; | unsigned int i, field_idx, match_count; | |||
index_mail_filter_stream_destroy(mail); | ||||
i_assert(!mail->data.header_parser_initialized); | i_assert(!mail->data.header_parser_initialized); | |||
mail->header_seq = data->seq; | mail->header_seq = data->seq; | |||
if (mail->header_data == NULL) { | if (mail->header_data == NULL) { | |||
mail->header_data = buffer_create_dynamic(default_pool, 4096); | mail->header_data = buffer_create_dynamic(default_pool, 4096); | |||
i_array_init(&mail->header_lines, 32); | i_array_init(&mail->header_lines, 32); | |||
i_array_init(&mail->header_match, 32); | i_array_init(&mail->header_match, 32); | |||
i_array_init(&mail->header_match_lines, 32); | i_array_init(&mail->header_match_lines, 32); | |||
mail->header_match_value = HEADER_MATCH_SKIP_COUNT; | mail->header_match_value = HEADER_MATCH_SKIP_COUNT; | |||
} else { | } else { | |||
skipping to change at line 428 | skipping to change at line 436 | |||
data->parts = NULL; | data->parts = NULL; | |||
} | } | |||
if (data->parts == NULL || data->parts != parts) { | if (data->parts == NULL || data->parts != parts) { | |||
/* The previous parsing didn't finish, so we're | /* The previous parsing didn't finish, so we're | |||
re-parsing the header. The new parts don't have data | re-parsing the header. The new parts don't have data | |||
filled anymore. */ | filled anymore. */ | |||
data->parsed_bodystructure_header = FALSE; | data->parsed_bodystructure_header = FALSE; | |||
} | } | |||
} | } | |||
/* make sure parsing starts from the beginning of the stream */ | ||||
i_stream_seek(mail->data.stream, 0); | ||||
if (data->parts == NULL) { | if (data->parts == NULL) { | |||
data->parser_input = data->stream; | data->parser_input = data->stream; | |||
data->parser_ctx = message_parser_init(mail->mail.data_pool, | data->parser_ctx = message_parser_init(mail->mail.data_pool, | |||
data->stream, | data->stream, | |||
&msg_parser_set); | &msg_parser_set); | |||
} else { | } else { | |||
data->parser_ctx = | data->parser_ctx = | |||
message_parser_init_from_parts(data->parts, | message_parser_init_from_parts(data->parts, | |||
data->stream, | data->stream, | |||
&msg_parser_set); | &msg_parser_set); | |||
skipping to change at line 466 | skipping to change at line 476 | |||
index_mail_parse_part_header_cb, | index_mail_parse_part_header_cb, | |||
mail); | mail); | |||
} else { | } else { | |||
/* just read the header */ | /* just read the header */ | |||
i_assert(!data->save_bodystructure_body || | i_assert(!data->save_bodystructure_body || | |||
data->parser_ctx != NULL); | data->parser_ctx != NULL); | |||
message_parse_header(data->stream, &data->hdr_size, | message_parse_header(data->stream, &data->hdr_size, | |||
msg_parser_set.hdr_flags, | msg_parser_set.hdr_flags, | |||
index_mail_parse_header_cb, mail); | index_mail_parse_header_cb, mail); | |||
} | } | |||
if (index_mail_stream_check_failure(mail) < 0) | if (index_mail_stream_check_failure(mail) < 0) { | |||
index_mail_parse_header_deinit(mail); | ||||
return -1; | return -1; | |||
} | ||||
i_assert(!mail->data.header_parser_initialized); | ||||
data->hdr_size_set = TRUE; | data->hdr_size_set = TRUE; | |||
data->access_part &= ENUM_NEGATE(PARSE_HDR); | data->access_part &= ENUM_NEGATE(PARSE_HDR); | |||
return 0; | return 0; | |||
} | } | |||
int index_mail_parse_headers(struct index_mail *mail, | int index_mail_parse_headers(struct index_mail *mail, | |||
struct mailbox_header_lookup_ctx *headers, | struct mailbox_header_lookup_ctx *headers, | |||
const char *reason) | const char *reason) | |||
{ | { | |||
struct index_mail_data *data = &mail->data; | struct index_mail_data *data = &mail->data; | |||
skipping to change at line 890 | skipping to change at line 903 | |||
} | } | |||
static void | static void | |||
header_cache_callback(struct header_filter_istream *input ATTR_UNUSED, | header_cache_callback(struct header_filter_istream *input ATTR_UNUSED, | |||
struct message_header_line *hdr, | struct message_header_line *hdr, | |||
bool *matched ATTR_UNUSED, struct index_mail *mail) | bool *matched ATTR_UNUSED, struct index_mail *mail) | |||
{ | { | |||
index_mail_parse_header(NULL, hdr, mail); | index_mail_parse_header(NULL, hdr, mail); | |||
} | } | |||
static void index_mail_filter_stream_destroy(struct index_mail *mail) | ||||
{ | ||||
if (mail->data.filter_stream == NULL) | ||||
return; | ||||
const unsigned char *data; | ||||
size_t size; | ||||
/* read through the previous filter_stream. this makes sure that the | ||||
fields are added to cache, and most importantly it resets | ||||
header_parser_initialized=FALSE so we don't assert on it. */ | ||||
while (i_stream_read_more(mail->data.filter_stream, &data, &size) > 0) | ||||
i_stream_skip(mail->data.filter_stream, size); | ||||
if (mail->data.header_parser_initialized) { | ||||
/* istream failed while reading the header */ | ||||
i_assert(mail->data.filter_stream->stream_errno != 0); | ||||
index_mail_parse_header_deinit(mail); | ||||
} | ||||
i_stream_destroy(&mail->data.filter_stream); | ||||
} | ||||
int index_mail_get_header_stream(struct mail *_mail, | int index_mail_get_header_stream(struct mail *_mail, | |||
struct mailbox_header_lookup_ctx *headers, | struct mailbox_header_lookup_ctx *headers, | |||
struct istream **stream_r) | struct istream **stream_r) | |||
{ | { | |||
struct index_mail *mail = INDEX_MAIL(_mail); | struct index_mail *mail = INDEX_MAIL(_mail); | |||
struct istream *input; | struct istream *input; | |||
string_t *dest; | string_t *dest; | |||
if (mail->data.filter_stream != NULL) { | index_mail_filter_stream_destroy(mail); | |||
const unsigned char *data; | ||||
size_t size; | ||||
/* read through the previous filter_stream. this makes sure | ||||
that the fields are added to cache, and most importantly it | ||||
resets header_parser_initialized=FALSE so we don't assert | ||||
on it. */ | ||||
while (i_stream_read_more(mail->data.filter_stream, &data, &size) | ||||
> 0) | ||||
i_stream_skip(mail->data.filter_stream, size); | ||||
i_stream_destroy(&mail->data.filter_stream); | ||||
} | ||||
if (mail->data.save_bodystructure_header) { | if (mail->data.save_bodystructure_header) { | |||
/* we have to parse the header. */ | /* we have to parse the header. */ | |||
const char *reason = | const char *reason = | |||
index_mail_cache_reason(_mail, "bodystructure"); | index_mail_cache_reason(_mail, "bodystructure"); | |||
if (index_mail_parse_headers(mail, headers, reason) < 0) | if (index_mail_parse_headers(mail, headers, reason) < 0) | |||
return -1; | return -1; | |||
} | } | |||
dest = str_new(mail->mail.data_pool, 256); | dest = str_new(mail->mail.data_pool, 256); | |||
End of changes. 9 change blocks. | ||||
15 lines changed or deleted | 37 lines changed or added |