From: Willy Tarreau Date: Tue, 31 May 2011 16:06:18 +0000 (+0200) Subject: [BUG] stats: support url-encoded forms X-Git-Tag: v1.5-dev8~224 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf9c2fcd938ab4996d4eb98823c6128014e4f1fe;p=thirdparty%2Fhaproxy.git [BUG] stats: support url-encoded forms Bashkim Kasa reported that the stats admin page did not work when colons were used in server or backend names. This was caused by url-encoding resulting in ':' being sent as '%3A'. Now we systematically decode the field names and values to fix this issue. --- diff --git a/include/common/standard.h b/include/common/standard.h index 0082087336..769aec6611 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -227,6 +227,13 @@ char *encode_string(char *start, char *stop, const char escape, const fd_set *map, const char *string); +/* Decode an URL-encoded string in-place. The resulting string might + * be shorter. If some forbidden characters are found, the conversion is + * aborted, the string is truncated before the issue and non-zero is returned, + * otherwise the operation returns non-zero indicating success. + */ +int url_decode(char *string); + /* This one is 6 times faster than strtoul() on athlon, but does * no check at all. */ diff --git a/src/proto_http.c b/src/proto_http.c index 1fc7c94b92..69232f9447 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2932,6 +2932,9 @@ int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn *value++ = '\0'; } + if (!url_decode(key) || !url_decode(value)) + break; + /* Now we can check the key to see what to do */ if (!backend && strcmp(key, "b") == 0) { backend = value; diff --git a/src/standard.c b/src/standard.c index d3b9ef7143..5c27bdbed6 100644 --- a/src/standard.c +++ b/src/standard.c @@ -601,6 +601,40 @@ char *encode_string(char *start, char *stop, return start; } +/* Decode an URL-encoded string in-place. The resulting string might + * be shorter. If some forbidden characters are found, the conversion is + * aborted, the string is truncated before the issue and non-zero is returned, + * otherwise the operation returns non-zero indicating success. + */ +int url_decode(char *string) +{ + char *in, *out; + int ret = 0; + + in = string; + out = string; + while (*in) { + switch (*in) { + case '+' : + *out++ = ' '; + break; + case '%' : + if (!ishex(in[1]) || !ishex(in[2])) + goto end; + *out++ = (hex2i(in[1]) << 4) + hex2i(in[2]); + in += 2; + break; + default: + *out++ = *in; + break; + } + in++; + } + ret = 1; /* success */ + end: + *out = 0; + return ret; +} unsigned int str2ui(const char *s) {