Convert changelog and i18n header elements to current locale. [#43347], rh#140050 Index: lib/tagexts.c =================================================================== --- lib/tagexts.c.orig +++ lib/tagexts.c @@ -2,6 +2,7 @@ * \file lib/formats.c */ +#include #include "system.h" #include @@ -156,6 +157,114 @@ exit: return rc; } +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 mounted file system paths. * @param h header @@ -534,9 +643,43 @@ static int i18nTag(Header h, rpmTag tag, dstring = _free(dstring); rc = headerGet(h, tag, td, HEADERGET_DEFAULT); + if (rc && td->data) { + td->data = xstrdup(td->data); + td->data = strtolocale(td->data); + td->flags = RPMTD_ALLOCED; + } + 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_DEFAULT); + if (!rc) + return 0; + if (td->type == RPM_STRING_TYPE) { + td->data = xstrdup(td->data); + td->data = strtolocale(td->data); + td->flags = RPMTD_ALLOCED; + 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]); + } + td->data = arr; + td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; + } return rc; } + /** * Retrieve summary text. * @param h header @@ -559,6 +702,16 @@ static int descriptionTag(Header h, rpmt return i18nTag(h, RPMTAG_DESCRIPTION, td); } +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 @@ -663,6 +816,8 @@ static const struct headerTagFunc_s rpmH { RPMTAG_LONGARCHIVESIZE, longarchivesizeTag }, { RPMTAG_LONGSIZE, longsizeTag }, { RPMTAG_LONGSIGSIZE, longsigsizeTag }, + { RPMTAG_CHANGELOGNAME, changelognameTag }, + { RPMTAG_CHANGELOGTEXT, changelogtextTag }, { 0, NULL } };