From 15064493bc7645573dcc9ef43c532f425378400e Mon Sep 17 00:00:00 2001 From: moritz Date: Sat, 25 Aug 2007 12:24:51 +0000 Subject: [PATCH] Get closer to what Icecast does (or will) expect wrt used codesets. I still disagree with the new ISO-8859-1 assumption for non-Ogg streams, because (for example) with ID3 tags, a codeset is simply not part of the specification and a better assumption would be that they are in the user's locale. Therefore, it would make more sense, IMO, to clearly specify that ANY metadata sent to Icecast should be UTF-8 and let the source client figure out the rest. This would also answer the question what codeset an /admin user should use if the content type of a mountpoint isn't known (although that can be figured out with an unclean read of the mountpoint's stats beforehand.) git-svn-id: https://svn.xiph.org/trunk/ezstream@13622 0101bb08-14d6-0310-b084-bc0e0c8e3800 --- src/ezstream.c | 14 ++++++-- src/metadata.c | 4 +-- src/util.c | 87 ++++++++++++++++++++++++++++++++------------------ src/util.h | 9 ++++-- 4 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/ezstream.c b/src/ezstream.c index f47089a..ca62e53 100644 --- a/src/ezstream.c +++ b/src/ezstream.c @@ -470,7 +470,7 @@ int setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy) { shout_metadata_t *shout_mdata = NULL; - char *songInfo; + char *songInfo, *encSongInfo; int ret = SHOUTERR_SUCCESS; if (shout == NULL) { @@ -496,7 +496,14 @@ setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy) songInfo = metadata_assemble_string(mdata); } - if (shout_metadata_add(shout_mdata, "song", songInfo) != SHOUTERR_SUCCESS) { + if (strcmp(pezConfig->format, VORBIS_FORMAT) == 0 || + strcmp(pezConfig->format, THEORA_FORMAT) == 0) + encSongInfo = xstrdup(songInfo); + else + encSongInfo = UTF8toISO8859_1(songInfo, ICONV_TRANSLIT); + + if (shout_metadata_add(shout_mdata, "song", (encSongInfo != NULL) ? encSongInfo : "") + != SHOUTERR_SUCCESS) { /* Assume SHOUTERR_MALLOC */ printf("%s: shout_metadata_add(): %s\n", __progname, strerror(ENOMEM)); @@ -511,6 +518,7 @@ setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy) *mdata_copy = xstrdup(songInfo); xfree(songInfo); + xfree(encSongInfo); return (ret); } @@ -854,7 +862,7 @@ streamFile(shout_t *shout, const char *fileName) char *tmp, *metaData; tmp = metadata_assemble_string(mdata); - metaData = utf82char(tmp); + metaData = UTF8toCHAR(tmp, ICONV_REPLACE); xfree(tmp); printf("%s: Streaming ``%s''", __progname, metaData); if (vFlag) diff --git a/src/metadata.c b/src/metadata.c index 18ab36f..c49f771 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -185,9 +185,9 @@ metadata_use_self(metadata_t *md, FILE **filep) fread(&id3tag, 1, sizeof(struct ID3Tag), *filep); if (memcmp(id3tag.tag, "TAG", 3) == 0) { if (strlen(id3tag.artistName) > 0) - md->artist = char2utf8(id3tag.artistName); + md->artist = CHARtoUTF8(id3tag.artistName, ICONV_REPLACE); if (strlen(id3tag.trackName) > 0) - md->title = char2utf8(id3tag.trackName); + md->title = CHARtoUTF8(id3tag.trackName, ICONV_REPLACE); } } else if (strcmp(extension, ".ogg") == 0) { OggVorbis_File vf; diff --git a/src/util.c b/src/util.c index 70a511a..6387d19 100644 --- a/src/util.c +++ b/src/util.c @@ -58,9 +58,7 @@ extern EZCONFIG *pezConfig; extern char *__progname; -#ifdef HAVE_ICONV -char * iconvert(const char *, const char *, const char *); -#endif /* HAVE_ICONV */ +char * iconvert(const char *, const char *, const char *, int); int strrcmp(const char *s, const char *sub) @@ -227,67 +225,68 @@ stream_setup(const char *host, const int port, const char *mount) } char * -char2utf8(const char *in_str) +CHARtoUTF8(const char *in_str, int mode) { -#ifdef HAVE_ICONV -# ifndef WIN32 +#ifndef WIN32 char *codeset; -# if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET) +# if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET) setlocale(LC_CTYPE, ""); codeset = nl_langinfo(CODESET); setlocale(LC_CTYPE, "C"); -# else - codeset = (char *)""; -# endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE */ # else + codeset = (char *)""; +# endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE */ +#else char codeset[24]; snprintf(codeset, sizeof(codeset), "CP%u", GetACP()); -# endif /* !WIN32 */ +#endif /* !WIN32 */ if (in_str == NULL || strlen(in_str) == 0) return (NULL); - return (iconvert(in_str, codeset, "UTF-8")); -#else - return (xstrdup(in_str)); -#endif /* HAVE_ICONV */ + return (iconvert(in_str, codeset, "UTF-8", mode)); } char * -utf82char(const char *in_str) +UTF8toCHAR(const char *in_str, int mode) { -#ifdef HAVE_ICONV -# ifndef WIN32 +#ifndef WIN32 char *codeset; -# if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET) +# if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET) setlocale(LC_CTYPE, ""); codeset = nl_langinfo(CODESET); setlocale(LC_CTYPE, "C"); -# else - codeset = (char *)""; -# endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE */ # else + codeset = (char *)""; +# endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE */ +#else char codeset[24]; snprintf(codeset, sizeof(codeset), "CP%u", GetACP()); -# endif /* !WIN32 */ +#endif /* !WIN32 */ if (in_str == NULL || strlen(in_str) == 0) return (NULL); - return (iconvert(in_str, "UTF-8", codeset)); -#else - return (xstrdup(in_str)); -#endif /* HAVE_ICONV */ + return (iconvert(in_str, "UTF-8", codeset, mode)); } -#ifdef HAVE_ICONV char * -iconvert(const char *in_str, const char *from, const char *to) +UTF8toISO8859_1(const char *in_str, int mode) { + if (in_str == NULL || strlen(in_str) == 0) + return (NULL); + + return (iconvert(in_str, "UTF-8", "ISO-8859-1", mode)); +} + +char * +iconvert(const char *in_str, const char *from, const char *to, int mode) +{ +#ifdef HAVE_ICONV iconv_t cd; ICONV_CONST char *input, *ip; size_t input_len; @@ -296,9 +295,31 @@ iconvert(const char *in_str, const char *from, const char *to) char buf[BUFSIZ], *bp; size_t bufavail; size_t out_pos; + char *tocode; - if ((cd = iconv_open(to, from)) == (iconv_t)-1 && + switch (mode) { + size_t siz; + + case ICONV_TRANSLIT: + siz = strlen(to) + strlen("//TRANSLIT") + 1; + tocode = xcalloc(siz, sizeof(char)); + snprintf(tocode, siz, "%s//TRANSLIT", to); + break; + case ICONV_IGNORE: + siz = strlen(to) + strlen("//IGNORE") + 1; + tocode = xcalloc(siz, sizeof(char)); + snprintf(tocode, siz, "%s//IGNORE", to); + break; + case ICONV_REPLACE: + /* FALLTHROUGH */ + default: + tocode = xstrdup(to); + break; + } + + if ((cd = iconv_open(tocode, from)) == (iconv_t)-1 && (cd = iconv_open("", from)) == (iconv_t)-1) { + xfree(tocode); printf("%s: iconv_open(): %s\n", strerror(errno), __progname); return (NULL); } @@ -340,9 +361,13 @@ iconvert(const char *in_str, const char *from, const char *to) if (iconv_close(cd) == -1) { printf("%s: iconv_close(): %s\n", strerror(errno), __progname); xfree(output); + xfree(tocode); return (NULL); } + xfree(tocode); return (output); -} +#else + return (xstrdup(in_str)); #endif /* HAVE_ICONV */ +} diff --git a/src/util.h b/src/util.h index b4c4bd5..bec18a2 100644 --- a/src/util.h +++ b/src/util.h @@ -20,10 +20,15 @@ #ifndef __UTIL_H__ #define __UTIL_H__ +#define ICONV_REPLACE 0 +#define ICONV_TRANSLIT 1 +#define ICONV_IGNORE 2 + int strrcmp(const char *, const char *); int strrcasecmp(const char *, const char *); shout_t * stream_setup(const char *, const int, const char *); -char * char2utf8(const char *); -char * utf82char(const char *); +char * CHARtoUTF8(const char *, int); +char * UTF8toCHAR(const char *, int); +char * UTF8toISO8859_1(const char *, int); #endif /* __UTIL_H__ */