/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream.h"
#include "array.h"
#include "buffer.h"
#include "str.h"
#include "message-date.h"
#include "message-part-data.h"
#include "message-parser.h"
#include "message-header-decode.h"
#include "istream-tee.h"
#include "istream-header-filter.h"
#include "imap-envelope.h"
#include "imap-bodystructure.h"
#include "index-storage.h"
#include "index-mail.h"
const struct index_mail_line *l2)
{
int diff;
}
{
const unsigned char *header;
bool noncontiguous;
/* sort it first so fields are grouped together and ordered by
line number */
/* go through all the header lines we found */
/* matches and header lines are both sorted, all matches
until lines[i] weren't found */
match_idx < match_count) {
/* this header doesn't exist. remember that. */
HEADER_MATCH_FLAG_FOUND) == 0);
"", 0);
}
match_idx++;
}
if (match_idx < match_count) {
/* save index to first header line */
j = i + 1;
match_idx++;
}
/* header is already cached. skip over all the
header lines. */
for (j = i+1; j < count; j++) {
break;
}
continue;
}
/* buffer contains: { uint32_t line_num[], 0, header texts }
noncontiguous is just a small optimization.. */
buffer_set_used_size(buf, 0);
for (j = i+1; j < count; j++) {
break;
}
if (noncontiguous) {
for (; i < j; i++) {
}
i--;
} else {
}
}
/* this header doesn't exist. remember that. */
HEADER_MATCH_FLAG_FOUND) == 0);
}
}
}
static unsigned int
{
T_BEGIN {
} T_END;
return header_field.idx;
}
{
return TRUE;
return TRUE;
return FALSE;
}
{
unsigned int i, count;
pool_datastack_create(), &count);
for (i = 0; i < count; i++) {
continue;
continue;
}
}
struct mailbox_header_lookup_ctx *headers)
{
} else {
(HEADER_MATCH_SKIP_COUNT-1)) == 0);
if (mail->header_match_value == 0) {
/* wrapped, we'll have to clear the buffer */
}
}
}
}
}
}
/* register also all the other headers that exist in cache file */
T_BEGIN {
} T_END;
/* if we want sent date, it doesn't mean that we also want to cache
Date: header. if we have Date field's index set at this point we
know that we want it. otherwise add it and remember that we don't
want it cached. */
if (field_idx < match_count &&
/* cache Date: header */
data->save_sent_date) {
/* parse Date: header, but don't cache it. */
}
}
{
const unsigned int cache_field_envelope =
}
}
struct message_header_line *hdr,
struct index_mail *mail)
{
data->parse_line_num++;
if (data->save_bodystructure_header) {
}
if (data->save_envelope) {
}
/* end of headers */
T_BEGIN {
} T_END;
if (data->save_bodystructure_header) {
}
return;
}
T_BEGIN {
const char *cache_field_name =
} T_END;
}
/* we don't want this header. */
return;
}
/* beginning of a line. add the header name. */
/* remember that we saw this header so we don't add it to
cache as nonexistent. */
}
if (!hdr->no_newline)
}
}
static void
struct message_header_line *hdr,
struct index_mail *mail)
{
}
static void
struct index_mail *mail)
{
}
struct istream *
{
/* we're doing everything for now, figure out later if we want to
save them. */
/* Don't unnecessarily waste time generating a snippet, since it's
not as cheap as the others to generate. */
return input2;
}
{
const char *error;
}
}
} else {
data->parser_ctx =
}
}
struct mailbox_header_lookup_ctx *headers,
const char *reason)
{
return -1;
/* initialize bodystructure parsing in case we read the whole
message. */
mail);
} else {
/* just read the header */
}
if (index_mail_stream_check_failure(mail) < 0)
return -1;
return 0;
}
static void
struct index_mail *mail)
{
}
{
const unsigned int cache_field_envelope =
cache_field_envelope) > 0) {
return 0;
}
return -1;
}
/* we got the headers from cache - parse them to get the
envelope */
if (stream->stream_errno != 0) {
return -1;
}
}
return 0;
}
{
if (data[i] == '\n') {
if (i+1 == size ||
return i - pos;
}
}
}
unsigned int field_idx)
{
unsigned int count;
return -1;
}
{
const unsigned char *p = *data;
size_t i;
for (i = 0; i < len; i++) {
if (p[i] == ':')
break;
}
if (i == len)
return FALSE;
for (i++; i < len; i++) {
if (!IS_LWSP(p[i]))
break;
}
*data = p + i;
return TRUE;
}
static const char *const *
{
ARRAY(const char *) header_values;
const unsigned int *line_idx;
const char *value;
for (i = first_line_idx; i < lines_count; i++) {
break;
/* skip header: and drop ending LF */
value_end--;
value_end - value_start);
}
}
return array_idx(&header_values, 0);
}
static int
const char *const **value_r)
{
unsigned char *data;
unsigned int field_idx;
int ret;
ARRAY(const char *) header_values;
/* not in cache / error - first see if it's already parsed */
/* don't try to parse headers recursively. we're here
because message size was wrong and istream-mail
wants to log some cached headers. */
return -1;
}
/* parse */
headers);
if (ret < 0)
return -1;
}
/* not found */
return 0;
}
return 0;
}
if (len == 0) {
/* cached as nonexistent. */
return 0;
}
/* cached. skip "header name: " parts in dest. */
for (i = 0; i < len; i++) {
if (data[i] == ':') {
i++;
/* @UNSAFE */
i += len2 + 1;
}
}
return 0;
}
{
char *new_str;
unsigned int i, j;
for (i = 0; str[i] != '\0'; i++) {
if (str[i] == '\n')
break;
}
if (str[i] == '\0')
return 0;
/* @UNSAFE */
for (j = i; str[i] != '\0'; i++) {
if (str[i] == '\n') {
new_str[j++] = ' ';
i++;
if (str[i] == '\0')
break;
/* corrupted */
return -1;
}
} else {
}
}
new_str[j] = '\0';
return 0;
}
{
for (i = 0; i < len; i++) {
if (data[i] == '\0')
data[i] = ' ';
}
}
static int
unsigned int max_count)
{
unsigned int i, count;
for (i = 0; i < count; i++) {
str_truncate(str, 0);
/* unfold all lines into a single line */
return -1;
/* decode MIME encoded-words. decoding may also add new LFs. */
message_header_decode_utf8((const unsigned char *)input,
/* replace NULs with spaces */
}
}
decoded_list[i] = input;
}
*_list = decoded_list;
return 0;
}
bool decode_to_utf8, const char *const **value_r)
{
int ret;
return -1;
return 0;
if (!decode_to_utf8)
return 1;
T_BEGIN {
} T_END;
field);
} else {
break;
}
}
if (ret < 0) {
i_panic("BUG: Broken header %s for mail UID %u "
"wasn't fixed by re-parsing the header",
}
return 1;
}
bool decode_to_utf8, const char **value_r)
{
const char *const *list;
int ret;
return -1;
ret = 0;
break;
}
T_BEGIN {
} T_END;
field);
/* retry by parsing the full header */
} else {
break;
}
}
if (ret < 0) {
i_panic("BUG: Broken header %s for mail UID %u "
"wasn't fixed by re-parsing the header",
}
}
static void
struct message_header_line *hdr,
{
}
struct mailbox_header_lookup_ctx *headers,
{
const unsigned char *data;
/* 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. */
}
/* we have to parse the header. */
const char *reason =
return -1;
}
return 0;
}
/* not in cache / error */
if (not_found_count++ == 0)
first_not_found = i;
}
}
const char *reason;
if (not_found_count == 0)
reason = "BUG: all headers seem to exist in cache";
else {
"%u/%u headers not cached (first=%s)",
}
return -1;
return 0;
}