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