[PATCH] make get_initials() multibyte safe

Dennis Preiser <[email protected]> Thu, 3 Oct 2013 16:14:49 +0200
Newsgroups gmane.network.tin.devel
Message-ID <[email protected]>
--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

When using 'quote_chars=%s>_' and the first or last name contain
multibyte characters this leads to wrong initials. For instance, a
followup to Urs Janßen leads to 'UJe>' instead of 'UJ>' and names that
start with Š or Ø lead to completely wrong initials. It turns out that
get_initials() is not multibyte safe. The attached patch fixes this.

In addition, we should enable the check for iswalpha() (aclocal.m4 ~279
and ~339).

Dennis

--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="2013-10-03.diff"

diff -urp tin-2.1.4/src/misc.c tin-2.1.4_r1/src/misc.c
--- tin-2.1.4/src/misc.c	2013-09-29 10:07:40.000000000 +0200
+++ tin-2.1.4_r1/src/misc.c	2013-10-03 12:58:28.000000000 +0200
@@ -1960,12 +1960,34 @@ get_initials(
 	char tbuf[PATH_LEN];
 	int i, j = 0;
 	t_bool iflag = FALSE;
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+	wchar_t *wtmp, *wbuf;
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 
 	if (s == NULL || maxsize <= 0)
 		return 0;
 
-	strcpy(tbuf, ((arts[respnum].name != NULL) ? arts[respnum].name : arts[respnum].from));
-
+	STRCPY(tbuf, ((arts[respnum].name != NULL) ? arts[respnum].name : arts[respnum].from));
+#if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
+	if ((wtmp = char2wchar_t(tbuf)) != NULL) {
+		wbuf = my_malloc(sizeof(wchar_t) * (wcslen(wtmp) + 1));
+		for (i = 0; wtmp[i] && j < maxsize - 1; i++) {
+			if (iswalpha((wint_t) wtmp[i])) {
+				if (!iflag) {
+					wbuf[j++] = wtmp[i];
+					iflag = TRUE;
+				}
+			} else
+				iflag = FALSE;
+		}
+		wbuf[j] = (wchar_t) '\0';
+		s[0] = '\0';
+		if (wcstombs(tbuf, wbuf, sizeof(tbuf) - 1) != (size_t) -1)
+			strcat(s, tbuf);
+		free(wtmp);
+		free(wbuf);
+	}
+#else
 	for (i = 0; tbuf[i] && j < maxsize - 1; i++) {
 		if (isalpha((int)(unsigned char) tbuf[i])) {
 			if (!iflag) {
@@ -1976,6 +1998,7 @@ get_initials(
 			iflag = FALSE;
 	}
 	s[j] = '\0';
+#endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 	return 0;
 }
 

--/9DWx/yDrRhgMJTb--