Re: [tin 1.9.x] problem with Multipart/Mixed and text/plain?iso-10646-ucs-2 base64 parts

Urs Janßen <[email protected]> Mon, 06 Sep 2010 12:05:45 +0200
Newsgroups gmane.network.tin.devel
Organization tin.org
Message-ID <[email protected]>
In <[email protected]>, Urs Janßen wrote:
> root cause are possible NULL bytes in a multibyte char (in UTF-16, UTF.32,
> ...) but we are using string functions...
> a trivial "workaround" would be to assemble a list of charsets which may
> contain NULL bytes and tell tin to skip parts in that charset.

Here is a patch from Dennis which implements this, if anyone knows
additional multibyte charsets which may contain NULL-bytes please
extend the chatset list. I'm unsure about SCSU (AFAIK it may contain
NULLs but shouldn't be used in mime, add it anyway?).

=== modified file 'include/extern.h'
--- include/extern.h	2010-05-11 09:45:44 +0000
+++ include/extern.h	2010-09-05 09:42:08 +0000
@@ -460,6 +460,7 @@
 extern constext txt_attach[];
 extern constext txt_attach_charset[];
 extern constext txt_attach_description[];
+extern constext txt_attach_unsup_charset[];
 extern constext txt_attrib_menu_com[];
 extern constext txt_uue[];
 extern constext txt_at_s[];

=== modified file 'src/cook.c'
--- src/cook.c	2009-12-11 11:28:57 +0000
+++ src/cook.c	2010-09-05 13:09:58 +0000
@@ -55,6 +55,7 @@
 #define MATCH_REGEX(x,y,z)	(pcre_exec(x.re, x.extra, y, z, 0, 0, NULL, 0) >= 0)
 
 
+static t_bool charset_unsupported(const char *charset);
 static t_bool header_wanted(const char *line);
 static t_part *new_uue(t_part **part, char *name);
 static void process_text_body_part(t_bool wrap_lines, FILE *in, t_part *part, int hide_uue);
@@ -745,6 +746,39 @@
 
 
 /*
+ * Check for charsets which may contain NULL bytes and thus break string
+ * functions. Possibly incomplete.
+ *
+ * TODO: fix the other code to handle those charsets properly.
+ */
+static t_bool
+charset_unsupported(
+	const char *charset)
+{
+	static const char *charsets[] = {
+		"csUnicode",	/* alias for ISO-10646-UCS-2 */
+		"csUCS4",		/* alias for ISO-10646-UCS-4 */
+		"ISO-10646-UCS-2",
+		"ISO-10646-UCS-4",
+		"UTF-16",		/* covers also BE/LE */
+		"UTF-32",		/* covers also BE/LE */
+		NULL };
+	const char **charsetptr = charsets;
+	t_bool ret = FALSE;
+
+	if (!charset)
+		return ret;
+
+	do {
+		if (!strncasecmp(charset, *charsetptr, strlen(*charsetptr)))
+			ret = TRUE;
+	} while (!ret && *(++charsetptr) != NULL);
+
+	return ret;
+}
+
+
+/*
  * 'cooks' an article, ie, prepare what will actually appear on the screen
  * It is not easy to do this in the same pass as the initial read since
  * boundary conditions for multipart articles make it harder to do on the
@@ -878,24 +912,33 @@
 			PUT_ATTACH(ptr, ptr->depth * 4, name, charset);
 
 			/* Try to view anything of type text, may need to review this */
-			if (IS_PLAINTEXT(ptr))
-				process_text_body_part(wrap_lines, artinfo->raw, ptr, hide_uue);
+			if (IS_PLAINTEXT(ptr)) {
+				if (charset_unsupported(charset)) {
+					put_cooked(LEN, wrap_lines, C_ATTACH, _(txt_attach_unsup_charset), ptr->depth * 4, "", charset);
+					if (ptr->next)
+						put_cooked(1, wrap_lines, C_ATTACH, "\n");
+				} else
+					process_text_body_part(wrap_lines, artinfo->raw, ptr, hide_uue);
+			}
 		}
 	} else {
+		if (!strcmp(content_types[hdr->ext->type], "text"))
+			charset = get_param(hdr->ext->params, "charset");
+		else
+			charset = NULL;
 		/*
 		 * A regular single-body article
 		 */
-		if (IS_PLAINTEXT(hdr->ext))
-			process_text_body_part(wrap_lines, artinfo->raw, hdr->ext, hide_uue);
-		else {
+		if (IS_PLAINTEXT(hdr->ext)) {
+			if (charset_unsupported(charset))
+				put_cooked(LEN, wrap_lines, C_ATTACH, _(txt_attach_unsup_charset), 0, "", charset);
+			else
+				process_text_body_part(wrap_lines, artinfo->raw, hdr->ext, hide_uue);
+		} else {
 			/*
 			 * Non-textual main body
 			 */
 			name = get_filename(hdr->ext->params);
-			if (!strcmp(content_types[hdr->ext->type], "text"))
-				charset = get_param(hdr->ext->params, "charset");
-			else
-				charset = NULL;
 			PUT_ATTACH(hdr->ext, 0, name, charset);
 		}
 	}

=== modified file 'src/lang.c'
--- src/lang.c	2010-09-05 07:25:44 +0000
+++ src/lang.c	2010-09-05 09:41:57 +0000
@@ -74,6 +74,7 @@
 constext txt_at_s[] = N_(" at %s");
 constext txt_attach[] = N_("%*s[-- %s/%s, encoding %s%s%s, %d lines%s%s --]\n");
 constext txt_attach_charset[] = N_(", charset: ");
+constext txt_attach_unsup_charset[] = N_("%*s[-- charset %s not supported --]\n");
 constext txt_attach_description[] = N_("%*s[-- Description: %s --]\n");
 constext txt_attrib_menu_com[] = N_("Attributes Menu Commands");
 #ifdef NNTP_ABLE