<<< Date Index >>>     <<< Thread Index >>>

Re: Character set validation (with patch)



Hi,

* Rocco Rutte wrote:

Thoughts?

I was told iconvlist() is only implemented by libiconv, not glibc so that Linux users won't really benefit. Thus I've updated the patch to use mutt_iconv_open() to see if iconv_open() knows about the charset.

Thoughts?

Rocco
diff --git a/charset.c b/charset.c
--- a/charset.c
+++ b/charset.c
@@ -629,3 +629,59 @@ void fgetconv_close (FGETCONV **_fc)
     iconv_close (fc->cd);
   FREE (_fc);          /* __FREE_CHECKED__ */
 }
+
+#ifdef HAVE_ICONV_LIST
+
+struct iconvlist_data
+{
+  const char *name;
+  int found;
+};
+
+static int check_charset (unsigned int cnt, const char * const *names, void 
*data)
+{
+  struct iconvlist_data *d = (struct iconvlist_data *)data;
+  unsigned int i;
+
+  for (i = 0; !d->found && i < cnt; i++)
+    if (ascii_strcasecmp (names[i], d->name) == 0)
+      d->found = 1;
+  return d->found;
+}
+
+#endif /* HAVE_ICONV_LIST */
+
+int mutt_check_charset (const char *s, int strict)
+{
+  int i;
+#if HAVE_ICONV_LIST
+  struct iconvlist_data data;
+#else
+  iconv_t cd;
+#endif
+
+  if (!strict)
+    for (i = 0; PreferredMIMENames[i].key; i++)
+    {
+      if (ascii_strcasecmp (PreferredMIMENames[i].key, s) == 0 ||
+         ascii_strcasecmp (PreferredMIMENames[i].pref, s) == 0)
+       return 1;
+    }
+
+#if HAVE_ICONV_LIST
+  data.name = s;
+  data.found = 0;
+  iconvlist (check_charset, &data);
+  if (data.found)
+    return 1;
+#else
+  if ((cd = mutt_iconv_open (s, s, 0)) != (iconv_t)(-1))
+  {
+    iconv_close (cd);
+    return 1;
+  } else
+    return -1;
+#endif
+
+  return 0;
+}
diff --git a/charset.h b/charset.h
--- a/charset.h
+++ b/charset.h
@@ -56,4 +56,11 @@ char *mutt_get_default_charset ();
  */
 #define M_ICONV_HOOK_FROM 1    /* apply charset-hooks to fromcode */
 
+/* Check if given character set is valid (either officially assigned by
+ * known to local iconv() implementation). If strict is non-zero, check
+ * against iconv() only. Returns 1 if known and 0 otherwise.
+ * Uses mutt_iconv_open() if iconvlist() is missing.
+ */
+int mutt_check_charset (const char *s, int strict);
+
 #endif /* _CHARSET_H */
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -982,6 +982,35 @@ AC_CHECK_HEADERS(iconv.h,
                         [Define if <iconv.h> defines iconv_t.])],
                  AC_MSG_RESULT(no))])
 
+AC_CACHE_CHECK([for iconvlist()], mutt_cv_iconv_list,
+        mutt_save_LIBS="$LIBS"
+        LIBS="$LIBS $LIBICONV"
+        AC_TRY_RUN([
+#include <iconv.h>
+
+static int count = 0;
+
+static int test_iconvlist (unsigned int c, const char **n, void *d)
+{
+  count += c;
+  return 0;
+}
+
+int main()
+{
+  iconvlist (test_iconvlist, 0);
+  return count > 0 ? 0 : 1;
+}
+                ],
+                mutt_cv_iconv_list=yes,
+                mutt_cv_iconv_list=no,
+                mutt_cv_iconv_list=yes)
+        LIBS="$mutt_save_LIBS")
+if test "$mutt_cv_iconv_list" = yes; then
+  AC_DEFINE(HAVE_ICONV_LIST,1, [Define if you have the iconvlist() function.])
+fi
+
+
 dnl (1) Some implementations of iconv won't convert from UTF-8 to UTF-8.
 dnl (2) In glibc-2.1.2 and earlier there is a bug that messes up ob and
 dnl     obl when args 2 and 3 are 0 (fixed in glibc-2.1.3).
diff --git a/main.c b/main.c
--- a/main.c
+++ b/main.c
@@ -435,6 +435,12 @@ static void show_version (void)
        "+ICONV_NONTRANS  "
 #else
        "-ICONV_NONTRANS  "
+#endif
+
+#ifdef HAVE_ICONV_LIST
+       "+ICONV_LIST  "
+#else
+       "-ICONV_LIST  "
 #endif
 
 #if HAVE_LIBIDN