]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
idn: rename the files to idn.[ch] and hold all IDN functions
authorDaniel Stenberg <daniel@haxx.se>
Wed, 14 Dec 2022 13:49:59 +0000 (14:49 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 15 Dec 2022 21:56:58 +0000 (22:56 +0100)
Closes #10094

lib/Makefile.inc
lib/idn.c [new file with mode: 0644]
lib/idn.h [moved from lib/idn_win32.h with 75% similarity]
lib/idn_win32.c [deleted file]
lib/smtp.c
lib/url.c
lib/url.h

index f50e941e86d38ce0fba899d2d2c46c7d611fca7f..9eafa93b9a356dd022fd70aa2278f2026bec7e88 100644 (file)
@@ -162,7 +162,7 @@ LIB_CFILES =         \
   http_ntlm.c        \
   http_proxy.c       \
   http_aws_sigv4.c   \
-  idn_win32.c        \
+  idn.c              \
   if2ip.c            \
   imap.c             \
   inet_ntop.c        \
@@ -293,6 +293,7 @@ LIB_HFILES =         \
   http_ntlm.h        \
   http_proxy.h       \
   http_aws_sigv4.h   \
+  idn.h              \
   if2ip.h            \
   imap.h             \
   inet_ntop.h        \
diff --git a/lib/idn.c b/lib/idn.c
new file mode 100644 (file)
index 0000000..6255221
--- /dev/null
+++ b/lib/idn.c
@@ -0,0 +1,193 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+ /*
+  * IDN conversions
+  */
+
+#include "curl_setup.h"
+#include "urldata.h"
+#include "idn.h"
+#include "sendf.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
+#ifdef USE_LIBIDN2
+#include <idn2.h>
+
+#if defined(WIN32) && defined(UNICODE)
+#define IDN2_LOOKUP(name, host, flags)                                  \
+  idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
+#else
+#define IDN2_LOOKUP(name, host, flags)                          \
+  idn2_lookup_ul((const char *)name, (char **)host, flags)
+#endif
+#endif  /* USE_LIBIDN2 */
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef USE_WIN32_IDN
+/* using Windows kernel32 and normaliz libraries. */
+
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x600
+WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
+                                 const WCHAR *lpUnicodeCharStr,
+                                 int cchUnicodeChar,
+                                 WCHAR *lpASCIICharStr,
+                                 int cchASCIIChar);
+WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
+                                   const WCHAR *lpASCIICharStr,
+                                   int cchASCIIChar,
+                                   WCHAR *lpUnicodeCharStr,
+                                   int cchUnicodeChar);
+#endif
+
+#define IDN_MAX_LENGTH 255
+
+bool Curl_win32_idn_to_ascii(const char *in, char **out)
+{
+  bool success = FALSE;
+
+  wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
+  if(in_w) {
+    wchar_t punycode[IDN_MAX_LENGTH];
+    int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
+    curlx_unicodefree(in_w);
+    if(chars) {
+      char *mstr = curlx_convert_wchar_to_UTF8(punycode);
+      if(mstr) {
+        *out = strdup(mstr);
+        curlx_unicodefree(mstr);
+        if(*out)
+          success = TRUE;
+      }
+    }
+  }
+
+  return success;
+}
+
+#endif /* USE_WIN32_IDN */
+
+/*
+ * Helpers for IDNA conversions.
+ */
+bool Curl_is_ASCII_name(const char *hostname)
+{
+  /* get an UNSIGNED local version of the pointer */
+  const unsigned char *ch = (const unsigned char *)hostname;
+
+  if(!hostname) /* bad input, consider it ASCII! */
+    return TRUE;
+
+  while(*ch) {
+    if(*ch++ & 0x80)
+      return FALSE;
+  }
+  return TRUE;
+}
+
+#ifdef USE_IDN
+/*
+ * Curl_idn_decode() returns an allocated IDN decoded string if it was
+ * possible. NULL on error.
+ */
+static char *Curl_idn_decode(const char *input)
+{
+  char *decoded = NULL;
+#ifdef USE_LIBIDN2
+  if(idn2_check_version(IDN2_VERSION)) {
+    int flags = IDN2_NFC_INPUT
+#if IDN2_VERSION_NUMBER >= 0x00140000
+      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
+         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
+         processing. */
+      | IDN2_NONTRANSITIONAL
+#endif
+      ;
+    int rc = IDN2_LOOKUP(input, &decoded, flags);
+    if(rc != IDN2_OK)
+      /* fallback to TR46 Transitional mode for better IDNA2003
+         compatibility */
+      rc = IDN2_LOOKUP(input, &decoded, IDN2_TRANSITIONAL);
+    if(rc != IDN2_OK)
+      decoded = NULL;
+  }
+#elif defined(USE_WIN32_IDN)
+  if(!Curl_win32_idn_to_ascii(input, &decoded))
+    decoded = NULL;
+#endif
+  return decoded;
+}
+
+/*
+ * 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 */
+    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 */
+
+/*
+ * Perform any necessary IDN conversion of hostname
+ */
+CURLcode Curl_idnconvert_hostname(struct hostname *host)
+{
+  /* set the name we use to display the host name */
+  host->dispname = host->name;
+
+#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);
+    if(decoded) {
+      /* successful */
+      host->encalloc = decoded;
+      /* change the name pointer to point to the encoded hostname */
+      host->name = host->encalloc;
+    }
+    else
+      return CURLE_URL_MALFORMAT;
+  }
+#endif
+  return CURLE_OK;
+}
+
similarity index 75%
rename from lib/idn_win32.h
rename to lib/idn.h
index 8a76403368306d8addece66a9e23f8dbe67ef937..2d04efcdfff2c10220c0fcbfd2f855efc1069c78 100644 (file)
+++ b/lib/idn.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_IDN_WIN32_H
-#define HEADER_CURL_IDN_WIN32_H
+#ifndef HEADER_CURL_IDN_H
+#define HEADER_CURL_IDN_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
  ***************************************************************************/
 
 #ifdef USE_WIN32_IDN
-
 bool Curl_win32_idn_to_ascii(const char *in, char **out);
-
 #endif /* USE_WIN32_IDN */
-#endif /* HEADER_CURL_IDN_WIN32_H */
+bool Curl_is_ASCII_name(const char *hostname);
+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);
+#else
+#define Curl_free_idnconverted_hostname(x)
+#endif
+#endif /* HEADER_CURL_IDN_H */
diff --git a/lib/idn_win32.c b/lib/idn_win32.c
deleted file mode 100644 (file)
index b3088be..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
- /*
-  * IDN conversions using Windows kernel32 and normaliz libraries.
-  */
-
-#include "curl_setup.h"
-
-#ifdef USE_WIN32_IDN
-#include "idn_win32.h"
-#include "curl_multibyte.h"
-#include "curl_memory.h"
-#include "warnless.h"
-
-  /* The last #include file should be: */
-#include "memdebug.h"
-
-#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x600
-WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
-                                 const WCHAR *lpUnicodeCharStr,
-                                 int cchUnicodeChar,
-                                 WCHAR *lpASCIICharStr,
-                                 int cchASCIIChar);
-WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
-                                   const WCHAR *lpASCIICharStr,
-                                   int cchASCIIChar,
-                                   WCHAR *lpUnicodeCharStr,
-                                   int cchUnicodeChar);
-#endif
-
-#define IDN_MAX_LENGTH 255
-
-bool Curl_win32_idn_to_ascii(const char *in, char **out)
-{
-  bool success = FALSE;
-
-  wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
-  if(in_w) {
-    wchar_t punycode[IDN_MAX_LENGTH];
-    int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
-    curlx_unicodefree(in_w);
-    if(chars) {
-      char *mstr = curlx_convert_wchar_to_UTF8(punycode);
-      if(mstr) {
-        *out = strdup(mstr);
-        curlx_unicodefree(mstr);
-        if(*out)
-          success = TRUE;
-      }
-    }
-  }
-
-  return success;
-}
-
-#endif /* USE_WIN32_IDN */
index cb066d70ecc6dc646fa8af578dcdd1d2b0e4abd5..6d0783f458783aca7b51980f7a81f8487fc5d24f 100644 (file)
@@ -83,6 +83,7 @@
 #include "bufref.h"
 #include "curl_sasl.h"
 #include "warnless.h"
+#include "idn.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -105,7 +106,7 @@ static CURLcode smtp_setup_connection(struct Curl_easy *data,
 static CURLcode smtp_parse_url_options(struct connectdata *conn);
 static CURLcode smtp_parse_url_path(struct Curl_easy *data);
 static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
-static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
+static CURLcode smtp_parse_address(const char *fqma,
                                    char **address, struct hostname *host);
 static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech,
                                   const struct bufref *initresp);
@@ -541,7 +542,7 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
 
       /* Parse the mailbox to verify into the local address and host name
          parts, converting the host name to an IDN A-label if necessary */
-      result = smtp_parse_address(data, smtp->rcpt->data,
+      result = smtp_parse_address(smtp->rcpt->data,
                                   &address, &host);
       if(result)
         return result;
@@ -615,7 +616,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
 
     /* Parse the FROM mailbox into the local address and host name parts,
        converting the host name to an IDN A-label if necessary */
-    result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
+    result = smtp_parse_address(data->set.str[STRING_MAIL_FROM],
                                 &address, &host);
     if(result)
       return result;
@@ -653,7 +654,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
 
       /* Parse the AUTH mailbox into the local address and host name parts,
          converting the host name to an IDN A-label if necessary */
-      result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
+      result = smtp_parse_address(data->set.str[STRING_MAIL_AUTH],
                                   &address, &host);
       if(result) {
         free(from);
@@ -790,7 +791,7 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
 
   /* Parse the recipient mailbox into the local address and host name parts,
      converting the host name to an IDN A-label if necessary */
-  result = smtp_parse_address(data, smtp->rcpt->data,
+  result = smtp_parse_address(smtp->rcpt->data,
                               &address, &host);
   if(result)
     return result;
@@ -1782,8 +1783,8 @@ static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
  * calling function deems it to be) then the input will simply be returned in
  * the address part with the host name being NULL.
  */
-static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
-                                   char **address, struct hostname *host)
+static CURLcode smtp_parse_address(const char *fqma, char **address,
+                                   struct hostname *host)
 {
   CURLcode result = CURLE_OK;
   size_t length;
@@ -1807,7 +1808,7 @@ static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
     host->name = host->name + 1;
 
     /* Attempt to convert the host name to IDN ACE */
-    (void) Curl_idnconvert_hostname(data, host);
+    (void) Curl_idnconvert_hostname(host);
 
     /* If Curl_idnconvert_hostname() fails then we shall attempt to continue
        and send the host name using UTF-8 rather than as 7-bit ACE (which is
index 4f88fa984630bafb23cd2c5709b1ca934c9030b5..3ab63a068f585a9b91c4d9144b7ef53b0523bf73 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
 
 #include <limits.h>
 
-#ifdef USE_LIBIDN2
-#include <idn2.h>
-
-#if defined(WIN32) && defined(UNICODE)
-#define IDN2_LOOKUP(name, host, flags) \
-  idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
-#else
-#define IDN2_LOOKUP(name, host, flags) \
-  idn2_lookup_ul((const char *)name, (char **)host, flags)
-#endif
-#elif defined(USE_WIN32_IDN)
-#include "idn.h"
-#endif  /* USE_LIBIDN2 */
-
 #include "doh.h"
 #include "urldata.h"
 #include "netrc.h"
-
 #include "formdata.h"
 #include "mime.h"
 #include "vtls/vtls.h"
 #include "hsts.h"
 #include "noproxy.h"
 #include "cfilters.h"
+#include "idn.h"
 
 /* And now for the protocols */
 #include "ftp.h"
@@ -1548,111 +1534,6 @@ void Curl_verboseconnect(struct Curl_easy *data,
 }
 #endif
 
-/*
- * Helpers for IDNA conversions.
- */
-bool Curl_is_ASCII_name(const char *hostname)
-{
-  /* get an UNSIGNED local version of the pointer */
-  const unsigned char *ch = (const unsigned char *)hostname;
-
-  if(!hostname) /* bad input, consider it ASCII! */
-    return TRUE;
-
-  while(*ch) {
-    if(*ch++ & 0x80)
-      return FALSE;
-  }
-  return TRUE;
-}
-
-/*
- * Perform any necessary IDN conversion of hostname
- */
-CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
-                                  struct hostname *host)
-{
-#ifndef USE_LIBIDN2
-  (void)data;
-  (void)data;
-#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void)data;
-#endif
-
-  /* set the name we use to display the host name */
-  host->dispname = host->name;
-
-  /* Check name for non-ASCII and convert hostname to ACE form if we can */
-  if(!Curl_is_ASCII_name(host->name)) {
-#ifdef USE_LIBIDN2
-    if(idn2_check_version(IDN2_VERSION)) {
-      char *ace_hostname = NULL;
-#if IDN2_VERSION_NUMBER >= 0x00140000
-      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
-         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
-         processing. */
-      int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
-#else
-      int flags = IDN2_NFC_INPUT;
-#endif
-      int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags);
-      if(rc != IDN2_OK)
-        /* fallback to TR46 Transitional mode for better IDNA2003
-           compatibility */
-        rc = IDN2_LOOKUP(host->name, &ace_hostname,
-                         IDN2_TRANSITIONAL);
-      if(rc == IDN2_OK) {
-        host->encalloc = (char *)ace_hostname;
-        /* change the name pointer to point to the encoded hostname */
-        host->name = host->encalloc;
-      }
-      else {
-        failf(data, "Failed to convert %s to ACE; %s", host->name,
-              idn2_strerror(rc));
-        return CURLE_URL_MALFORMAT;
-      }
-    }
-#elif defined(USE_WIN32_IDN)
-    char *ace_hostname = NULL;
-
-    if(Curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
-      host->encalloc = ace_hostname;
-      /* change the name pointer to point to the encoded hostname */
-      host->name = host->encalloc;
-    }
-    else {
-      char buffer[STRERROR_LEN];
-      failf(data, "Failed to convert %s to ACE; %s", host->name,
-            Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
-      return CURLE_URL_MALFORMAT;
-    }
-#else
-    infof(data, "IDN support not present, can't parse Unicode domains");
-#endif
-  }
-  return CURLE_OK;
-}
-
-/*
- * 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 */
-    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
-}
-
 /*
  * Allocate and initialize a new connectdata object.
  */
@@ -1992,11 +1873,11 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   /*************************************************************
    * IDN-convert the hostnames
    *************************************************************/
-  result = Curl_idnconvert_hostname(data, &conn->host);
+  result = Curl_idnconvert_hostname(&conn->host);
   if(result)
     return result;
   if(conn->bits.conn_to_host) {
-    result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
+    result = Curl_idnconvert_hostname(&conn->conn_to_host);
     if(result)
       return result;
   }
@@ -3664,12 +3545,12 @@ static CURLcode create_conn(struct Curl_easy *data,
    *************************************************************/
 #ifndef CURL_DISABLE_PROXY
   if(conn->bits.httpproxy) {
-    result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
+    result = Curl_idnconvert_hostname(&conn->http_proxy.host);
     if(result)
       return result;
   }
   if(conn->bits.socksproxy) {
-    result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
+    result = Curl_idnconvert_hostname(&conn->socks_proxy.host);
     if(result)
       return result;
   }
index 26c11ee735d48586ad188e6a5652ba99588e4db5..1a03c564c64ef0f581eaedfac8bd5a036b93b88d 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -49,11 +49,6 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
 const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
                                                size_t schemelen);
 
-bool Curl_is_ASCII_name(const char *hostname);
-CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
-                                  struct hostname *host);
-void Curl_free_idnconverted_hostname(struct hostname *host);
-
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
 #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
                                              specified */