diff options
author | Daniel Stenberg <daniel@haxx.se> | 2022-12-26 10:58:37 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2022-12-26 23:29:23 +0100 |
commit | 901392cbb7939f43b7e7ed2b39135b45416a2714 (patch) | |
tree | fd74a1a6370ba56fcd76cd15cb052d352fbcb076 /lib | |
parent | cf174810db32c362775349e9afe5543c0e9cc18b (diff) | |
download | curl-901392cbb7939f43b7e7ed2b39135b45416a2714.tar.gz |
urlapi: add CURLU_PUNYCODE
Allows curl_url_get() get the punycode version of host names for the
host name and URL parts.
Extend test 1560 to verify.
Closes #10109
Diffstat (limited to 'lib')
-rw-r--r-- | lib/idn.c | 30 | ||||
-rw-r--r-- | lib/idn.h | 8 | ||||
-rw-r--r-- | lib/strerror.c | 3 | ||||
-rw-r--r-- | lib/urlapi.c | 28 |
4 files changed, 56 insertions, 13 deletions
@@ -116,7 +116,7 @@ bool Curl_is_ASCII_name(const char *hostname) * Curl_idn_decode() returns an allocated IDN decoded string if it was * possible. NULL on error. */ -static char *Curl_idn_decode(const char *input) +static char *idn_decode(const char *input) { char *decoded = NULL; #ifdef USE_LIBIDN2 @@ -144,24 +144,29 @@ static char *Curl_idn_decode(const char *input) return decoded; } +char *Curl_idn_decode(const char *input) +{ + char *d = idn_decode(input); +#ifdef USE_LIBIDN2 + if(d) { + char *c = strdup(d); + idn2_free(d); + d = c; + } +#endif + return d; +} + /* * Frees data allocated by idnconvert_hostname() */ void Curl_free_idnconverted_hostname(struct hostname *host) { -#if defined(USE_LIBIDN2) if(host->encalloc) { - idn2_free(host->encalloc); /* must be freed with idn2_free() since this was - allocated by libidn */ + /* must be freed with idn2_free() if allocated by libidn */ + Curl_idn_free(host->encalloc); host->encalloc = NULL; } -#elif defined(USE_WIN32_IDN) - free(host->encalloc); /* must be freed with free() since this was - allocated by Curl_win32_idn_to_ascii */ - host->encalloc = NULL; -#else - (void)host; -#endif } #endif /* USE_IDN */ @@ -177,7 +182,7 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host) #ifdef USE_IDN /* Check name for non-ASCII and convert hostname if we can */ if(!Curl_is_ASCII_name(host->name)) { - char *decoded = Curl_idn_decode(host->name); + char *decoded = idn_decode(host->name); if(decoded) { /* successful */ host->encalloc = decoded; @@ -190,4 +195,3 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host) #endif return CURLE_OK; } - @@ -32,7 +32,15 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host); #if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) #define USE_IDN void Curl_free_idnconverted_hostname(struct hostname *host); +char *Curl_idn_decode(const char *input); +#ifdef USE_LIBIDN2 +#define Curl_idn_free(x) idn2_free(x) +#else +#define Curl_idn_free(x) free(x) +#endif + #else #define Curl_free_idnconverted_hostname(x) +#define Curl_idn_decode(x) NULL #endif #endif /* HEADER_CURL_IDN_H */ diff --git a/lib/strerror.c b/lib/strerror.c index b9a51e26b..3d7193509 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -550,6 +550,9 @@ curl_url_strerror(CURLUcode error) case CURLUE_BAD_USER: return "Bad user"; + case CURLUE_LACKS_IDN: + return "libcurl lacks IDN support"; + case CURLUE_LAST: break; } diff --git a/lib/urlapi.c b/lib/urlapi.c index b96af35ad..29238c7e3 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -33,6 +33,7 @@ #include "inet_pton.h" #include "inet_ntop.h" #include "strdup.h" +#include "idn.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -1379,6 +1380,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, char portbuf[7]; bool urldecode = (flags & CURLU_URLDECODE)?1:0; bool urlencode = (flags & CURLU_URLENCODE)?1:0; + bool punycode = FALSE; bool plusdecode = FALSE; (void)flags; if(!u) @@ -1408,6 +1410,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, case CURLUPART_HOST: ptr = u->host; ifmissing = CURLUE_NO_HOST; + punycode = (flags & CURLU_PUNYCODE)?1:0; break; case CURLUPART_ZONEID: ptr = u->zoneid; @@ -1460,6 +1463,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, char *options = u->options; char *port = u->port; char *allochost = NULL; + punycode = (flags & CURLU_PUNYCODE)?1:0; if(u->scheme && strcasecompare("file", u->scheme)) { url = aprintf("file://%s%s%s", u->path, @@ -1514,6 +1518,17 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, if(!allochost) return CURLUE_OUT_OF_MEMORY; } + else if(punycode) { + if(!Curl_is_ASCII_name(u->host)) { +#ifndef USE_IDN + return CURLUE_LACKS_IDN; +#else + allochost = Curl_idn_decode(u->host); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; +#endif + } + } else { /* only encode '%' in output host name */ char *host = u->host; @@ -1611,6 +1626,19 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, free(*part); *part = Curl_dyn_ptr(&enc); } + else if(punycode) { + if(!Curl_is_ASCII_name(u->host)) { +#ifndef USE_IDN + return CURLUE_LACKS_IDN; +#else + char *allochost = Curl_idn_decode(*part); + if(!allochost) + return CURLUE_OUT_OF_MEMORY; + free(*part); + *part = allochost; +#endif + } + } return CURLUE_OK; } |