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