]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
idn: support non-UTF-8 input under AppleIDN
authorBo Anderson <mail@boanderson.me>
Wed, 7 Aug 2024 02:14:57 +0000 (03:14 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 7 Aug 2024 12:59:01 +0000 (14:59 +0200)
This aligns the behaviour with libidn2 and the curl documentation.

Closes #14431

CMakeLists.txt
configure.ac
docs/KNOWN_BUGS
lib/idn.c
tests/data/DISABLED

index 7242d687fcee77930e007fe03001d435b54774b2..7427516898574fd62341552733063675fb3be23e 100644 (file)
@@ -980,7 +980,7 @@ if(APPLE)
     check_symbol_exists("uidna_openUTS46" "unicode/uidna.h" HAVE_APPLE_IDN)
     cmake_pop_check_state()
     if(HAVE_APPLE_IDN)
-      list(APPEND CURL_LIBS "icucore")
+      list(APPEND CURL_LIBS "icucore" "iconv")
     else()
       set(USE_APPLE_IDN OFF)
     endif()
index 1e7a9bba72a841b92af73f2a46a5bf1c48dcd441..d81167a851436699e7b721be1e0ba79c4150a1e2 100644 (file)
@@ -2780,7 +2780,7 @@ case $host_os in
               AC_DEFINE(USE_APPLE_IDN, 1, [if AppleIDN])
               AC_SUBST(USE_APPLE_IDN, [1])
               AC_SUBST([IDN_ENABLED], [1])
-              LIBS="-licucore $LIBS"
+              LIBS="-licucore -liconv $LIBS"
             )
           ])
           ;;
index 9555e420589358821c94ff629e5616b728ad829a..cc5f1dd289be31a429334a491dccfe17b49ea936 100644 (file)
@@ -530,7 +530,7 @@ problems may have been fixed or changed somewhat since this was written.
 
 11.7 AppleIDN test failures
 
- Test 1034 and 1035 fail on macOS when built to use AppleIDN.
+ Test 1035 fail on macOS when built to use AppleIDN.
 
  See https://github.com/curl/curl/issues/14176
 
index ef55ddfec07c57efc2bb6f0068ce71734bb4ab35..b1c1fcaa6250670001aa6297cdffab8b6bca7981 100644 (file)
--- a/lib/idn.c
+++ b/lib/idn.c
 /* for macOS and iOS targets */
 #if defined(USE_APPLE_IDN)
 #include <unicode/uidna.h>
+#include <iconv.h>
+#include <langinfo.h>
 
 #define MAX_HOST_LENGTH 512
 
+static CURLcode iconv_to_utf8(const char *in, size_t inlen,
+                              char **out, size_t *outlen)
+{
+  iconv_t cd = iconv_open("UTF-8", nl_langinfo(CODESET));
+  if(cd != (iconv_t)-1) {
+    size_t iconv_outlen = *outlen;
+    char *iconv_in = (char *)in;
+    size_t iconv_inlen = inlen;
+    size_t iconv_result = iconv(cd, &iconv_in, &iconv_inlen,
+                                out, &iconv_outlen);
+    *outlen -= iconv_outlen;
+    iconv_close(cd);
+    if(iconv_result == (size_t)-1) {
+      if(errno == ENOMEM)
+        return CURLE_OUT_OF_MEMORY;
+      else
+        return CURLE_URL_MALFORMAT;
+    }
+
+    return CURLE_OK;
+  }
+  else {
+    if(errno == ENOMEM)
+      return CURLE_OUT_OF_MEMORY;
+    else
+      return CURLE_FAILED_INIT;
+  }
+}
+
 static CURLcode mac_idn_to_ascii(const char *in, char **out)
 {
   size_t inlen = strlen(in);
   if(inlen < MAX_HOST_LENGTH) {
-    UErrorCode err = U_ZERO_ERROR;
-    UIDNA* idna = uidna_openUTS46(
-      UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_ASCII, &err);
-    if(!U_FAILURE(err)) {
-      UIDNAInfo info = UIDNA_INFO_INITIALIZER;
-      char buffer[MAX_HOST_LENGTH] = {0};
-      (void)uidna_nameToASCII_UTF8(idna, in, -1, buffer,
-                                   sizeof(buffer) - 1, &info, &err);
-      uidna_close(idna);
+    char iconv_buffer[MAX_HOST_LENGTH] = {0};
+    char *iconv_outptr = iconv_buffer;
+    size_t iconv_outlen = sizeof(iconv_buffer);
+    CURLcode iconv_result = iconv_to_utf8(in, inlen,
+                                          &iconv_outptr, &iconv_outlen);
+    if(!iconv_result) {
+      UErrorCode err = U_ZERO_ERROR;
+      UIDNA* idna = uidna_openUTS46(
+        UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_ASCII, &err);
       if(!U_FAILURE(err)) {
-        *out = strdup(buffer);
-        if(*out)
-          return CURLE_OK;
-        else
-          return CURLE_OUT_OF_MEMORY;
+        UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+        char buffer[MAX_HOST_LENGTH] = {0};
+        (void)uidna_nameToASCII_UTF8(idna, iconv_buffer, (int)iconv_outlen,
+                                     buffer, sizeof(buffer) - 1, &info, &err);
+        uidna_close(idna);
+        if(!U_FAILURE(err)) {
+          *out = strdup(buffer);
+          if(*out)
+            return CURLE_OK;
+          else
+            return CURLE_OUT_OF_MEMORY;
+        }
       }
     }
+    else
+      return iconv_result;
   }
   return CURLE_URL_MALFORMAT;
 }
index 02593cde0d1e5c1f607947c1ccc0fb6d46a8b126..0e6c79767af6a917a790c70ccb754ef1c25f028a 100644 (file)
@@ -94,7 +94,6 @@
 313
 %endif
 %if AppleIDN
-1034
 1035
 %endif
 %if WinIDN