From cf753f20cc2a8506c831a5cedd933e3e78417261 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 24 Jul 2016 13:24:45 +0100 Subject: Avoid using curl for URL unescaping. This moves us towards working without curl. --- utils/url.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 10 deletions(-) (limited to 'utils') diff --git a/utils/url.c b/utils/url.c index efbc7691e..3be983d78 100644 --- a/utils/url.c +++ b/utils/url.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -32,25 +33,80 @@ #include "utils/url.h" +/** + * Convert a hex digit to a hex value + * + * Must be called with valid hex char, results undefined otherwise. + * + * \param[in] c char to convert yo value + * \return the value of c + */ +static inline char xdigit_to_hex(char c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } else { + return c - 'a' + 10; + } +} + + /* exported interface documented in utils/url.h */ -nserror url_unescape(const char *str, size_t length, char **result) +nserror url_unescape(const char *str, size_t length, char **result_out) { - char *curlstr; - char *retstr; + const char *str_end; + size_t new_len; + char *res_pos; + char *result; + + if (length == 0) { + length = strlen(str); + } - curlstr = curl_unescape(str, length); - if (curlstr == NULL) { + result = malloc(length + 1); + if (result == NULL) { return NSERROR_NOMEM; } - retstr = strdup(curlstr); - curl_free(curlstr); + new_len = length; + + res_pos = result; + str_end = str + length; + if (length >= 3) { + str_end -= 2; + while (str < str_end) { + char c = *str; + char c1 = *(str + 1); + char c2 = *(str + 2); + + if (c == '%' && isxdigit(c1) && isxdigit(c2)) { + c = xdigit_to_hex(c1) << 4 | xdigit_to_hex(c2); + str += 2; + new_len -= 2; + } + *res_pos++ = c; + str++; + } + str_end += 2; + } - if (retstr == NULL) { - return NSERROR_NOMEM; + while (str < str_end) { + *res_pos++ = *str++; + } + + *res_pos++ = '\0'; + + if (new_len != length) { + /* Shrink wrap the allocaiton around the string */ + char *tmp = realloc(result, new_len + 1); + if (tmp != NULL) { + result = tmp; + } } - *result = retstr; + *result_out = result; return NSERROR_OK; } -- cgit v1.2.3