1 #ifndef MESSAGE_HEADER_PARSER_H
2 #define MESSAGE_HEADER_PARSER_H
3 
4 #define IS_LWSP(c) \
5 	((c) == ' ' || (c) == '\t')
6 
7 struct message_size;
8 struct message_header_parser_ctx;
9 
10 enum message_header_parser_flags {
11 	/* Don't add LWSP after "header: " to value. */
12 	MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP	= 0x01,
13 	/* Don't add CRs to full_value even if input had them */
14 	MESSAGE_HEADER_PARSER_FLAG_DROP_CR		= 0x02,
15 	/* Convert [CR+]LF+LWSP to a space character in full_value */
16 	MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE	= 0x04
17 };
18 
19 struct message_header_line {
20 	const char *name;
21 	size_t name_len;
22 
23 	const unsigned char *value;
24 	size_t value_len;
25 
26 	const unsigned char *full_value;
27 	size_t full_value_len;
28 
29 	const unsigned char *middle;
30 	size_t middle_len;
31 
32 	uoff_t name_offset, full_value_offset;
33 
34 	bool continues:1; /* multiline header, continues in next line */
35 	bool continued:1; /* multiline header, continues */
36 	bool eoh:1; /* "end of headers" line */
37 	bool no_newline:1; /* no \n after this line */
38 	bool crlf_newline:1; /* newline was \r\n */
39 	bool use_full_value:1; /* set if you want full_value */
40 };
41 
42 /* called once with hdr = NULL at the end of headers */
43 typedef void message_header_callback_t(struct message_header_line *hdr,
44 				       void *context);
45 
46 struct message_header_parser_ctx *
47 message_parse_header_init(struct istream *input, struct message_size *hdr_size,
48 			  enum message_header_parser_flags flags) ATTR_NULL(2);
49 void message_parse_header_deinit(struct message_header_parser_ctx **ctx);
50 
51 /* Read and return next header line. Returns 1 if header is returned, 0 if
52    input stream is non-blocking and more data needs to be read, -1 when all is
53    done or error occurred (see stream's error status). */
54 int message_parse_header_next(struct message_header_parser_ctx *ctx,
55 			      struct message_header_line **hdr_r);
56 
57 /* Returns TRUE if the parser has seen NUL characters. */
58 bool message_parse_header_has_nuls(const struct message_header_parser_ctx *ctx)
59 	ATTR_PURE;
60 
61 /* Read and parse the header from the given stream. */
62 void message_parse_header(struct istream *input, struct message_size *hdr_size,
63 			  enum message_header_parser_flags flags,
64 			  message_header_callback_t *callback, void *context)
65 	ATTR_NULL(2);
66 #define message_parse_header(input, hdr_size, flags, callback, context) \
67 	  message_parse_header(input, hdr_size, flags - \
68 		CALLBACK_TYPECHECK(callback, void (*)( \
69 			struct message_header_line *hdr, typeof(context))), \
70  		(message_header_callback_t *)callback, context)
71 
72 /* Write the header line to buffer exactly as it was read, including the
73    newline. */
74 void message_header_line_write(buffer_t *output,
75 			       const struct message_header_line *hdr);
76 
77 /* Duplicate the given header value data and return it. Replaces any NULs with
78    UNICODE_REPLACEMENT_CHAR_UTF8. */
79 const char *
80 message_header_strdup(pool_t pool, const unsigned char *data, size_t size);
81 
82 /* Returns TRUE if message header name is valid. */
83 bool message_header_name_is_valid(const char *name);
84 
85 #endif
86