]> granicus.if.org Git - neomutt/commitdiff
Validate charset names for all charset options.
authorRocco Rutte <pdmef@gmx.net>
Mon, 18 Aug 2008 08:20:40 +0000 (10:20 +0200)
committerRocco Rutte <pdmef@gmx.net>
Mon, 18 Aug 2008 08:20:40 +0000 (10:20 +0200)
Validation is either done against mutt's table of IANA assigned names or local iconv
implementation (based on the assumption that iconv_open(charset,charset) fails if charset
is unknown to the implementation). Closes #1668.

ChangeLog
charset.c
charset.h
init.c

index 6078580461b52f20c06dfa4dc7b53f5c5d45b281..8233992909aa5300f528067b8de6bb6bed70f7be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-08-15 11:53 -0700  Brendan Cully  <brendan@kublai.com>  (ff3fbb6a92a8)
+
+       * mutt_sasl.c: Fix type-punning warning in sasl_getprop usage
+
+2008-08-15 11:41 -0700  Brendan Cully  <brendan@kublai.com>  (622ef570a7e3)
+
+       * ChangeLog, parse.c: Fix a couple of compiler warnings introduced in
+       [00ce81d778bf]. Make the style of mutt_parse_references more
+       pleasing to me.
+
 2008-07-10 09:38 -0400  Aron Griffis  <agriffis@n01se.net>  (d3ee9644765f)
 
        * copy.c: Fix three bugs handling flags in mutt_copy_header
index 30d157e2466a353d1b46da44920dfcbe06658833..69c0e9bbfe6e2185ecafed54a95fbd719b148b7e 100644 (file)
--- a/charset.c
+++ b/charset.c
@@ -629,3 +629,28 @@ void fgetconv_close (FGETCONV **_fc)
     iconv_close (fc->cd);
   FREE (_fc);          /* __FREE_CHECKED__ */
 }
+
+int mutt_check_charset (const char *s, int strict)
+{
+  int i;
+  iconv_t cd;
+
+  if (mutt_is_utf8 (s))
+    return 0;
+
+  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 0;
+    }
+
+  if ((cd = mutt_iconv_open (s, s, 0)) != (iconv_t)(-1))
+  {
+    iconv_close (cd);
+    return 0;
+  }
+
+  return -1;
+}
index ab5f062bfbc8f0e8b232bac8d4945272f18e55b1..bb308868ef2ef6f1872ad2066e560b2748312a6b 100644 (file)
--- a/charset.h
+++ b/charset.h
@@ -56,4 +56,10 @@ 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 or
+ * known to local iconv implementation). If strict is non-zero, check
+ * against iconv only. Returns 0 if known and negative otherwise.
+ */
+int mutt_check_charset (const char *s, int strict);
+
 #endif /* _CHARSET_H */
diff --git a/init.c b/init.c
index 6db5a20da3125aad4a36e3ad706f5904f9d29a84..2a4bded996ef15c23bb724c49dac314ebfffa4a7 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1684,6 +1684,26 @@ static void pretty_var (char *dst, size_t len, const char *option, const char *v
   *p = 0;
 }
 
+static int check_charset (struct option_t *opt, const char *val)
+{
+  char *p, *q, *s = safe_strdup (val);
+  int rc = 0, strict = strcmp (opt->option, "send_charset") == 0;
+
+  for (p = strtok_r (s, ":", &q); p; p = strtok_r (NULL, ":", &q))
+  {
+    if (!*p)
+      continue;
+    if (mutt_check_charset (p, strict) < 0)
+    {
+      rc = -1;
+      break;
+    }
+  }
+
+  FREE(&s);
+  return rc;
+}
+
 static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
 {
   int query, unset, inv, reset, r = 0;
@@ -1877,14 +1897,9 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
          myvar = safe_strdup (myvar);
           myvar_del (myvar);
        }
-        else if (DTYPE (MuttVars[idx].type) == DT_ADDR)
-         rfc822_free_address ((ADDRESS **) MuttVars[idx].data);
-        else
-         /* MuttVars[idx].data is already 'char**' (or some 'void**') or... 
-          * so cast to 'void*' is okay */
-         FREE ((void *) MuttVars[idx].data);           /* __FREE_CHECKED__ */
 
         mutt_extract_token (tmp, s, 0);
+
         if (myvar)
         {
           myvar_set (myvar, tmp->data);
@@ -1893,18 +1908,32 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
         }
         else if (DTYPE (MuttVars[idx].type) == DT_PATH)
         {
+         /* MuttVars[idx].data is already 'char**' (or some 'void**') or... 
+          * so cast to 'void*' is okay */
+         FREE ((void *) MuttVars[idx].data);           /* __FREE_CHECKED__ */
+
          strfcpy (scratch, tmp->data, sizeof (scratch));
          mutt_expand_path (scratch, sizeof (scratch));
          *((char **) MuttVars[idx].data) = safe_strdup (scratch);
         }
         else if (DTYPE (MuttVars[idx].type) == DT_STR)
         {
+         if (strstr (MuttVars[idx].option, "charset") &&
+             check_charset (&MuttVars[idx], tmp->data) < 0)
+         {
+           snprintf (err->data, err->dsize, _("Invalid value for option %s: \"%s\""),
+                     MuttVars[idx].option, tmp->data);
+           return (-1);
+         }
+
+         FREE ((void *) MuttVars[idx].data);           /* __FREE_CHECKED__ */
          *((char **) MuttVars[idx].data) = safe_strdup (tmp->data);
          if (mutt_strcmp (MuttVars[idx].option, "charset") == 0)
            mutt_set_charset (Charset);
         }
         else
         {
+         rfc822_free_address ((ADDRESS **) MuttVars[idx].data);
          *((ADDRESS **) MuttVars[idx].data) = rfc822_parse_adrlist (NULL, tmp->data);
         }
       }