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

Character set validation (with patch)



Hi,

there're some bugs open where trouble could have been avoided if mutt did validate character sets (e.g. #1668 and maybe //TRANSLIT in #2956). I attached a patch with configure magic that checks for usability of iconvlist() to see whether a character set is supported being used in mutt_check_charset().

This currently isn't used anywhere since I'd like to ask for opinions on a) whether mutt should do some sort of validation at all (I vote for it) and b) in what places/in what situations.

To me, the easiest way would be to simply issue warnings/errors upon setting $charset, $send_charset, $config_charset and friends.

Thoughts?

(Note: the configure code in configure.ac looks strange, but AC_CHECK_FUNC didn't report iconvlist() as present while my version does)

Rocco
diff --git a/charset.c b/charset.c
--- a/charset.c
+++ b/charset.c
@@ -629,3 +629,50 @@ 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;
+#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;
+#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.
+ * Requires iconvlist() routine.
+ */
+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
@@ -992,6 +992,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
@@ -441,6 +441,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