commit 72582cbd92b17b2bd1c1de3c0ee6d012470e4756 Author: unknown author <cooker@mandrivalinux.org> Date: Mon Jan 5 13:29:57 2009 +0000 headerIconv - Make the spec as follows ... Summary: default summary Summary(ja_JP.eucJP): [some strings encoded in euc-jp] Name:hogefuga ... - Show summary in each locale. $ LANG=ja_JP.utf8 rpm -qp --qf "%{SUMMARY}\n" hogefuga.rpm [some strings encoded in euc-jp] do not display in UTF-8. This patch improve the parser of spec-file which are written in multi-languages. In case the language code is ja_JP , as you know ja_JP use some different encodings such as ja_JP.eucJP,ja_JP.sjis,ja_JP.utf8... When the spec-file are written in eucJP but the local LANG environment is UTF-8, rpm will display encoded characters not same as LANG environment(a.k.a Mojibake). So this patch will convert the data to a specific encoding which used in the selected locale. diff --git a/lib/header.c b/lib/header.c index 77e2473..876a246 100644 --- a/lib/header.c +++ b/lib/header.c @@ -9,6 +9,8 @@ /* network byte order and is converted on the fly to host order. */ #include "system.h" +#include <iconv.h> +#include <langinfo.h> #include <rpm/rpmtypes.h> #include <rpm/rpmstring.h> @@ -1214,6 +1216,54 @@ static int headerMatchLocale(const char *td, const char *l, const char *le) return 0; } +/** \ingroup header + * convert data to specific encoding used in the selected locale. + * @param td header i18n table data, NUL terminated + * @param indata original data + * @return converted data(or original data if failed) + */ +static const char *headerIconv(const char *td,const char *indata) +{ + char *tcode=NULL; + char *fcode=NULL; + + if( strstr(td,".") != NULL ){ + fcode=strchr(td,'.')+1; + tcode=nl_langinfo(CODESET); + if( tcode!=NULL && *tcode != '\0' && strcasecmp(fcode,tcode) != 0 ){ +// fprintf(stderr,"%s:fcode=%s,tcode=%s\n",__func__,fcode,tcode); + iconv_t conv = iconv_open(tcode,fcode); + if (conv != (iconv_t)-1) { + char *inp = indata; + char *outp,*outdata; + size_t inleft = strlen(indata); + size_t outleft; + size_t outdata_size = (inleft+1)*2; + outp = outdata = calloc(1,outdata_size); + outleft = outdata_size - 1; + int status = E2BIG; + + while (inleft > 0 && status == E2BIG) { + iconv(conv, &inp, &inleft, &outp, &outleft); + status = errno; + size_t used = outp-outdata; + char *newdest; + outdata_size *=2; + newdest = realloc(outdata,outdata_size); + if(newdest==NULL) break; + outdata = newdest; + outp = outdata+used; + outleft = outdata_size - used - 1; + *outp = '\0'; + } + iconv_close(conv); + return outdata; + } + } + } + return strdup(indata); +} + /** * Return i18n string from header that matches locale. * @param h header @@ -1246,6 +1296,7 @@ static int copyI18NEntry(Header h, indexEntry entry, rpmtd td, for (l = lang; *l != '\0'; l = le) { const char *t; char *ed, *ed_weak = NULL; + const char *t_weak = NULL; int langNum; while (*l && *l == ':') /* skip leading colons */ @@ -1262,24 +1313,20 @@ static int copyI18NEntry(Header h, indexEntry entry, rpmtd td, int match = headerMatchLocale(t, l, le); if (match == 1) { - td->data = ed; + td->data = headerIconv(t, ed); goto exit; } else if (match == 2) { ed_weak = ed; + t_weak = t; } } if (ed_weak) { - td->data = ed_weak; + td->data = headerIconv(t_weak, ed_weak); goto exit; } } exit: - if (flags & HEADERGET_ALLOC) { - td->data = xstrdup(td->data); - td->flags |= RPMTD_ALLOCED; - } - return 1; }