mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Add evhttp_parse_query_str_flags()
And a set of flags: - EVHTTP_URI_QUERY_LAST - EVHTTP_URI_QUERY_NONCONFORMANT Fixes: #15
This commit is contained in:
parent
d161ec3842
commit
26ef859aa7
23
http.c
23
http.c
@ -3216,7 +3216,7 @@ evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
|
||||
|
||||
static int
|
||||
evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
|
||||
int is_whole_uri)
|
||||
int is_whole_uri, unsigned flags)
|
||||
{
|
||||
char *line=NULL;
|
||||
char *argument;
|
||||
@ -3254,8 +3254,14 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
|
||||
|
||||
value = argument;
|
||||
key = strsep(&value, "=");
|
||||
if (value == NULL || *key == '\0') {
|
||||
goto error;
|
||||
if (flags & EVHTTP_URI_QUERY_NONCONFORMANT) {
|
||||
if (value == NULL)
|
||||
value = "";
|
||||
if (*key == '\0')
|
||||
continue;
|
||||
} else {
|
||||
if (value == NULL || *key == '\0')
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
|
||||
@ -3265,6 +3271,8 @@ evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
|
||||
evhttp_decode_uri_internal(value, strlen(value),
|
||||
decoded_value, 1 /*always_decode_plus*/);
|
||||
event_debug(("Query Param: %s -> %s\n", key, decoded_value));
|
||||
if (flags & EVHTTP_URI_QUERY_LAST_VAL)
|
||||
evhttp_remove_header(headers, key);
|
||||
evhttp_add_header_internal(headers, key, decoded_value);
|
||||
mm_free(decoded_value);
|
||||
}
|
||||
@ -3284,12 +3292,17 @@ done:
|
||||
int
|
||||
evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
|
||||
{
|
||||
return evhttp_parse_query_impl(uri, headers, 1);
|
||||
return evhttp_parse_query_impl(uri, headers, 1, 0);
|
||||
}
|
||||
int
|
||||
evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
|
||||
{
|
||||
return evhttp_parse_query_impl(uri, headers, 0);
|
||||
return evhttp_parse_query_impl(uri, headers, 0, 0);
|
||||
}
|
||||
int
|
||||
evhttp_parse_query_str_flags(const char *uri, struct evkeyvalq *headers, unsigned flags)
|
||||
{
|
||||
return evhttp_parse_query_impl(uri, headers, 0, flags);
|
||||
}
|
||||
|
||||
static struct evhttp_cb *
|
||||
|
@ -1004,6 +1004,33 @@ char *evhttp_uridecode(const char *uri, int decode_plus,
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
|
||||
|
||||
/** @see evhttp_parse_query_str_flags() */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers);
|
||||
|
||||
/** Tolerate queries that are not standard conformant.
|
||||
*
|
||||
* Here are some examples:
|
||||
*
|
||||
* - test=123&test2
|
||||
* with with this flag test2 will be present in the output headers
|
||||
*
|
||||
* - test=123&&test2=1
|
||||
* will parse the query with this flag
|
||||
*
|
||||
* - test=123&=456&test2=1
|
||||
* will parse the queyr with this flag, however there won't be empty key
|
||||
* present
|
||||
*/
|
||||
#define EVHTTP_URI_QUERY_NONCONFORMANT 0x01
|
||||
/** Prefer last value over the first from query args
|
||||
*
|
||||
* Example: test=123&test=456
|
||||
* Without: test=123
|
||||
* With : test=456
|
||||
*/
|
||||
#define EVHTTP_URI_QUERY_LAST_VAL 0x02
|
||||
|
||||
/**
|
||||
Helper function to parse out arguments from the query portion of an
|
||||
HTTP URI.
|
||||
@ -1019,10 +1046,11 @@ int evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
|
||||
|
||||
@param query_parse the query portion of the URI
|
||||
@param headers the head of the evkeyval queue
|
||||
@param flags one or more of EVHTTP_URI_QUERY_*
|
||||
@return 0 on success, -1 on failure
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers);
|
||||
int evhttp_parse_query_str_flags(const char *uri, struct evkeyvalq *headers, unsigned flags);
|
||||
|
||||
/**
|
||||
* Escape HTML character entities in a string.
|
||||
|
@ -2517,6 +2517,62 @@ http_parse_query_str_test(void *ptr)
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
end:
|
||||
evhttp_clear_headers(&headers);
|
||||
}
|
||||
static void
|
||||
http_parse_query_str_flags_test(void *ptr)
|
||||
{
|
||||
struct evkeyvalq headers;
|
||||
int r;
|
||||
|
||||
TAILQ_INIT(&headers);
|
||||
|
||||
/** ~EVHTTP_URI_QUERY_LAST_VAL */
|
||||
r = evhttp_parse_query_str_flags("q=test&q=test2", &headers, 0);
|
||||
tt_want(validate_header(&headers, "q", "test") == 0);
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
/** EVHTTP_URI_QUERY_LAST_VAL */
|
||||
r = evhttp_parse_query_str_flags("q=test&q=test2", &headers, EVHTTP_URI_QUERY_LAST_VAL);
|
||||
tt_want(validate_header(&headers, "q", "test2") == 0);
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
/** ~EVHTTP_URI_QUERY_NONCONFORMANT */
|
||||
r = evhttp_parse_query_str_flags("q=test&q2", &headers, 0);
|
||||
tt_int_op(r, ==, -1);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
r = evhttp_parse_query_str_flags("q=test&&q2=test2", &headers, 0);
|
||||
tt_int_op(r, ==, -1);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
r = evhttp_parse_query_str_flags("q=test&=1&q2=test2", &headers, 0);
|
||||
tt_int_op(r, ==, -1);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
/** EVHTTP_URI_QUERY_NONCONFORMANT */
|
||||
r = evhttp_parse_query_str_flags("q=test&q2", &headers, EVHTTP_URI_QUERY_NONCONFORMANT);
|
||||
tt_want(validate_header(&headers, "q", "test") == 0);
|
||||
tt_want(validate_header(&headers, "q2", "") == 0);
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
r = evhttp_parse_query_str_flags("q=test&&q2=test2", &headers, EVHTTP_URI_QUERY_NONCONFORMANT);
|
||||
tt_want(validate_header(&headers, "q", "test") == 0);
|
||||
tt_want(validate_header(&headers, "q2", "test2") == 0);
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
r = evhttp_parse_query_str_flags("q=test&=1&q2=test2", &headers, EVHTTP_URI_QUERY_NONCONFORMANT);
|
||||
tt_want(validate_header(&headers, "q", "test") == 0);
|
||||
tt_want(validate_header(&headers, "q2", "test2") == 0);
|
||||
tt_int_op(r, ==, 0);
|
||||
evhttp_clear_headers(&headers);
|
||||
|
||||
|
||||
end:
|
||||
evhttp_clear_headers(&headers);
|
||||
}
|
||||
@ -4826,6 +4882,7 @@ struct testcase_t http_testcases[] = {
|
||||
{ "bad_headers", http_bad_header_test, 0, NULL, NULL },
|
||||
{ "parse_query", http_parse_query_test, 0, NULL, NULL },
|
||||
{ "parse_query_str", http_parse_query_str_test, 0, NULL, NULL },
|
||||
{ "parse_query_str_flags", http_parse_query_str_flags_test, 0, NULL, NULL },
|
||||
{ "parse_uri", http_parse_uri_test, 0, NULL, NULL },
|
||||
{ "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
|
||||
{ "uriencode", http_uriencode_test, 0, NULL, NULL },
|
||||
|
Loading…
x
Reference in New Issue
Block a user