http-response-parser.c revision 88ead42eefcad4af0313f55275de196f96e8f002
/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "istream.h"
#include "http-parser.h"
#include "http-date.h"
#include "http-message-parser.h"
#include "http-response-parser.h"
#include <ctype.h>
enum http_response_parser_state {
};
struct http_response_parser {
struct http_message_parser parser;
unsigned int response_status;
const char *response_reason;
};
struct http_response_parser *
const struct http_header_limits *hdr_limits)
{
struct http_response_parser *parser;
/* FIXME: implement status line limit */
return parser;
}
{
}
static void
{
parser->response_status = 0;
}
{
/* status-code = 3DIGIT
*/
if (size < 3)
return 0;
return -1;
(p[0] - '0')*100 + (p[1] - '0')*10 + (p[2] - '0');
return -1;
return 1;
}
{
/* reason-phrase = *( HTAB / SP / VCHAR / obs-text )
*/
// FIXME: limit length
p++;
return 0;
return 1;
}
{
const unsigned char *p;
unsigned int i;
bool quote_open = FALSE;
if (*p >= 0x20 && *p < 0x7F) {
if (!quote_open) {
quote_open = TRUE;
}
str_append_c(str, *p);
} else {
if (quote_open) {
quote_open = FALSE;
}
if (*p == 0x0a)
else if (*p == 0x0d)
else
}
}
if (quote_open)
}
{
int ret;
/* RFC 7230, Section 3.1.2: Status Line
status-line = HTTP-version SP status-code SP reason-phrase CRLF
status-code = 3DIGIT
reason-phrase = *( HTAB / SP / VCHAR / obs-text )
*/
/* fall through */
if (ret < 0)
"Invalid HTTP version in response: %s",
return ret;
}
return 0;
/* fall through */
("Expected ' ' after response version, but found %s",
return -1;
}
return 0;
/* fall through */
if (ret < 0)
return ret;
}
return 0;
/* fall through */
("Expected ' ' after response status code, but found %s",
return -1;
}
return 0;
/* fall through */
return 0;
}
return 0;
/* fall through */
return 0;
/* fall through */
("Expected line end after response, but found %s",
return -1;
}
return 1;
default:
break;
}
i_unreached();
return -1;
}
static int
{
const unsigned char *begin;
int ret;
old_bytes + 1)) > 0) {
return -1;
if (ret > 0)
return 1;
}
if (ret == -2) {
return -1;
}
if (ret < 0) {
return 0;
return -1;
}
return 0;
}
static int
{
/* RFC 7231, Section 7.1.3: Retry-After
The value of this field can be either an HTTP-date or a number of
seconds to delay after the response is received.
Retry-After = HTTP-date / delta-seconds
A delay-seconds value is a non-negative decimal integer, representing
time in seconds.
delta-seconds = 1*DIGIT
*/
return -1;
}
return 0;
}
return (http_date_parse
}
{
const char *hdrval;
int ret;
/* make sure we finished streaming payload from previous response
before we continue. */
return ret;
}
/* RFC 7230, Section 3:
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
*/
return ret;
}
}
return ret;
}
/* RFC 7230, Section 3.3.2: Content-Length
A server MUST NOT send a Content-Length header field in any response
with a status code of 1xx (Informational) or 204 (No Content).
*/
"Unexpected Content-Length header field for %u response "
return -1;
}
/* RFC 7230, Section 3.3.3: Message Body Length
1. Any response to a HEAD request and any response with a 1xx
(Informational), 204 (No Content), or 304 (Not Modified) status
code is always terminated by the first empty line after the
header fields, regardless of the header fields present in the
message, and thus cannot contain a message body.
*/
}
if ((payload_type == HTTP_RESPONSE_PAYLOAD_TYPE_ALLOWED) ||
/* [ message-body ] */
return -1;
}
}
/* RFC 7231, Section 7.1.3: Retry-After
Servers send the "Retry-After" header field to indicate how long the
user agent ought to wait before making a follow-up request. When
sent with a 503 (Service Unavailable) response, Retry-After indicates
how long the service is expected to be unavailable to the client.
When sent with any 3xx (Redirection) response, Retry-After indicates
the minimum time that the user agent is asked to wait before issuing
the redirected request.
*/
/* broken Retry-After header is ignored */
}
}
return 1;
}