From 19b284c21452b2c50924de3e0a04f5ed8040430d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 2 Oct 2004 13:01:44 +0000
Subject: [PATCH] Gisle Vanem provided code that displays an error message when
 the (libidn based) IDN conversion fails. This is really due to a missing
 suitable function in the libidn API that I hope we can remove once libidn
 gets a function like this.

---
 CHANGES        |  6 +++++
 lib/strerror.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/strerror.h |  4 +++
 lib/url.c      |  5 ++--
 4 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/CHANGES b/CHANGES
index c0348360fe..90a04e576c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@
 
                                   Changelog
 
+Daniel (2 October 2004)
+- Gisle Vanem provided code that displays an error message when the (libidn
+  based) IDN conversion fails. This is really due to a missing suitable
+  function in the libidn API that I hope we can remove once libidn gets a
+  function like this.
+
 Daniel (1 October 2004)
 - Aleksandar Milivojevic reported a problem in the Redhat bugzilla (see
   https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=134133) and not to
diff --git a/lib/strerror.c b/lib/strerror.c
index 5263f442c8..b64af1cb84 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -27,6 +27,10 @@
 #include <string.h>
 #include <errno.h>
 
+#ifdef USE_LIBIDN
+#include <idna.h>
+#endif
+
 #include "strerror.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
@@ -556,3 +560,68 @@ const char *Curl_strerror(struct connectdata *conn, int err)
      *p = '\0';
   return buf;
 }
+
+#ifdef USE_LIBIDN
+/*
+ * Return error-string for libidn status as returned
+ * from idna_to_ascii_lz().
+ */
+const char *Curl_idn_strerror (struct connectdata *conn, int err)
+{
+  const char *str;
+  char *buf;
+  size_t max;
+
+  curlassert(conn);
+
+  buf = conn->syserr_buf;
+  max = sizeof(conn->syserr_buf)-1;
+
+  switch ((Idna_rc)err) {
+    case IDNA_SUCCESS:
+      str = "No error";
+      break;
+    case IDNA_STRINGPREP_ERROR:
+      str = "Error in string preparation";
+      break;
+    case IDNA_PUNYCODE_ERROR:
+      str = "Error in Punycode operation";
+      break;
+    case IDNA_CONTAINS_NON_LDH:
+      str = "Illegal ASCII characters";
+      break;
+    case IDNA_CONTAINS_MINUS:
+      str = "Contains minus";
+      break;
+    case IDNA_INVALID_LENGTH:
+      str = "Invalid output length";
+      break;
+    case IDNA_NO_ACE_PREFIX:
+      str = "No ACE prefix (\"xn--\")";
+      break;
+    case IDNA_ROUNDTRIP_VERIFY_ERROR:
+      str = "Roundtrip verify error";
+      break;
+    case IDNA_CONTAINS_ACE_PREFIX:
+      str = "Already have ACE prefix (\"xn--\")";
+      break;
+    case IDNA_ICONV_ERROR:
+      str = "Locale conversion failed";
+      break;
+    case IDNA_MALLOC_ERROR:
+      str = "Allocation failed";
+      break;
+    case IDNA_DLOPEN_ERROR:
+      str = "dlopen() error";
+      break;
+    default:
+      snprintf(buf, max, "error %d", (int)err);
+      str = NULL;
+      break;
+  }
+  if (str)
+    strncpy(buf, str, max);
+  buf[max] = '\0';
+  return (buf);
+}
+#endif  /* USE_LIBIDN */
diff --git a/lib/strerror.h b/lib/strerror.h
index 7d687230ed..d003cb182e 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -27,4 +27,8 @@
 
 const char *Curl_strerror (struct connectdata *conn, int err);
 
+#ifdef USE_LIBIDN
+const char *Curl_idn_strerror (struct connectdata *conn, int err);
+#endif
+
 #endif
diff --git a/lib/url.c b/lib/url.c
index 3f40b6b610..c0921ced43 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -116,6 +116,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
 #include "progress.h"
 #include "cookie.h"
 #include "strequal.h"
+#include "strerror.h"
 #include "escape.h"
 #include "strtok.h"
 #include "share.h"
@@ -2078,8 +2079,8 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
     infof (data, "Input domain encoded as `%s'\n",
            stringprep_locale_charset ());
     if (rc != IDNA_SUCCESS)
-      infof(data, "Failed to convert %s to ACE; IDNA error %d\n",
-            host->name, rc);
+      infof(data, "Failed to convert %s to ACE; %s\n",
+            host->name, Curl_idn_strerror(conn,rc));
     else {
       host->encalloc = ace_hostname;
       /* change the name pointer to point to the encoded hostname */
-- 
GitLab