/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "buffer.h"
#include "istream.h"
#include "str.h"
#include "str-sanitize.h"
#include "http-parser.h"
#include "http-header.h"
#include "http-header-parser.h"
enum http_header_parse_state {
};
struct http_header_parser {
unsigned int field_count;
const char *error;
};
struct http_header_parser *
const struct http_header_limits *limits,
enum http_header_parse_flags flags)
{
return parser;
}
{
//i_stream_skip(ctx->input, ctx->skip);
}
{
parser->field_size = 0;
parser->field_count = 0;
}
{
/* field-name = token
token = 1*tchar
*/
return 0;
return -1;
}
return 1;
}
{
/* OWS = *( SP / HTAB )
; "optional" whitespace
*/
}
{
const unsigned char *first;
/* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text
*/
do {
}
break;
/* We'll be lenient here to accommodate for some bad servers. We just
drop offending characters */
return 0;
return 1;
}
static inline const char *_chr_sanitize(unsigned char c)
{
if (c >= 0x20 && c < 0x7F)
return t_strdup_printf("'%c'", c);
return t_strdup_printf("0x%02x", c);
}
{
int ret;
/* RFC 7230, Section 3.2: Header Fields
'header' = *( header-field CRLF ) CRLF
; Actually part of HTTP-message syntax
header-field = field-name ":" OWS field-value OWS
field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text
obs-fold = CRLF 1*( SP / HTAB )
; obsolete line folding
; see Section 3.2.4
*/
for (;;) {
/* last CRLF */
return 0;
break;
/* last LF */
break;
}
/* next line */
/* fall through */
return ret;
/* fall through */
("Expected ':' after header field name '%s', but found %s",
return -1;
}
return -1;
}
return -1;
}
/* fall through */
return ret;
/* fall through */
return ret;
/* fall through */
("Invalid character %s in content of header field '%s'",
return -1;
}
return 0;
/* fall through */
("Expected LF after CR at end of header field '%s', but found %s",
return -1;
}
return 0;
/* fall through */
/* obs-fold */
break;
}
/* next header line */
return 1;
("Encountered stray CR at beginning of header line, followed by %s",
return -1;
}
/* header fully parsed */
return 1;
default:
i_unreached();
}
}
i_unreached();
return -1;
}
const char **error_r)
{
const unsigned char *data;
int ret;
/* check header size limits */
*error_r = "Excessive header size";
return -1;
}
*error_r = "Excessive header field size";
return -1;
}
/* don't parse beyond header size limits */
}
return -1;
}
if (ret == 1) {
parser->field_size = 0;
/* trim trailing OWS */
while (size > 0 &&
size--;
} else {
}
return 1;
}
}
if (ret < 0) {
*error_r = "Premature end of input";
else
}
return ret;
}