Package sources for project devel:ALP are received through scmsync. This is not supported by the OBS frontend

File localetag.diff of Package rpm.21495

Convert output to the current locale. Assumes utf8 input if the
decoding works, otherwise iso-8859-1.

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