Exemplo n.º 1
0
/**
 * Parse an HTTP parameter
 *
 * \param input      Pointer to current input byte. Updated on exit.
 * \param parameter  Pointer to location to receive on-heap parameter.
 * \return NSERROR_OK on success,
 * 	   NSERROR_NOMEM on memory exhaustion
 *
 * The returned parameter is owned by the caller.
 */
static nserror http_parse_parameter(const char **input,
		http_parameter **parameter)
{
	const char *pos = *input;
	char *name;
	char *value;
	http_parameter *param;
	nserror error;

	/* token "=" ( token | quoted-string ) */

	error = http_parse_token(&pos, &name);
	if (error != NSERROR_OK)
		return error;

	while (*pos == ' ' || *pos == '\t')
		pos++;

	if (*pos != '=') {
		value = strdup("");
		if (value == NULL) {
			free(name);
			return NSERROR_NOMEM;
		}
	} else {
		pos++;

		while (*pos == ' ' || *pos == '\t')
			pos++;

		if (*pos == '"')
			error = http_parse_quoted_string(&pos, &value);
		else
			error = http_parse_token(&pos, &value);

		if (error != NSERROR_OK) {
			free(name);
			return error;
		}
	}

	param = malloc(sizeof(*param));
	if (param == NULL) {
		free(value);
		free(name);
		return NSERROR_NOMEM;
	}

	param->next = NULL;
	param->name = name;
	param->value = value;

	*parameter = param;
	*input = pos;

	return NSERROR_OK;
}
Exemplo n.º 2
0
int http_parse_token_list_next(struct http_parser *parser,
	const char **token_r)
{
	/* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-21;
	     Appendix B:

	   For compatibility with legacy list rules, recipients SHOULD accept
	   empty list elements.  In other words, consumers would follow the list
	   productions:

	   #element => [ ( "," / element ) *( OWS "," [ OWS element ] ) ]
	   1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
	*/

	for (;;) {	
		if (http_parse_token(parser, token_r) > 0)
			break;
		http_parse_ows(parser);
		if (parser->cur >= parser->end || parser->cur[0] != ',')
			return 0;
		parser->cur++;
		http_parse_ows(parser);
	}

	return 1;
}
Exemplo n.º 3
0
int http_parse_token_or_qstring(struct http_parser *parser,
	const char **word_r)
{
	if (parser->cur >= parser->end)
		return 0;
	if (parser->cur[0] == '"')
		return http_parse_quoted_string(parser, word_r);
	return http_parse_token(parser, word_r);
}
static int
http_request_parse_expect_header(struct http_request_parser *parser,
	struct http_request *request, const struct http_header_field *hdr)
{
	struct http_message_parser *_parser = &parser->parser;
	struct http_parser hparser;
	bool parse_error = FALSE;
	unsigned int num_expectations = 0;

	/* Expect       = 1#expectation
	   expectation  = expect-name [ BWS "=" BWS expect-value ]
	                    *( OWS ";" [ OWS expect-param ] )
	   expect-param = expect-name [ BWS "=" BWS expect-value ]
	   expect-name  = token
	   expect-value = token / quoted-string
	 */
	http_parser_init(&hparser, (const unsigned char *)hdr->value, hdr->size);
	while (!parse_error) {
		const char *expect_name, *expect_value;

		/* expect-name */
		if (http_parse_token(&hparser, &expect_name) > 0) {
			num_expectations++;
			if (strcasecmp(expect_name, "100-continue") == 0) {
				request->expect_100_continue = TRUE;
			} else {
				/* http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-23
				     Section 5.1.1:

				   If all received Expect header field(s) are syntactically valid but
				   contain an expectation that the recipient does not understand or
				   cannot comply with, the recipient MUST respond with a 417
				   (Expectation Failed) status code.  A recipient of a syntactically
				   invalid Expectation header field MUST respond with a 4xx status code
				   other than 417.

				   --> Must check rest of expect header syntax before returning error.
				 */
				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Unknown Expectation `%s'", expect_name);
				}
			}

			/* BWS "=" BWS */
			http_parse_ows(&hparser);
			if (hparser.cur >= hparser.end)
				break;
			
			if (*hparser.cur == '=') {
				hparser.cur++;
				http_parse_ows(&hparser);

				/* value */
				if (http_parse_word(&hparser, &expect_value) <= 0) {
					parse_error = TRUE;
					break;
				}
		
				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Expectation `%s' has unexpected value", expect_name);
				}
			}

			/* *( OWS ";" [ OWS expect-param ] ) */
			while (!parse_error) {
				const char *attribute, *value;

				/* OWS ";" */
				http_parse_ows(&hparser);
				if (hparser.cur >= hparser.end || *hparser.cur != ';')
					break;
				hparser.cur++;
				http_parse_ows(&hparser);

				/* expect-param */
				if (http_parse_token(&hparser, &attribute) <= 0) {
					parse_error = TRUE;
					break;
				}

				/* BWS "=" BWS */
				http_parse_ows(&hparser);
				if (hparser.cur >= hparser.end || *hparser.cur != '=') {
					parse_error = TRUE;
					break;
				}
				hparser.cur++;
				http_parse_ows(&hparser);

				/* value */
				if (http_parse_word(&hparser, &value) <= 0) {
					parse_error = TRUE;
					break;
				}

				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Expectation `%s' has unknown parameter `'%s'",
							expect_name, attribute);
				}
			}
			if (parse_error)
				break;		
		}
		http_parse_ows(&hparser);
		if (hparser.cur >= hparser.end || *hparser.cur != ',')
			break;
		hparser.cur++;
		http_parse_ows(&hparser);
	}

	if (parse_error || hparser.cur < hparser.end) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
		_parser->error = "Invalid Expect header";
		return -1;
	}

	if (parser->error_code != HTTP_REQUEST_PARSE_ERROR_NONE)
		return -1;

	if (num_expectations == 0) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
		_parser->error = "Empty Expect header";
		return -1;
	}
	return 0;
}
Exemplo n.º 5
0
/* See http.h for documentation */
nserror http_parse_content_type(const char *header_value, char **media_type, 
		http_parameter **parameters)
{
	const char *pos = header_value;
	char *type;
	char *subtype = NULL;
	http_parameter *params = NULL;
	char *mime;
	size_t mime_len;
	nserror error;

	/* type "/" subtype *( ";" parameter ) */

	while (*pos == ' ' || *pos == '\t')
		pos++;

	error = http_parse_token(&pos, &type);
	if (error != NSERROR_OK)
		return error;

	while (*pos == ' ' || *pos == '\t')
		pos++;

	if (*pos == '/') {
		pos++;

		while (*pos == ' ' || *pos == '\t')
			pos++;

		error = http_parse_token(&pos, &subtype);
		if (error != NSERROR_OK) {
			free(type);
			return error;
		}

		while (*pos == ' ' || *pos == '\t')
			pos++;

		if (*pos == ';') {
			pos++;

			while (*pos == ' ' || *pos == '\t')
				pos++;

			error = http_parse_parameter_list(&pos, &params);
			if (error != NSERROR_OK) {
				free(subtype);
				free(type);
				return error;
			}
		}
	}

	/* <type> + <subtype> + '/' */
	mime_len = strlen(type) + (subtype != NULL ? strlen(subtype) : 0) + 1;

	mime = malloc(mime_len + 1);
	if (mime == NULL) {
		http_parameter_list_destroy(params);
		free(subtype);
		free(type);
		return NSERROR_OK;
	}

	sprintf(mime, "%s/%s", type, subtype != NULL ? subtype : "");

	free(subtype);
	free(type);

	*media_type = mime;
	*parameters = params;

	return NSERROR_OK;
}
Exemplo n.º 6
0
static int
http_request_parse_expect_header(struct http_request_parser *parser,
	struct http_request *request, const struct http_header_field *hdr)
{
	struct http_message_parser *_parser = &parser->parser;
	struct http_parser hparser;
	bool parse_error = FALSE;
	unsigned int num_expectations = 0;

	/* RFC 7231, Section 5.1.1:

	   Expect  = "100-continue"
	 */
	// FIXME: simplify; RFC 7231 discarded Expect extension mechanism
	http_parser_init(&hparser, (const unsigned char *)hdr->value, hdr->size);
	while (!parse_error) {
		const char *expect_name, *expect_value;

		/* expect-name */
		if (http_parse_token(&hparser, &expect_name) > 0) {
			num_expectations++;
			if (strcasecmp(expect_name, "100-continue") == 0) {
				request->expect_100_continue = TRUE;
			} else {
				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Unknown Expectation `%s'", expect_name);
				}
			}

			/* BWS "=" BWS */
			http_parse_ows(&hparser);
			if (hparser.cur >= hparser.end)
				break;
			
			if (*hparser.cur == '=') {
				hparser.cur++;
				http_parse_ows(&hparser);

				/* value */
				if (http_parse_token_or_qstring(&hparser, &expect_value) <= 0) {
					parse_error = TRUE;
					break;
				}
		
				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Expectation `%s' has unexpected value", expect_name);
				}
			}

			/* *( OWS ";" [ OWS expect-param ] ) */
			while (!parse_error) {
				const char *attribute, *value;

				/* OWS ";" */
				http_parse_ows(&hparser);
				if (hparser.cur >= hparser.end || *hparser.cur != ';')
					break;
				hparser.cur++;
				http_parse_ows(&hparser);

				/* expect-param */
				if (http_parse_token(&hparser, &attribute) <= 0) {
					parse_error = TRUE;
					break;
				}

				/* BWS "=" BWS */
				http_parse_ows(&hparser);
				if (hparser.cur >= hparser.end || *hparser.cur != '=') {
					parse_error = TRUE;
					break;
				}
				hparser.cur++;
				http_parse_ows(&hparser);

				/* value */
				if (http_parse_token_or_qstring(&hparser, &value) <= 0) {
					parse_error = TRUE;
					break;
				}

				if (parser->error_code == HTTP_REQUEST_PARSE_ERROR_NONE) {
					parser->error_code = HTTP_REQUEST_PARSE_ERROR_EXPECTATION_FAILED;
					_parser->error = t_strdup_printf
						("Expectation `%s' has unknown parameter `'%s'",
							expect_name, attribute);
				}
			}
			if (parse_error)
				break;		
		}
		http_parse_ows(&hparser);
		if (hparser.cur >= hparser.end || *hparser.cur != ',')
			break;
		hparser.cur++;
		http_parse_ows(&hparser);
	}

	if (parse_error || hparser.cur < hparser.end) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
		_parser->error = "Invalid Expect header";
		return -1;
	}

	if (parser->error_code != HTTP_REQUEST_PARSE_ERROR_NONE)
		return -1;

	if (num_expectations == 0) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BAD_REQUEST;
		_parser->error = "Empty Expect header";
		return -1;
	}
	return 0;
}