message-parser.h revision 0e0606d74a05d451b3438922b9a63ebf1755f838
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#ifndef MESSAGE_PARSER_H
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#define MESSAGE_PARSER_H
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#include "message-header-parser.h"
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen#include "message-size.h"
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenenum message_parser_flags {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* Don't return message bodies in message_blocks. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK = 0x01,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* Buggy software creates Content-Type: headers without Mime-Version:
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen header. By default we allow this and assume message is MIME if
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen Content-Type: is found. This flag disables this. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PARSER_FLAG_MIME_VERSION_STRICT = 0x02,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* Return multipart (preamble and epilogue) blocks */
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS = 0x04
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen};
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen/* Note that these flags are used directly by message-parser-serialize, so
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen existing flags can't be changed without breaking backwards compatibility */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenenum message_part_flags {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_MULTIPART = 0x01,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_MULTIPART_DIGEST = 0x02,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_MESSAGE_RFC822 = 0x04,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* content-type: text/... */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_TEXT = 0x08,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_UNUSED = 0x10,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* message part header or body contains NULs */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_HAS_NULS = 0x20,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* Mime-Version header exists. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen MESSAGE_PART_FLAG_IS_MIME = 0x40
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen};
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstruct message_part {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_part *parent;
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen struct message_part *next;
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen struct message_part *children;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen uoff_t physical_pos; /* absolute position from beginning of message */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_size header_size;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_size body_size;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen enum message_part_flags flags;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen void *context;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen};
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstruct message_parser_ctx;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstruct message_block {
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* Message part this block belongs to */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_part *part;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen /* non-NULL if a header line was read */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_header_line *hdr;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen /* hdr = NULL, size = 0 block returned at the end of headers */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen const unsigned char *data;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen size_t size;
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen};
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen/* called once with hdr = NULL at the end of headers */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainentypedef void message_part_header_callback_t(struct message_part *part,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_header_line *hdr,
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen void *context);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainenextern message_part_header_callback_t *null_message_part_header_callback;
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen/* Initialize message parser. part_spool specifies where struct message_parts
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen are allocated from. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstruct message_parser_ctx *
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenmessage_parser_init(pool_t part_pool, struct istream *input,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen enum message_header_parser_flags hdr_flags,
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen enum message_parser_flags flags);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen/* Use preparsed parts to speed up parsing. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenstruct message_parser_ctx *
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenmessage_parser_init_from_parts(struct message_part *parts,
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen struct istream *input,
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen enum message_header_parser_flags hdr_flags,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen enum message_parser_flags flags);
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen/* Returns 0 if parts were returned, -1 we used preparsed parts and they
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen didn't match the current message */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenint message_parser_deinit(struct message_parser_ctx **ctx,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_part **parts_r);
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen/* Read the next block of a message. Returns 1 if block is returned, 0 if
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen input stream is non-blocking and more data needs to be read, -1 when all is
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen done or error occurred (see stream's error status). */
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainenint message_parser_parse_next_block(struct message_parser_ctx *ctx,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_block *block_r);
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen/* Read and parse header. */
e62f6437a4ff01d692a5a61369fe4168d69191edTimo Sirainenvoid message_parser_parse_header(struct message_parser_ctx *ctx,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen struct message_size *hdr_size,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_part_header_callback_t *callback,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen void *context);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#ifdef CONTEXT_TYPE_SAFETY
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen# define message_parser_parse_header(ctx, hdr_size, callback, context) \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ({(void)(1 ? 0 : callback((struct message_part *)0, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (struct message_header_line *)0, context)); \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_parser_parse_header(ctx, hdr_size, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (message_part_header_callback_t *)callback, context); })
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#else
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen# define message_parser_parse_header(ctx, hdr_size, callback, context) \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_parser_parse_header(ctx, hdr_size, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (message_part_header_callback_t *)callback, context)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#endif
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen/* Read and parse body. If message is a MIME multipart or message/rfc822
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message, hdr_callback is called for all headers. body_callback is called
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen for the body content. */
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainenvoid message_parser_parse_body(struct message_parser_ctx *ctx,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_part_header_callback_t *hdr_callback,
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen void *context);
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#ifdef CONTEXT_TYPE_SAFETY
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen# define message_parser_parse_body(ctx, callback, context) \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen ({(void)(1 ? 0 : callback((struct message_part *)0, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (struct message_header_line *)0, context)); \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_parser_parse_body(ctx, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (message_part_header_callback_t *)callback, context); })
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#else
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen# define message_parser_parse_body(ctx, callback, context) \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen message_parser_parse_body(ctx, \
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen (message_part_header_callback_t *)callback, context)
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#endif
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen#endif
74ab5ea66c0c4b388f1c774ae6a47ab94f1b4f18Timo Sirainen