From 7ee713ddd8b712a3de5b8bc8451cbf80352c285e Mon Sep 17 00:00:00 2001 From: John Marino Date: Thu, 1 Nov 2012 21:43:06 +0100 Subject: [PATCH] libfetch: Support percent-encoded user and password RFC 1738 specifies that any ":", "@", or "/" within a user name or password in a URL is percent-encoded, to avoid ambiguity with the use of those characters as URL component separators. Taken-From: FreeBSD SVN 234138 (12 APR 2012) --- lib/libfetch/fetch.c | 52 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c index 3f06c7eb0e..93d01ab956 100644 --- a/lib/libfetch/fetch.c +++ b/lib/libfetch/fetch.c @@ -26,7 +26,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/lib/libfetch/fetch.c,v 1.42 2008/12/17 18:00:18 murray Exp $ - * $DragonFly: src/lib/libfetch/fetch.c,v 1.3 2007/08/05 21:48:12 swildner Exp $ */ #include @@ -288,6 +287,49 @@ fetchMakeURL(const char *scheme, const char *host, int port, const char *doc, return (u); } +/* + * Return value of the given hex digit. + */ +static int +fetch_hexval(char ch) +{ + + if (ch >= '0' && ch <= '9') + return (ch - '0'); + else if (ch >= 'a' && ch <= 'f') + return (ch - 'a' + 10); + else if (ch >= 'A' && ch <= 'F') + return (ch - 'A' + 10); + return (-1); +} + +/* + * Decode percent-encoded URL component from src into dst, stopping at end + * of string, or at @ or : separators. Returns a pointer to the unhandled + * part of the input string (null terminator, @, or :). No terminator is + * written to dst (it is the caller's responsibility). + */ +static const char * +fetch_pctdecode(char *dst, const char *src, size_t dlen) +{ + int d1, d2; + char c; + const char *s; + + for (s = src; *s != '\0' && *s != '@' && *s != ':'; s++) { + if (s[0] == '%' && (d1 = fetch_hexval(s[1])) >= 0 && + (d2 = fetch_hexval(s[2])) >= 0 && (d1 > 0 || d2 > 0)) { + c = d1 << 4 | d2; + s += 2; + } else { + c = *s; + } + if (dlen-- > 0) + *dst++ = c; + } + return (s); +} + /* * Split an URL into components. URL syntax is: * [method:/][/[user[:pwd]@]host[:port]/][document] @@ -329,15 +371,11 @@ fetchParseURL(const char *URL) p = strpbrk(URL, "/@"); if (p && *p == '@') { /* username */ - for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) - if (i < URL_USERLEN) - u->user[i++] = *q; + q = fetch_pctdecode(u->user, URL, URL_USERLEN); /* password */ if (*q == ':') - for (q++, i = 0; (*q != ':') && (*q != '@'); q++) - if (i < URL_PWDLEN) - u->pwd[i++] = *q; + q = fetch_pctdecode(u->pwd, ++q, URL_PWDLEN); p++; } else { -- 2.41.0