[dovecot-cvs] dovecot/src/lib-storage/index index-mail.c,NONE,1.1 index-mail.h,NONE,1.1

cras at procontrol.fi cras at procontrol.fi
Tue Jan 21 07:36:34 EET 2003


Update of /home/cvs/dovecot/src/lib-storage/index
In directory danu:/tmp/cvs-serv4972

Added Files:
	index-mail.c index-mail.h 
Log Message:
Forgot to add



--- NEW FILE: index-mail.c ---
/* Copyright (C) 2002 Timo Sirainen */

#include "lib.h"
#include "istream.h"
#include "message-address.h"
#include "message-date.h"
#include "message-part-serialize.h"
#include "imap-bodystructure.h"
#include "imap-envelope.h"
#include "mail-index.h"
#include "mail-index-util.h"
#include "mail-custom-flags.h"
#include "index-storage.h"
#include "index-mail.h"

#include <ctype.h>

static int get_envelope_header_field(const char *name,
				     enum imap_envelope_field *ret)
{
	*ret = (enum imap_envelope_field)-1;

	switch (i_toupper(*name)) {
	case 'B':
		if (strcasecmp(name, "bcc") == 0)
			*ret = IMAP_ENVELOPE_BCC;
		break;
	case 'C':
		if (strcasecmp(name, "cc") == 0)
			*ret = IMAP_ENVELOPE_CC;
		break;
	case 'D':
		if (strcasecmp(name, "date") == 0)
			*ret = IMAP_ENVELOPE_DATE;
		break;
	case 'F':
		if (strcasecmp(name, "from") == 0)
			*ret = IMAP_ENVELOPE_FROM;
		break;
	case 'I':
		if (strcasecmp(name, "in-reply-to") == 0)
			*ret = IMAP_ENVELOPE_IN_REPLY_TO;
		break;
	case 'M':
		if (strcasecmp(name, "message-id") == 0)
			*ret = IMAP_ENVELOPE_MESSAGE_ID;
		break;
	case 'R':
		if (strcasecmp(name, "reply-to") == 0)
			*ret = IMAP_ENVELOPE_REPLY_TO;
		break;
	case 'S':
		if (strcasecmp(name, "subject") == 0)
			*ret = IMAP_ENVELOPE_SUBJECT;
		if (strcasecmp(name, "sender") == 0)
			*ret = IMAP_ENVELOPE_SENDER;
		break;
	case 'T':
		if (strcasecmp(name, "to") == 0)
			*ret = IMAP_ENVELOPE_TO;
		break;
	}

	return *ret != (enum imap_envelope_field)-1;
}

static struct message_part *get_cached_parts(struct index_mail *mail)
{
	struct message_part *part;
	const void *part_data;
	const char *error;
	size_t part_size;

	part_data = mail->ibox->index->
		lookup_field_raw(mail->ibox->index, mail->data.rec,
				 DATA_FIELD_MESSAGEPART, &part_size);
	if (part_data == NULL) {
		mail->ibox->index->cache_fields_later(mail->ibox->index,
						      DATA_FIELD_MESSAGEPART);
		return NULL;
	}

	part = message_part_deserialize(mail->pool, part_data, part_size,
					&error);
	if (part == NULL) {
		index_set_corrupted(mail->ibox->index,
			"Corrupted cached message_part data (%s)", error);
		return NULL;
	}

	return part;
}

static char *get_cached_field(struct index_mail *mail,
			      enum mail_data_field field)
{
	const char *ret;

	ret = mail->ibox->index->lookup_field(mail->ibox->index,
					      mail->data.rec, field);
	if (ret == NULL)
		mail->ibox->index->cache_fields_later(mail->ibox->index, field);
	return p_strdup(mail->pool, ret);
}

static uoff_t get_cached_uoff_t(struct index_mail *mail,
				enum mail_data_field field,
				const char *field_name)
{
	const uoff_t *uoff_p;
	size_t size;

	uoff_p = mail->ibox->index->
		lookup_field_raw(mail->ibox->index, mail->data.rec,
				 field, &size);

	if (uoff_p == NULL)
		mail->ibox->index->cache_fields_later(mail->ibox->index, field);
	else if (size != sizeof(*uoff_p)) {
		index_set_corrupted(mail->ibox->index,
				    "Corrupted cached %s", field_name);
		uoff_p = NULL;
	}

	return uoff_p == NULL ? (uoff_t)-1 : *uoff_p;
}

static uoff_t get_cached_virtual_size(struct index_mail *mail)
{
	return get_cached_uoff_t(mail, DATA_HDR_VIRTUAL_SIZE, "virtual size");
}

static time_t get_cached_received_date(struct index_mail *mail)
{
	const time_t *time_p;
	size_t size;

	time_p = mail->ibox->index->
		lookup_field_raw(mail->ibox->index, mail->data.rec,
				 DATA_HDR_INTERNAL_DATE, &size);

	if (time_p == NULL) {
		mail->ibox->index->cache_fields_later(mail->ibox->index,
						      DATA_HDR_INTERNAL_DATE);
	} else if (size != sizeof(*time_p)) {
		index_set_corrupted(mail->ibox->index,
				    "Corrupted cached received time");
		time_p = NULL;
	}

	return time_p == NULL ? (time_t)-1 : *time_p;
}

static int open_stream(struct index_mail *mail, uoff_t position)
{
	int deleted;

	if (mail->data.stream == NULL) {
		mail->data.stream = mail->ibox->index->
			open_mail(mail->ibox->index, mail->data.rec,
				  &mail->data.received_date, &deleted);

		if (mail->data.stream == NULL)
			return FALSE;
	}

	i_stream_seek(mail->data.stream, position);
	return TRUE;
}

static void prepend_cached_header(struct index_mail *mail, const char *name)
{
	struct cached_header *hdr;

	hdr = p_new(mail->pool, struct cached_header, 1);
	hdr->name = name;
	hdr->name_len = strlen(name);

	hdr->next = mail->data.headers;
	mail->data.headers = hdr;
}

void index_mail_init_parse_header(struct index_mail *mail)
{
	const char *const *tmp;

	if (mail->wanted_headers != NULL) {
		for (tmp = mail->wanted_headers; *tmp != NULL; tmp++)
			prepend_cached_header(mail, *tmp);
	}
}

void index_mail_parse_header(struct message_part *part __attr_unused__,
			     const unsigned char *name, size_t name_len,
			     const unsigned char *value, size_t value_len,
			     void *context)
{
	struct index_mail *mail = context;
	struct index_mail_data *data = &mail->data;
	struct cached_header *hdr;

	if (data->save_envelope) {
		imap_envelope_parse_header(mail->pool, &data->envelope_data,
					   name, name_len, value, value_len);
	}

	if (name_len == 4 && data->save_sent_time &&
	    memcasecmp(name, "date",4) == 0) {
		if (!message_date_parse(value, value_len, &data->sent_time,
					&data->sent_timezone)) {
			/* 0 == parse error */
			data->sent_time = 0;
			data->sent_timezone = 0;
		}
		data->save_sent_time = FALSE;
	}

	if (name_len == 0) {
		/* end of headers */
		if (data->save_sent_time) {
			/* not found */
			data->sent_time = 0;
			data->sent_timezone = 0;
			data->save_sent_time = FALSE;
		}
	}

	for (hdr = data->headers; hdr != NULL; hdr = hdr->next) {
		if (hdr->name_len == name_len &&
		    memcasecmp(hdr->name, name, name_len) == 0) {
			/* save only the first header */
			if (hdr->value == NULL) {
				hdr->value = p_strndup(mail->pool,
						       value, value_len);
			}
			break;
		}
	}
}

static int parse_header(struct index_mail *mail)
{
	if (!open_stream(mail, 0))
		return FALSE;

        index_mail_init_parse_header(mail);
	message_parse_header(NULL, mail->data.stream, &mail->data.hdr_size,
			     index_mail_parse_header, mail);
	mail->data.parse_header = FALSE;
	mail->data.hdr_size_set = TRUE;

	return TRUE;
}

static const struct mail_full_flags *get_flags(struct mail *_mail)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;

	data->flags.flags = data->rec->msg_flags;
	data->flags.custom_flags =
		mail_custom_flags_list_get(mail->ibox->index->custom_flags);
	data->flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;

	if (data->rec->uid >= mail->ibox->index->first_recent_uid)
		data->flags.flags |= MAIL_RECENT;

	return &data->flags;
}

static const struct message_part *get_parts(struct mail *_mail)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;

	if (data->parts != NULL)
		return data->parts;

	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) == 0) {
		data->parts = get_cached_parts(mail);
		if (data->parts != NULL)
			return data->parts;
	}

	if (!open_stream(mail, 0))
		return NULL;

        index_mail_init_parse_header(mail);
	data->parts = message_parse(mail->pool, data->stream,
				    index_mail_parse_header, mail);
	return data->parts;
}

static time_t get_received_date(struct mail *_mail)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;

	if (data->received_date != (time_t)-1)
		return data->received_date;

	if ((mail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) == 0) {
		data->received_date = get_cached_received_date(mail);
		if (data->received_date != (time_t)-1)
			return data->received_date;
	}

	data->received_date = mail->ibox->index->
		get_internal_date(mail->ibox->index, mail->data.rec);
	return data->received_date;
}

static time_t get_date(struct mail *_mail, int *timezone)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;
	const char *result;

	if (data->sent_time != (time_t)-1) {
		if (timezone != NULL)
			*timezone = data->sent_timezone;
		return data->sent_time;
	}

	if (data->parse_header || data->envelope == NULL) {
		data->save_sent_time = TRUE;
		parse_header(mail);
	} else {
		if (!imap_envelope_parse(data->envelope,
					 IMAP_ENVELOPE_DATE,
					 IMAP_ENVELOPE_RESULT_TYPE_STRING,
					 &result))
			return (time_t)-1;

		if (!message_date_parse((const unsigned char *) result,
					(size_t)-1, &data->sent_time,
					&data->sent_timezone))
			data->sent_time = 0;
	}

	if (timezone != NULL)
		*timezone = data->sent_timezone;
	return data->sent_time;
}

static int get_msgpart_sizes(struct index_mail *mail)
{
	struct index_mail_data *data = &mail->data;

	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) != 0)
		(void)get_parts(&mail->mail);

	if (data->parts == NULL)
		data->parts = get_cached_parts(mail);

	if (data->parts != NULL) {
		data->hdr_size = data->parts->header_size;
		data->body_size = data->parts->body_size;
		data->hdr_size_set = TRUE;
		data->body_size_set = TRUE;
	}

	return data->parts != NULL;
}

static void get_binary_sizes(struct index_mail *mail)
{
	uoff_t size;

	if (!mail->data.hdr_size_set &&
	    (mail->data.rec->index_flags & INDEX_MAIL_FLAG_BINARY_HEADER)) {
		size = get_cached_uoff_t(mail, DATA_HDR_HEADER_SIZE,
					 "header size");
		if (size != (uoff_t)-1) {
			mail->data.hdr_size.physical_size =
				mail->data.hdr_size.virtual_size = size;
			mail->data.hdr_size_set = TRUE;
		}
	}

	if (!mail->data.body_size_set &&
	    (mail->data.rec->index_flags & INDEX_MAIL_FLAG_BINARY_BODY)) {
		size = get_cached_uoff_t(mail, DATA_HDR_BODY_SIZE, "body size");
		if (size != (uoff_t)-1) {
			mail->data.body_size.physical_size =
				mail->data.body_size.virtual_size = size;
			mail->data.body_size_set = TRUE;
		}
	}
}

static uoff_t get_size(struct mail *_mail)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;
	uoff_t hdr_size, body_size;

	if (data->size != (uoff_t)-1)
		return data->size;

	if ((mail->wanted_fields & MAIL_FETCH_SIZE) == 0) {
		data->size = get_cached_virtual_size(mail);
		if (data->size != (uoff_t)-1)
			return data->size;
	}

	if (!get_msgpart_sizes(mail)) {
		if (data->parse_header)
			parse_header(mail);
	}

	hdr_size = data->hdr_size_set ?
		data->hdr_size.virtual_size : (uoff_t)-1;
	body_size = data->body_size_set ?
		data->body_size.virtual_size : (uoff_t)-1;

	if (body_size != (uoff_t)-1 && hdr_size != (uoff_t)-1) {
		data->size = hdr_size + body_size;
		return data->size;
	}

	/* maybe it's binary */
	get_binary_sizes(mail);
	if (data->hdr_size_set && hdr_size == (uoff_t)-1)
		hdr_size = data->hdr_size.virtual_size;
	if (data->body_size_set && body_size == (uoff_t)-1)
		body_size = data->body_size.virtual_size;

	if (body_size != (uoff_t)-1 && hdr_size != (uoff_t)-1) {
		data->size = hdr_size + body_size;
		return data->size;
	}

	/* have to parse, slow.. */
	if (!open_stream(mail, hdr_size != (uoff_t)-1 ? hdr_size : 0))
		return (uoff_t)-1;

	if (hdr_size == (uoff_t)-1) {
		message_get_header_size(data->stream, &data->hdr_size);
		hdr_size = data->hdr_size.virtual_size;
		data->hdr_size_set = TRUE;
	}
	if (body_size == (uoff_t)-1) {
		message_get_body_size(data->stream, &data->body_size,
				      (uoff_t)-1, NULL);
		body_size = data->body_size.virtual_size;
		data->body_size_set = TRUE;
	}

	data->size = hdr_size + body_size;
	return data->size;
}

static const char *get_header(struct mail *_mail, const char *field)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;
	struct cached_header *hdr;
	enum imap_envelope_field env_field = 0;
	const char *str;
	char *ret;

	for (hdr = data->headers; hdr != NULL; hdr = hdr->next) {
		if (strcasecmp(hdr->name, field) == 0)
			return hdr->value;
	}

	if (data->parse_header || data->envelope == NULL ||
	    !get_envelope_header_field(field, &env_field)) {
		/* if we have to parse the header, do it even if we could use
		   envelope - envelope parsing would just slow up. */
                prepend_cached_header(mail, field);
		parse_header(mail);

		for (hdr = data->headers; hdr != NULL; hdr = hdr->next) {
			if (strcasecmp(hdr->name, field) == 0)
				return hdr->value;
		}

		return NULL;
	} else {
		t_push();
		if (!imap_envelope_parse(data->envelope, env_field,
					 IMAP_ENVELOPE_RESULT_TYPE_STRING,
					 &str))
			str = NULL;
		ret = p_strdup(mail->pool, str);
		t_pop();
		return ret;
	}
}

static const struct message_address *
get_address(struct mail *_mail, const char *field)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	const char *str;

	/* don't bother with checking envelope - we're most likely
	   creating it */
	str = get_header(_mail, field);
	if (str == NULL)
		return NULL;

	return message_address_parse(mail->pool, str, (size_t)-1, 1);
}

static const char *get_first_mailbox(struct mail *_mail, const char *field)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;
	enum imap_envelope_field env_field;
	const char *str;
	const char *ret = NULL;

	if (data->envelope != NULL &&
	    get_envelope_header_field(field, &env_field)) {
		/* prefer parsing envelope - faster than having to actually
		   parse the header field */
		t_push();
		if (!imap_envelope_parse(data->envelope, env_field,
					IMAP_ENVELOPE_RESULT_TYPE_FIRST_MAILBOX,
					&str))
			str = NULL;
		ret = p_strdup(mail->pool, str);
		t_pop();
	} else {
		struct message_address *addr;

		str = get_header(_mail, field);
		if (str == NULL)
			return NULL;

		addr = message_address_parse(mail->pool, str,
					     (size_t)-1, 1);
		if (addr != NULL)
			ret = addr->mailbox;
	}

	return ret;
}

static struct istream *get_stream(struct mail *_mail,
				  struct message_size *hdr_size,
				  struct message_size *body_size)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;

	if (!open_stream(mail, 0))
		return NULL;

	if (hdr_size != NULL || body_size != NULL) {
		if (!get_msgpart_sizes(mail))
			get_binary_sizes(mail);
	}

	if (hdr_size != NULL) {
		if (!data->hdr_size_set) {
			message_get_header_size(data->stream, &data->hdr_size);
			data->hdr_size_set = TRUE;
		}

		*hdr_size = data->hdr_size;
	}

	if (body_size != NULL) {
		if (!data->body_size_set) {
			i_stream_seek(data->stream,
				      data->hdr_size.physical_size);

			message_get_body_size(data->stream, &data->body_size,
					      (uoff_t)-1, NULL);
			data->body_size_set = TRUE;
		}

		*body_size = data->body_size;
	}

	i_stream_seek(data->stream, 0);
	return data->stream;
}

static const char *get_special(struct mail *_mail, enum mail_fetch_field field)
{
	struct index_mail *mail = (struct index_mail *) _mail;
	struct index_mail_data *data = &mail->data;
	char *str;

	switch (field) {
	case MAIL_FETCH_IMAP_BODY:
		if (data->body != NULL)
			return data->body;
		/* fall through */
	case MAIL_FETCH_IMAP_BODYSTRUCTURE:
		if (data->bodystructure != NULL) {
			if (field == MAIL_FETCH_IMAP_BODYSTRUCTURE)
				return data->bodystructure;

			/* create BODY from cached BODYSTRUCTURE */
			t_push();
			data->body = p_strdup(mail->pool,
				imap_body_parse_from_bodystructure(
							data->bodystructure));
			t_pop();
			return data->body;
		}

		if (data->parts == NULL)
			data->parts = get_cached_parts(mail);

		t_push();
		str = p_strdup(mail->pool, imap_part_get_bodystructure(
				mail->pool, &data->parts, data->stream,
				field == MAIL_FETCH_IMAP_BODYSTRUCTURE));
		t_pop();

		if (field == MAIL_FETCH_IMAP_BODYSTRUCTURE)
			data->bodystructure = str;
		else
			data->body = str;
		return str;
	case MAIL_FETCH_IMAP_ENVELOPE:
		if (data->envelope != NULL)
			return data->envelope;

		if ((mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE) == 0) {
			data->envelope = p_strdup(mail->pool,
				get_cached_field(mail, DATA_FIELD_ENVELOPE));
			if (data->envelope != NULL)
				return data->envelope;
		}

		data->save_envelope = TRUE;
		parse_header(mail);
		return data->envelope;
	default:
		i_unreached();
		return NULL;
	}
}

static struct mail index_mail = {
	0, 0, 0,

	get_flags,
	get_parts,
	get_received_date,
	get_date,
	get_size,
	get_header,
	get_address,
	get_first_mailbox,
	get_stream,
	get_special
};

void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
		     enum mail_fetch_field wanted_fields,
		     const char *const wanted_headers[])
{
	mail->mail = index_mail;
	mail->pool = pool_alloconly_create("index_mail", 4096);

	mail->ibox = ibox;
	mail->wanted_fields = wanted_fields;
	mail->wanted_headers = wanted_headers;
}

int index_mail_next(struct index_mail *mail, struct mail_index_record *rec)
{
	struct index_mail_data *data = &mail->data;
	int open_mail, parse_header;

	/* close the old one */
	if (data->stream != NULL)
		i_stream_unref(data->stream);

	memset(data, 0, sizeof(*data));
	p_clear(mail->pool);

	data->rec = rec;
	data->size = (uoff_t)-1;
	data->received_date = data->sent_time = (time_t)-1;

	/* if some wanted fields are cached, get them */
	if (mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS)
		data->parts = get_cached_parts(mail);
	if (mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE)
		data->envelope = get_cached_field(mail, DATA_FIELD_ENVELOPE);
	if (mail->wanted_fields & MAIL_FETCH_IMAP_BODY)
		data->body = get_cached_field(mail, DATA_FIELD_BODY);
	if (mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) {
		data->bodystructure =
			get_cached_field(mail, DATA_FIELD_BODYSTRUCTURE);
	}
	if (mail->wanted_fields & MAIL_FETCH_SIZE)
		data->size = get_cached_virtual_size(mail);

	/* see if we have to parse the message */
	open_mail = parse_header = FALSE;
	if ((mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) &&
	    data->parts == NULL)
		parse_header = TRUE;
	else if ((mail->wanted_fields & (MAIL_FETCH_DATE |
					 MAIL_FETCH_IMAP_ENVELOPE)) &&
		 data->envelope == NULL)
		parse_header = TRUE;
	else if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) &&
		 data->bodystructure == NULL) {
		if (data->parts == NULL)
			data->parts = get_cached_parts(mail);
		/* FIXME: this isn't helping really.. */
		open_mail = TRUE;
		parse_header = data->parts == NULL;
	} else if ((mail->wanted_fields & MAIL_FETCH_IMAP_BODY) &&
		   data->body == NULL && data->bodystructure == NULL) {
		if (data->parts == NULL)
			data->parts = get_cached_parts(mail);
		open_mail = TRUE;
		parse_header = data->parts == NULL;
	} else if (mail->wanted_fields & (MAIL_FETCH_STREAM_HEADER |
					  MAIL_FETCH_STREAM_BODY))
		open_mail = TRUE;
	else if ((mail->wanted_fields & MAIL_FETCH_SIZE) && data->size == 0)
		open_mail = TRUE;

	if (!parse_header && mail->wanted_headers != NULL) {
		const char *const *tmp;
		enum imap_envelope_field env_field;
		int envelope_headers = FALSE;

		for (tmp = mail->wanted_headers; *tmp != NULL; tmp++) {
			if (get_envelope_header_field(*tmp, &env_field))
				envelope_headers = TRUE;
			else {
				open_mail = TRUE;
				parse_header = TRUE;
				break;
			}
		}

		if (!parse_header && envelope_headers &&
		    data->envelope == NULL) {
			data->envelope =
				get_cached_field(mail, DATA_FIELD_ENVELOPE);
			if (data->envelope == NULL)
				parse_header = TRUE;
		}
	}

	if (open_mail || parse_header) {
		int deleted;

		data->stream = mail->ibox->index->
			open_mail(mail->ibox->index, data->rec,
				  &data->received_date, &deleted);
		if (data->stream == NULL)
			return deleted ? 0 : -1;
	}

	if ((mail->wanted_fields & MAIL_FETCH_RECEIVED_DATE) &&
	    data->received_date == (time_t)-1) {
		/* check this only after open_mail() */
		data->received_date = get_cached_received_date(mail);
	}

	if (mail->wanted_fields & MAIL_FETCH_DATE)
		data->save_sent_time = TRUE;
	if (mail->wanted_fields & MAIL_FETCH_IMAP_ENVELOPE)
		data->save_envelope = TRUE;

	data->parse_header = parse_header;
	return 1;
}

void index_mail_deinit(struct index_mail *mail)
{
	if (mail->data.stream != NULL) {
		i_stream_unref(mail->data.stream);
		mail->data.stream = NULL;
	}

	pool_unref(mail->pool);
	mail->pool = NULL;
}

--- NEW FILE: index-mail.h ---
#ifndef __INDEX_MAIL_H
#define __INDEX_MAIL_H

struct cached_header {
	struct cached_header *next;

	size_t name_len;
	const char *name, *value;
};

struct index_mail_data {
	struct mail_full_flags flags;
	time_t received_date;
	uoff_t size;

	time_t sent_time;
	int sent_timezone;

	struct cached_header *headers;
	struct message_part *parts;
	char *envelope, *body, *bodystructure;
        struct message_part_envelope_data *envelope_data;

	struct mail_index_record *rec;
	struct istream *stream;
        struct message_size hdr_size, body_size;

	unsigned int parse_header:1;
	unsigned int save_sent_time:1;
	unsigned int save_envelope:1;
	unsigned int hdr_size_set:1;
	unsigned int body_size_set:1;
};

struct index_mail {
	struct mail mail;
	struct index_mail_data data;

	pool_t pool;
	struct index_mailbox *ibox;

	enum mail_fetch_field wanted_fields;
	const char *const *wanted_headers;
};

void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
		     enum mail_fetch_field wanted_fields,
		     const char *const wanted_headers[]);
int index_mail_next(struct index_mail *mail, struct mail_index_record *rec);
void index_mail_deinit(struct index_mail *mail);

void index_mail_init_parse_header(struct index_mail *mail);
void index_mail_parse_header(struct message_part *part,
			     const unsigned char *name, size_t name_len,
			     const unsigned char *value, size_t value_len,
			     void *context);

#endif




More information about the dovecot-cvs mailing list