Blame localetag.diff

Bernhard M. Wiedemann 1250f9
Convert output to the current locale. Assumes utf8 input if the
Bernhard M. Wiedemann 1250f9
decoding works, otherwise iso-8859-1.
Bernhard M. Wiedemann 1250f9
Bernhard M. Wiedemann 1250f9
--- ./lib/tagexts.c.orig	2016-10-21 09:44:00.309962086 +0000
Bernhard M. Wiedemann 1250f9
+++ ./lib/tagexts.c	2017-01-19 10:27:57.243832208 +0000
Bernhard M. Wiedemann 1250f9
@@ -2,6 +2,7 @@
Bernhard M. Wiedemann 1250f9
  * \file lib/formats.c
Bernhard M. Wiedemann 1250f9
  */
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
+#include <wchar.h>
Bernhard M. Wiedemann 1250f9
 #include "system.h"
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
 #include <rpm/rpmtypes.h>
Bernhard M. Wiedemann 1250f9
@@ -197,6 +198,114 @@ typedef enum tMode_e {
Bernhard M. Wiedemann 1250f9
     TRANSFILETRIGGER  = 2,
Bernhard M. Wiedemann 1250f9
 } tMode;
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
+static char * strtolocale(char *str)
Bernhard M. Wiedemann 1250f9
+{
Bernhard M. Wiedemann 1250f9
+    wchar_t *wstr, *wp;
Bernhard M. Wiedemann 1250f9
+    const unsigned char *cp;
Bernhard M. Wiedemann 1250f9
+    char *cc;
Bernhard M. Wiedemann 1250f9
+    int state = 0;
Bernhard M. Wiedemann 1250f9
+    int c;
Bernhard M. Wiedemann 1250f9
+    int ccl, cca, mb_cur_max;
Bernhard M. Wiedemann 1250f9
+    size_t l;
Bernhard M. Wiedemann 1250f9
+    mbstate_t ps;
Bernhard M. Wiedemann 1250f9
+    int strisutf8 = 1;
Bernhard M. Wiedemann 1250f9
+    int locisutf8 = 1;
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
+    if (!str)
Bernhard M. Wiedemann 1250f9
+	return 0;
Bernhard M. Wiedemann 1250f9
+    if (!*str)
Bernhard M. Wiedemann 1250f9
+	return str;
Bernhard M. Wiedemann 1250f9
+    wstr = (wchar_t *)xmalloc((strlen(str) + 1) * sizeof(*wstr));
Bernhard M. Wiedemann 1250f9
+    wp = wstr;
Bernhard M. Wiedemann 1250f9
+    cp = (const unsigned char *)str;
Bernhard M. Wiedemann 1250f9
+    while ((c = *cp++) != 0) {
Bernhard M. Wiedemann 1250f9
+	if (state) {
Bernhard M. Wiedemann 1250f9
+	    if ((c & 0xc0) != 0x80) {
Bernhard M. Wiedemann 1250f9
+		/* encoding error */
Bernhard M. Wiedemann 1250f9
+		break;
Bernhard M. Wiedemann 1250f9
+	    }
Bernhard M. Wiedemann 1250f9
+	    c = (c & 0x3f) | (state << 6);
Bernhard M. Wiedemann 1250f9
+	    if (!(state & 0x40000000)) {
Bernhard M. Wiedemann 1250f9
+	      /* check for overlong sequences */
Bernhard M. Wiedemann 1250f9
+	        if ((c & 0x820823e0) == 0x80000000)
Bernhard M. Wiedemann 1250f9
+		    c = 0xfdffffff;
Bernhard M. Wiedemann 1250f9
+	        else if ((c & 0x020821f0) == 0x02000000)
Bernhard M. Wiedemann 1250f9
+		    c = 0xfff7ffff;
Bernhard M. Wiedemann 1250f9
+	        else if ((c & 0x000820f8) == 0x00080000)
Bernhard M. Wiedemann 1250f9
+		    c = 0xffffd000;
Bernhard M. Wiedemann 1250f9
+	        else if ((c & 0x0000207c) == 0x00002000)
Bernhard M. Wiedemann 1250f9
+		    c = 0xffffff70;
Bernhard M. Wiedemann 1250f9
+	    }
Bernhard M. Wiedemann 1250f9
+	} else {
Bernhard M. Wiedemann 1250f9
+	    /* new sequence */
Bernhard M. Wiedemann 1250f9
+	    if (c >= 0xfe)
Bernhard M. Wiedemann 1250f9
+		c = 0xfffd;
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xfc)
Bernhard M. Wiedemann 1250f9
+		c = (c & 0x01) | 0xbffffffc;    /* 5 bytes to follow */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xf8)
Bernhard M. Wiedemann 1250f9
+		c = (c & 0x03) | 0xbfffff00;    /* 4 */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xf0)
Bernhard M. Wiedemann 1250f9
+		c = (c & 0x07) | 0xbfffc000;    /* 3 */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xe0)
Bernhard M. Wiedemann 1250f9
+		c = (c & 0x0f) | 0xbff00000;    /* 2 */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xc2)
Bernhard M. Wiedemann 1250f9
+		c = (c & 0x1f) | 0xfc000000;    /* 1 */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0xc0)
Bernhard M. Wiedemann 1250f9
+		c = 0xfdffffff;         /* overlong */
Bernhard M. Wiedemann 1250f9
+	    else if (c >= 0x80)
Bernhard M. Wiedemann 1250f9
+		c = 0xfffd;
Bernhard M. Wiedemann 1250f9
+        }
Bernhard M. Wiedemann 1250f9
+	state = (c & 0x80000000) ? c : 0;
Bernhard M. Wiedemann 1250f9
+	if (state)
Bernhard M. Wiedemann 1250f9
+	    continue;
Bernhard M. Wiedemann 1250f9
+	*wp++ = (wchar_t)c;
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
+    if (state) {
Bernhard M. Wiedemann 1250f9
+	/* encoding error, assume latin1 */
Bernhard M. Wiedemann 1250f9
+        strisutf8 = 0;
Bernhard M. Wiedemann 1250f9
+	cp = (const unsigned char *)str;
Bernhard M. Wiedemann 1250f9
+	wp = wstr;
Bernhard M. Wiedemann 1250f9
+	while ((c = *cp++) != 0) {
Bernhard M. Wiedemann 1250f9
+	    *wp++ = (wchar_t)c;
Bernhard M. Wiedemann 1250f9
+	}
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
+    *wp = 0;
Bernhard M. Wiedemann 1250f9
+    mb_cur_max = MB_CUR_MAX;
Bernhard M. Wiedemann 1250f9
+    memset(&ps, 0, sizeof(ps));
Bernhard M. Wiedemann 1250f9
+    cc = xmalloc(mb_cur_max);
Bernhard M. Wiedemann 1250f9
+    /* test locale encoding */
Bernhard M. Wiedemann 1250f9
+    if (wcrtomb(cc, 0x20ac, &ps) != 3 || memcmp(cc, "\342\202\254", 3))
Bernhard M. Wiedemann 1250f9
+	locisutf8 = 0;
Bernhard M. Wiedemann 1250f9
+    if (locisutf8 == strisutf8) {
Bernhard M. Wiedemann 1250f9
+	wstr = _free(wstr);
Bernhard M. Wiedemann 1250f9
+	return str;
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
+    str = _free((char *)str);
Bernhard M. Wiedemann 1250f9
+    memset(&ps, 0, sizeof(ps));
Bernhard M. Wiedemann 1250f9
+    ccl = cca = 0;
Bernhard M. Wiedemann 1250f9
+    for (wp = wstr; ; wp++) {
Bernhard M. Wiedemann 1250f9
+	l = wcrtomb(cc + ccl, *wp, &ps);
Bernhard M. Wiedemann 1250f9
+	if (*wp == 0)
Bernhard M. Wiedemann 1250f9
+	    break;
Bernhard M. Wiedemann 1250f9
+	if (l == (size_t)-1) {
Bernhard M. Wiedemann 1250f9
+	    if (*wp < (wchar_t)256 && mbsinit(&ps)) {
Bernhard M. Wiedemann 1250f9
+		cc[ccl] = *wp;
Bernhard M. Wiedemann 1250f9
+		l = 1;
Bernhard M. Wiedemann 1250f9
+	    } else
Bernhard M. Wiedemann 1250f9
+	        l = wcrtomb(cc + ccl, (wchar_t)'?', &ps);
Bernhard M. Wiedemann 1250f9
+	}
Bernhard M. Wiedemann 1250f9
+        if (l == 0 || l == (size_t)-1)
Bernhard M. Wiedemann 1250f9
+	    continue;
Bernhard M. Wiedemann 1250f9
+        ccl += l;
Bernhard M. Wiedemann 1250f9
+        if (ccl > cca) {
Bernhard M. Wiedemann 1250f9
+	    cca = ccl + 16;
Bernhard M. Wiedemann 1250f9
+	    cc = xrealloc(cc, cca + mb_cur_max);
Bernhard M. Wiedemann 1250f9
+	}
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
+    wstr = _free(wstr);
Bernhard M. Wiedemann 1250f9
+    return (char *)cc;
Bernhard M. Wiedemann 1250f9
+}
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
 /**
Bernhard M. Wiedemann 1250f9
  * Retrieve trigger info.
Bernhard M. Wiedemann 1250f9
  * @param mode		type of trigger (see tMode_e)
Bernhard M. Wiedemann 1250f9
@@ -607,10 +716,41 @@ static int i18nTag(Header h, rpmTag tag,
Bernhard M. Wiedemann 1250f9
 #endif
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
     rc = headerGet(h, tag, td, HEADERGET_ALLOC);
Bernhard M. Wiedemann 1250f9
+    if (rc && td->data) {
Bernhard M. Wiedemann 1250f9
+	td->data = strtolocale(td->data);
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
     return rc;
Bernhard M. Wiedemann 1250f9
 }
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
 /**
Bernhard M. Wiedemann 1250f9
+ * Retrieve text and convert to locale.
Bernhard M. Wiedemann 1250f9
+ */
Bernhard M. Wiedemann 1250f9
+static int localeTag(Header h, rpmTag tag, rpmtd td)
Bernhard M. Wiedemann 1250f9
+{
Bernhard M. Wiedemann 1250f9
+    int rc;
Bernhard M. Wiedemann 1250f9
+    rc = headerGet(h, tag, td, HEADERGET_ALLOC);
Bernhard M. Wiedemann 1250f9
+    if (!rc)
Bernhard M. Wiedemann 1250f9
+	return 0;
Bernhard M. Wiedemann 1250f9
+    if (td->type == RPM_STRING_TYPE) {
Bernhard M. Wiedemann 1250f9
+	td->data = strtolocale(td->data);
Bernhard M. Wiedemann 1250f9
+	td->count = 1;
Bernhard M. Wiedemann 1250f9
+    } else if (td->type == RPM_STRING_ARRAY_TYPE) {
Bernhard M. Wiedemann 1250f9
+	char **arr;
Bernhard M. Wiedemann 1250f9
+	int i;
Bernhard M. Wiedemann 1250f9
+	arr = xmalloc(td->count * sizeof(*arr));
Bernhard M. Wiedemann 1250f9
+	for (i = 0; i < td->count; i++) {
Bernhard M. Wiedemann 1250f9
+	    arr[i] = xstrdup(((char **)td->data)[i]);
Bernhard M. Wiedemann 1250f9
+	    arr[i] = strtolocale(arr[i]);
Bernhard M. Wiedemann 1250f9
+	}
Bernhard M. Wiedemann 1250f9
+	_free(td->data);
Bernhard M. Wiedemann 1250f9
+	td->data = arr;
Bernhard M. Wiedemann 1250f9
+	td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
Bernhard M. Wiedemann 1250f9
+    }
Bernhard M. Wiedemann 1250f9
+    return rc; 
Bernhard M. Wiedemann 1250f9
+}
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
+/**
Bernhard M. Wiedemann 1250f9
  * Retrieve summary text.
Bernhard M. Wiedemann 1250f9
  * @param h		header
Bernhard M. Wiedemann 1250f9
  * @retval td		tag data container
Bernhard M. Wiedemann 1250f9
@@ -634,6 +774,16 @@ static int descriptionTag(Header h, rpmt
Bernhard M. Wiedemann 1250f9
     return i18nTag(h, RPMTAG_DESCRIPTION, td, hgflags);
Bernhard M. Wiedemann 1250f9
 }
Bernhard M. Wiedemann 1250f9
 
Bernhard M. Wiedemann 1250f9
+static int changelognameTag(Header h, rpmtd td)
Bernhard M. Wiedemann 1250f9
+{
Bernhard M. Wiedemann 1250f9
+    return localeTag(h, RPMTAG_CHANGELOGNAME, td);
Bernhard M. Wiedemann 1250f9
+}
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
+static int changelogtextTag(Header h, rpmtd td)
Bernhard M. Wiedemann 1250f9
+{
Bernhard M. Wiedemann 1250f9
+    return localeTag(h, RPMTAG_CHANGELOGTEXT, td);
Bernhard M. Wiedemann 1250f9
+}
Bernhard M. Wiedemann 1250f9
+
Bernhard M. Wiedemann 1250f9
 /**
Bernhard M. Wiedemann 1250f9
  * Retrieve group text.
Bernhard M. Wiedemann 1250f9
  * @param h		header
Bernhard M. Wiedemann 1250f9
@@ -971,6 +1121,8 @@ static const struct headerTagFunc_s rpmH
Bernhard M. Wiedemann 1250f9
     { RPMTAG_LONGARCHIVESIZE,	longarchivesizeTag },
Bernhard M. Wiedemann 1250f9
     { RPMTAG_LONGSIZE,		longsizeTag },
Bernhard M. Wiedemann 1250f9
     { RPMTAG_LONGSIGSIZE,	longsigsizeTag },
Bernhard M. Wiedemann 1250f9
+    { RPMTAG_CHANGELOGNAME,     changelognameTag },
Bernhard M. Wiedemann 1250f9
+    { RPMTAG_CHANGELOGTEXT,     changelogtextTag },
Bernhard M. Wiedemann 1250f9
     { RPMTAG_DBINSTANCE,	dbinstanceTag },
Bernhard M. Wiedemann 1250f9
     { RPMTAG_EVR,		evrTag },
Bernhard M. Wiedemann 1250f9
     { RPMTAG_NVR,		nvrTag },