1 #ifndef MESSAGE_PARSER_H 2 #define MESSAGE_PARSER_H 3 4 #include "message-header-parser.h" 5 #include "message-part.h" 6 7 enum message_parser_flags { 8 /* Don't return message bodies in message_blocks. */ 9 MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK = 0x01, 10 /* Buggy software creates Content-Type: headers without Mime-Version: 11 header. By default we allow this and assume message is MIME if 12 Content-Type: is found. This flag disables this. */ 13 MESSAGE_PARSER_FLAG_MIME_VERSION_STRICT = 0x02, 14 /* Return multipart (preamble and epilogue) blocks */ 15 MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS = 0x04, 16 /* Return --boundary lines */ 17 MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES = 0x08 18 }; 19 20 #define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100 21 #define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000 22 23 struct message_parser_settings { 24 enum message_header_parser_flags hdr_flags; 25 enum message_parser_flags flags; 26 27 /* Maximum nested MIME parts. 28 0 = MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS. */ 29 unsigned int max_nested_mime_parts; 30 /* Maximum MIME parts in total. 31 0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */ 32 unsigned int max_total_mime_parts; 33 }; 34 35 struct message_parser_ctx; 36 37 struct message_block { 38 /* Message part this block belongs to */ 39 struct message_part *part; 40 41 /* non-NULL if a header line was read */ 42 struct message_header_line *hdr; 43 44 /* hdr = NULL, size = 0 block returned at the end of headers for the 45 empty line between header and body (unless the header is truncated). 46 Later on data and size>0 is returned for blocks of mail body that 47 is read (see message_parser_flags for what is actually returned) */ 48 const unsigned char *data; 49 size_t size; 50 }; 51 52 /* called once with hdr = NULL at the end of headers */ 53 typedef void message_part_header_callback_t(struct message_part *part, 54 struct message_header_line *hdr, 55 void *context); 56 57 extern message_part_header_callback_t *null_message_part_header_callback; 58 59 /* Initialize message parser. part_spool specifies where struct message_parts 60 are allocated from. */ 61 struct message_parser_ctx * 62 message_parser_init(pool_t part_pool, struct istream *input, 63 const struct message_parser_settings *set); 64 /* Deinitialize message parser. The ctx must NOT have been created by 65 message_parser_init_from_parts(). */ 66 void message_parser_deinit(struct message_parser_ctx **ctx, 67 struct message_part **parts_r); 68 /* Use preparsed parts to speed up parsing. */ 69 struct message_parser_ctx * 70 message_parser_init_from_parts(struct message_part *parts, 71 struct istream *input, 72 const struct message_parser_settings *set); 73 /* Same as message_parser_deinit(), but return an error message describing 74 why the preparsed parts didn't match the message. This can also safely be 75 called even when preparsed parts weren't used - it'll always just return 76 success in that case. */ 77 int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx, 78 struct message_part **parts_r, 79 const char **error_r); 80 81 /* Read the next block of a message. Returns 1 if block is returned, 0 if 82 input stream is non-blocking and more data needs to be read, -1 when all is 83 done or error occurred (see stream's error status). */ 84 int message_parser_parse_next_block(struct message_parser_ctx *ctx, 85 struct message_block *block_r); 86 87 /* Read and parse header. */ 88 void message_parser_parse_header(struct message_parser_ctx *ctx, 89 struct message_size *hdr_size, 90 message_part_header_callback_t *callback, 91 void *context) ATTR_NULL(4); 92 #define message_parser_parse_header(ctx, hdr_size, callback, context) \ 93 message_parser_parse_header(ctx, hdr_size - \ 94 CALLBACK_TYPECHECK(callback, void (*)( \ 95 struct message_part *, \ 96 struct message_header_line *, typeof(context))), \ 97 (message_part_header_callback_t *)callback, context) 98 99 /* Read and parse body. If message is a MIME multipart or message/rfc822 100 message, hdr_callback is called for all headers. body_callback is called 101 for the body content. */ 102 void message_parser_parse_body(struct message_parser_ctx *ctx, 103 message_part_header_callback_t *hdr_callback, 104 void *context) ATTR_NULL(3); 105 #define message_parser_parse_body(ctx, callback, context) \ 106 message_parser_parse_body(ctx, \ 107 (message_part_header_callback_t *)callback, \ 108 (void *)((uintptr_t)context - CALLBACK_TYPECHECK(callback, \ 109 void (*)(struct message_part *, \ 110 struct message_header_line *, typeof(context))))) 111 112 #endif 113