http-response-parser.c revision 1ec26e0b70ac7f8a4e3dfbc59aa77f572651d5ae
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainenhttp_response_parser_init(struct istream *input,
717a444a466280a84a468220f647fdcb9f3b546fTimo Sirainen /* FIXME: implement status line limit */
08f24237ccc177f5b3a09b24d8a725fa47e1ee32Timo Sirainen parser = i_new(struct http_response_parser, 1);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen http_message_parser_init(&parser->parser, input, hdr_limits, 0, TRUE);
797de45dcf6e24642ab347d5033beb92034b779dTimo Sirainenvoid http_response_parser_deinit(struct http_response_parser **_parser)
720692523ece4a549f7c589508d5693ee310f6b3Timo Sirainen struct http_response_parser *parser = *_parser;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainenhttp_response_parser_restart(struct http_response_parser *parser)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen http_message_parser_restart(&parser->parser, NULL);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic int http_response_parse_status(struct http_response_parser *parser)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen const size_t size = parser->parser.end - parser->parser.cur;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* status-code = 3DIGIT
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if (!i_isdigit(p[0]) || !i_isdigit(p[1]) || !i_isdigit(p[2]))
49b6e2d72cfaa5c244c798ddbae5b61489b0f728Timo Sirainen (p[0] - '0')*100 + (p[1] - '0')*10 + (p[2] - '0');
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic int http_response_parse_reason(struct http_response_parser *parser)
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen /* reason-phrase = *( HTAB / SP / VCHAR / obs-text )
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen // FIXME: limit length
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen while (p < parser->parser.end && http_char_is_text(*p))
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen pool = http_message_parser_get_pool(&parser->parser);
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainenstatic const char *_reply_sanitize(struct http_message_parser *parser)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen const unsigned char *p;
debb28d107fa06d26fd194fdac523cfb32809199Timo Sirainen unsigned int i;
4d4cd9cde9e01d4ad9354e6e30ac2f90d13042b2Timo Sirainen for (p = parser->cur, i = 0; p < parser->end && i < 20; p++, i++) {
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen if (*p == 0x0a)
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen else if (*p == 0x0d)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainenstatic int http_response_parse(struct http_response_parser *parser)
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen struct http_message_parser *_parser = &parser->parser;
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen /* RFC 7230, Section 3.1.2: Status Line
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen status-line = HTTP-version SP status-code SP reason-phrase CRLF
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen status-code = 3DIGIT
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen reason-phrase = *( HTAB / SP / VCHAR / obs-text )
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen parser->state = HTTP_RESPONSE_PARSE_STATE_VERSION;
f2767c736d72e6aa9a2aae5d0a9b89abae9e29e9Timo Sirainen /* fall through */
745f2c7424d88e368eff0a3a7650b352a9d1f0ddTimo Sirainen if ((ret=http_message_parse_version(_parser)) <= 0) {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen "Invalid HTTP version in response: %s",
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen parser->state = HTTP_RESPONSE_PARSE_STATE_SP1;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* fall through */
dba5754de32284b3149ddd5c9bb1701b05707752Timo Sirainen ("Expected ' ' after response version, but found %s",
b9a13c136b7c5803a8271878fcbbf5328f6e7f2aTimo Sirainen parser->state = HTTP_RESPONSE_PARSE_STATE_STATUS;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* fall through */
80cfaba9e253545cbcd08f84939b27cdbb4a50d0Aki Tuomi if ((ret=http_response_parse_status(parser)) <= 0) {
6795f542ed816a3c977085d4f74df1d62a37b690Timo Sirainen _parser->error = "Invalid HTTP status code in response";
b116c06e4d3609f07f1d9582a932ad3ea9ce7e15Stephan Bosch parser->state = HTTP_RESPONSE_PARSE_STATE_SP2;
eff0f02f2c8320c1bd4df72a281a92051d78b2b1Timo Sirainen /* fall through */
c8920d5f3df9663668ccd6412218eb28008f4e9aTimo Sirainen ("Expected ' ' after response status code, but found %s",
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen parser->state = HTTP_RESPONSE_PARSE_STATE_REASON;
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* fall through */
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen if ((ret=http_response_parse_reason(parser)) <= 0) {
c014f12e8268bf37ca2997e632ad7c22b8d04a84Timo Sirainen /* fall through */
8d59f06c9422fa49b538e23ffb06eddb23c6add2Timo Sirainen /* fall through */
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ("Expected line end after response, but found %s",
b9a13c136b7c5803a8271878fcbbf5328f6e7f2aTimo Sirainen parser->state = HTTP_RESPONSE_PARSE_STATE_HEADER;
i_unreached();
const unsigned char *begin;
int ret;
if (ret > 0)
if (ret < 0) {
return (http_date_parse
const char *hdrval;
int ret;
return ret;
return ret;
return ret;