]> sjero.net Git - wget/blobdiff - src/iri.c
Basic IDN/IRI support
[wget] / src / iri.c
index 5fb06d0992bde05c5dda9768e68e2b9b8d5ad454..32eb7210fdea7d2cbca2d8ab2414510611404c79 100644 (file)
--- a/src/iri.c
+++ b/src/iri.c
@@ -1,6 +1,5 @@
 /* IRI related functions.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   Copyright (C) 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -42,6 +41,8 @@ as that of the covered work.  */
 #include "utils.h"
 #include "iri.h"
 
+char *remote;
+char *current;
 
 static iconv_t locale2utf8;
 
@@ -81,7 +82,7 @@ parse_charset (char *str)
       return NULL;
     }
 
-  logprintf (LOG_VERBOSE, "parse_charset: %s\n", quote (charset));
+  /*logprintf (LOG_VERBOSE, "parse_charset: %s\n", quote (charset));*/
 
   return charset;
 }
@@ -102,9 +103,9 @@ check_encoding_name (char *encoding)
 
   while (*s)
     {
-      if (!c_isascii(*s) || c_isspace(*s))
+      if (!c_isascii (*s) || c_isspace (*s))
         {
-          logprintf (LOG_VERBOSE, "Encoding %s isn't valid\n", quote(encoding));
+          logprintf (LOG_VERBOSE, "Encoding %s isn't valid\n", quote (encoding));
           return false;
         }
 
@@ -136,7 +137,7 @@ open_locale_to_utf8 (void)
     return true;
 
   logprintf (LOG_VERBOSE, "Conversion from %s to %s isn't supported\n",
-             quote (opt.locale), quote("UTF-8"));
+             quote (opt.locale), quote ("UTF-8"));
   locale2utf8 = NULL;
   return false;
 }
@@ -186,6 +187,10 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out)
       /* Incomplete or invalid multibyte sequence */
       if (errno == EINVAL || errno == EILSEQ)
         {
+          if (!invalid)
+            logprintf (LOG_VERBOSE,
+                      "Incomplete or invalide multibyte sequence encountered\n");
+
           invalid++;
           **out = *in;
           in++;
@@ -193,7 +198,7 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out)
           (*out)++;
           outlen--;
         }
-      else if (errno == E2BIG) /* Output buffer full */ 
+      else if (errno == E2BIG) /* Output buffer full */
         {
           char *new;
 
@@ -217,17 +222,31 @@ do_conversion (iconv_t cd, char *in, size_t inlen, char **out)
     return false;
 }
 
-/* Try to encode UTF-8 host to ASCII. Return the new domain on success or NULL
+/* Try to ASCII encode UTF-8 host. Return the new domain on success or NULL
    on error. */
-char *idn_encode (char *host)
+char *
+idn_encode (char *host, bool utf8_encoded)
 {
   char *new;
   int ret;
 
+  /* Encode to UTF-8 if not done using current remote */
+  if (!utf8_encoded)
+    {
+      if (!remote_to_utf8 ((const char *) host, (const char **) &new))
+        {
+          /* Nothing to encode or an error occured */
+          return NULL;
+        }
+
+      host = new;
+    }
+
   /* toASCII UTF-8 NULL terminated string */
   ret = idna_to_ascii_8z (host, &new, 0);
   if (ret != IDNA_SUCCESS)
     {
+      /* sXXXav : free new when needed ! */
       logprintf (LOG_VERBOSE, "idn_encode failed (%d): %s\n", ret,
                  quote (idna_strerror (ret)));
       return NULL;
@@ -236,3 +255,106 @@ char *idn_encode (char *host)
   return new;
 }
 
+/* Try to decode an ASCII encoded host. Return the new domain in the locale on
+   success or NULL on error. */
+char *
+idn_decode (char *host)
+{
+  char *new;
+  int ret;
+
+  ret = idna_to_unicode_8zlz (host, &new, 0);
+  if (ret != IDNA_SUCCESS)
+    {
+      logprintf (LOG_VERBOSE, "idn_decode failed (%d): %s\n", ret,
+                 quote (idna_strerror (ret)));
+      return NULL;
+    }
+
+  return new;
+}
+
+/* Return a new string */
+bool
+remote_to_utf8 (const char *str, const char **new)
+{
+  char *remote;
+  iconv_t cd;
+  bool ret = false;
+
+  if (opt.encoding_remote)
+    remote = opt.encoding_remote;
+  else if (current)
+    remote = current;
+  else
+    return false;
+
+  cd = iconv_open ("UTF-8", remote);
+  if (cd == (iconv_t)(-1))
+    return false;
+
+  if (do_conversion (cd, (char *) str, strlen ((char *) str), (char **) new))
+    ret = true;
+
+  iconv_close (cd);
+
+  /* Test if something was converted */
+  if (!strcmp (str, *new))
+    {
+      xfree ((char *) *new);
+      return false;
+    }
+
+  return ret;
+}
+
+char *get_remote_charset (void)
+{
+  return remote;
+}
+
+char *get_current_charset (void)
+{
+  return current;
+}
+
+void set_current_charset (char *charset)
+{
+  /*printf("[ current = `%s'\n", charset);*/
+
+  if (current)
+    xfree (current);
+
+  current = charset ? xstrdup (charset) : NULL;
+}
+
+void set_current_as_locale (void)
+{
+  /*printf("[ current = locale = `%s'\n", opt.locale);*/
+  if (current)
+    xfree (current);
+
+  /* sXXXav : assert opt.locale NULL ? */
+  current = xstrdup (opt.locale);
+}
+
+void
+set_remote_charset (char *charset)
+{
+  /*printf("[ remote = `%s'\n", charset);*/
+  if (remote)
+    xfree (remote);
+
+  remote = charset ? xstrdup (charset) : NULL;
+}
+
+void
+set_remote_as_current (void)
+{
+  /*printf("[ remote = current = `%s'\n", current);*/
+  if (remote)
+    xfree (remote);
+
+  remote = current ? xstrdup (current) : NULL;
+}
+