http-request-parser.c revision 188297bee5a2fb1bd5130019da4cd1955b753e15
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream.h"
#include "http-parser.h"
#include "http-message-parser.h"
#include "http-request-parser.h"
enum http_request_parser_state {
};
struct http_request_parser {
struct http_message_parser parser;
struct http_request request;
unsigned int skipping_line:1;
};
{
struct http_request_parser *parser;
return parser;
}
{
}
static void
{
}
{
/* method = token
*/
p++;
return 0;
return 1;
}
{
/* We'll just parse anything up to the first SP or a control char.
We could also implement workarounds for buggy HTTP clients and
parse anything up to the HTTP-version and return 301 with the
target properly encoded. */
p++;
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);
}
const char **error_r)
{
int ret;
/* request-line = method SP request-target SP HTTP-version CRLF
*/
for (;;) {
return 0;
if (parser->skipping_line) {
/* second extra CRLF; not allowed */
*error_r = "Empty request line";
return -1;
}
/* HTTP/1.0 client sent one extra CRLF after body.
ignore it. */
break;
}
/* fall through */
if (ret < 0)
*error_r = "Invalid HTTP method in request";
return ret;
}
return 0;
/* fall through */
("Expected ' ' after request method, but found %s",
return -1;
}
return 0;
/* fall through */
if (ret < 0)
*error_r = "Invalid HTTP target in request";
return ret;
}
return 0;
/* fall through */
("Expected ' ' after request target, but found %s",
return -1;
}
return 0;
/* fall through */
if (ret < 0)
*error_r = "Invalid HTTP version in request";
return ret;
}
return 0;
/* fall through */
return 0;
/* fall through */
("Expected line end after request, but found %s",
return -1;
}
if (!parser->skipping_line) {
return 1;
}
break;
default:
i_unreached();
}
}
i_unreached();
return -1;
}
const char **error_r)
{
const unsigned char *begin;
int ret;
old_bytes)) > 0) {
return -1;
if (ret > 0)
return 1;
}
if (ret < 0) {
return 0;
*error_r = "Stream error";
return -1;
}
return 0;
}
struct http_request **request_r,
const char **error_r)
{
int ret;
/* make sure we finished streaming payload from previous request
before we continue. */
return ret;
/* HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
*/
return ret;
}
return ret;
return -1;
return 1;
}