diff --git a/include/utils/http.h b/include/utils/http.h index 6a16957..fe8fc26 100644 --- a/include/utils/http.h +++ b/include/utils/http.h @@ -30,6 +30,7 @@ size_t rfc1123Gmt(char *, size_t, const time_t *); size_t rfc1123GmtNow(char *, size_t); +size_t urldecode(char *, size_t); char isHttpVersion(const char *, size_t); HttpMessage httpGetMessage( const char *, size_t, diff --git a/src/http/parser/p_post_vars.c b/src/http/parser/p_post_vars.c index b266940..361bf10 100644 --- a/src/http/parser/p_post_vars.c +++ b/src/http/parser/p_post_vars.c @@ -28,6 +28,8 @@ #include "hash.h" #include "class.h" +#include "utils/http.h" + /** * \todo this is very similar to other pair parsing * things... key1=val1key2=val2...keyn=valn @@ -40,6 +42,8 @@ httpParserPostVars(HttpParser this) char * pair = this->current->body; ssize_t togo = this->current->nbody; + togo = urldecode(pair, togo); + while(NULL != pair && 0 < togo) { char * key = pair; char * eqsign = memchr(key, '=', togo); diff --git a/src/utils/http.c b/src/utils/http.c index 04e9ec1..0001eaa 100644 --- a/src/utils/http.c +++ b/src/utils/http.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -33,6 +34,10 @@ #include "commons.h" +#define ALPHAVAL(x) (tolower((x)) - 'a' + 0xa) +#define DIGITVAL(x) ((x) - '0') +#define ALNUMVAL(x) (isdigit((x))?DIGITVAL((x)):ALPHAVAL((x))) + static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -68,6 +73,41 @@ rfc1123GmtNow(char * buffer, size_t _nbuf) return rfc1123Gmt(buffer, _nbuf, &t); } +/** + * Decode an url encoded string. This expects a valid url + * encoded string and it size as arguments, else the behaviour + * of this function is undefined. + * This function modifies the data in buffer. No copy is made. + * The reason for this is only performance. + */ +size_t +urldecode(char * buffer, size_t nbuffer) +{ + char * buf_ptr = buffer; + char * res_ptr = buffer; + + for(; 0 < nbuffer; nbuffer--, buf_ptr++, res_ptr++) { + switch(*buf_ptr) { + case '%': + *res_ptr = (ALNUMVAL(buf_ptr[1]) << 4) | ALNUMVAL(buf_ptr[2]); + buf_ptr += 2; + nbuffer -= 2; + break; + + case '+': + *buf_ptr = ' '; + /* intended drop through */ + + default: + *res_ptr = *buf_ptr; + break; + } + } + *res_ptr = 0; + + return res_ptr - buffer; +} + char isHttpVersion(const char * str, size_t len) {