]> granicus.if.org Git - neomutt/commitdiff
Add the mutt_ch_check API (#1139)
authorPietro Cerutti <gahr@gahr.ch>
Tue, 29 May 2018 13:29:02 +0000 (14:29 +0100)
committerGitHub <noreply@github.com>
Tue, 29 May 2018 13:29:02 +0000 (14:29 +0100)
* Add the mutt_ch_check API

This adds the mutt_ch_check API that can be used to check whether a
string can be converted between character sets. It is stricter than
mutt_ch_convert_string in that it doesn't apply any replacement chars to
unconvertible characters and doesn't return the converted string.

* Fix ICONV_CONST

* Fix arguments to iconv()

* Free the correct pointer

mutt/charset.c
mutt/charset.h

index b70302bbbec3c840d220e74b19059f8884b44c26..6fb2426b32b32aae64b0c62522a139e4694cda60 100644 (file)
@@ -667,6 +667,36 @@ const char *mutt_ch_iconv_lookup(const char *chs)
   return lookup_charset(MUTT_LOOKUP_ICONV, chs);
 }
 
+/**
+ * mutt_ch_check - Check whether a string can be converted between encodings
+ * @param[in] ps    String to check
+ * @param[in] slen  Length of the string to check
+ * @param[in] from  Current character set
+ * @param[in] to    Target character set
+ * @retval 0  Success
+ * @retval -1 Error in iconv_open()
+ * @retval >0 Errno as set by iconv()
+ */
+int mutt_ch_check(const char *s, size_t slen, const char *from, const char *to)
+{
+  int rc = 0;
+  iconv_t cd = mutt_ch_iconv_open(to, from, 0);
+  if (cd == (iconv_t)-1)
+    return -1;
+
+  size_t outlen = MB_LEN_MAX * slen;
+  char *out = mutt_mem_malloc(outlen + 1);
+  char *saved_out = out;
+
+  const size_t convlen = iconv(cd, (ICONV_CONST char **) &s, &slen, &out, (size_t *) &outlen);
+  if (convlen == -1)
+    rc = errno;
+
+  FREE(&saved_out);
+  iconv_close(cd);
+  return rc;
+}
+
 /**
  * mutt_ch_convert_string - Convert a string between encodings
  * @param[in,out] ps    String to convert
@@ -972,7 +1002,9 @@ char *mutt_ch_choose(const char *fromcode, const char *charsets, char *u,
     t[n] = '\0';
 
     s = mutt_str_substr_dup(u, u + ulen);
-    if (mutt_ch_convert_string(&s, fromcode, t, 0) != 0)
+    const int rc = (d != NULL) ? mutt_ch_convert_string(&s, fromcode, t, 0)
+                               : mutt_ch_check(s, ulen, fromcode, t);
+    if (rc)
     {
       FREE(&t);
       FREE(&s);
index 67ae0191788bf551ba208c0af9fc96b65b008506..9e64b07529b3759116b318591600e5766b28ae57 100644 (file)
@@ -104,6 +104,7 @@ void             mutt_ch_fgetconv_close(struct FgetConv **fc);
 int              mutt_ch_fgetconv(struct FgetConv *fc);
 char *           mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc);
 
+int              mutt_ch_check(const char *s, size_t slen, const char *from, const char *to);
 char *           mutt_ch_choose(const char *fromcode, const char *charsets,
                                 char *u, size_t ulen, char **d, size_t *dlen);