HTTP_HEADER_PARSE_STATE_CR,
HTTP_HEADER_PARSE_STATE_LF,
HTTP_HEADER_PARSE_STATE_NEW_LINE,
- HTTP_HEADER_PARSE_STATE_LAST_LINE,
HTTP_HEADER_PARSE_STATE_EOH
};
case HTTP_HEADER_PARSE_STATE_INIT:
buffer_set_used_size(parser->value_buf, 0);
str_truncate(parser->name, 0);
+ if (*parser->cur == '\r') {
+ /* last CRLF */
+ parser->cur++;
+ parser->state = HTTP_HEADER_PARSE_STATE_EOH;
+ if (parser->cur == parser->end)
+ return 0;
+ break;
+ } else if (*parser->cur == '\n') {
+ /* last LF */
+ parser->state = HTTP_HEADER_PARSE_STATE_EOH;
+ break;
+ }
+ /* next line */
parser->state = HTTP_HEADER_PARSE_STATE_NAME;
/* fall through */
case HTTP_HEADER_PARSE_STATE_NAME:
- if (http_char_is_token(*parser->cur)) {
- if ((ret=http_header_parse_name(parser)) <= 0)
- return ret;
- } else if (*parser->cur != ':' && str_len(parser->name) == 0) {
- parser->state = HTTP_HEADER_PARSE_STATE_LAST_LINE;
- break;
- }
+ if ((ret=http_header_parse_name(parser)) <= 0)
+ return ret;
parser->state = HTTP_HEADER_PARSE_STATE_COLON;
/* fall through */
case HTTP_HEADER_PARSE_STATE_COLON:
case HTTP_HEADER_PARSE_STATE_CR:
if (*parser->cur == '\r') {
parser->cur++;
+ } else if (*parser->cur != '\n') {
+ parser->error = t_strdup_printf
+ ("Invalid character %s in content of header field '%s'",
+ _chr_sanitize(*parser->cur),
+ str_sanitize(str_c(parser->name),64));
+ return -1;
}
parser->state = HTTP_HEADER_PARSE_STATE_LF;
if (parser->cur == parser->end)
case HTTP_HEADER_PARSE_STATE_LF:
if (*parser->cur != '\n') {
parser->error = t_strdup_printf
- ("Expected line end after header field '%s', but found %s",
+ ("Expected LF after CR at end of header field '%s', but found %s",
str_sanitize(str_c(parser->name),64),
_chr_sanitize(*parser->cur));
return -1;
buffer_append_c(parser->value_buf, ' ');
parser->state = HTTP_HEADER_PARSE_STATE_OWS;
break;
- }
+ }
+ /* next header line */
parser->state = HTTP_HEADER_PARSE_STATE_INIT;
return 1;
- case HTTP_HEADER_PARSE_STATE_LAST_LINE:
- if (*parser->cur == '\r') {
- /* last CRLF */
- parser->cur++;
- parser->state = HTTP_HEADER_PARSE_STATE_EOH;
- if (parser->cur == parser->end)
- return 0;
- break;
- } else if (*parser->cur == '\n') {
- /* header fully parsed */
- parser->cur++;
- parser->state = HTTP_HEADER_PARSE_STATE_EOH;
- return 1;
- }
- parser->error = t_strdup_printf
- ("Expected CRLF or header field name, but found %s",
- _chr_sanitize(*parser->cur));
- return -1;
case HTTP_HEADER_PARSE_STATE_EOH:
if (*parser->cur != '\n') {
parser->error = t_strdup_printf
- ("Expected LF after CR at end of header, but found %s",
+ ("Encountered stray CR at beginning of header line, followed by %s",
_chr_sanitize(*parser->cur));
return -1;
}
}
i_assert(ret != -2);
- if (ret < 0)
- *error_r = "Stream error";
+ if (ret < 0) {
+ if (i_stream_is_eof(parser->input))
+ *error_r = "Premature end of input";
+ else
+ *error_r = "Stream error";
+ }
return ret;
}