blob: 85e574bcb8cb7b6a420883439276128706d1ec5e [file] [log] [blame]
/* plugin_common - Routines common to several plugins
* Copyright (C) 2002-2009 Josh Coalson
* Copyright (C) 2011-2016 Xiph.Org Foundation
*
* Only slightly modified charset.c from:
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 1999-2001 Håvard Kvålen <havardk@xmms.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#ifdef HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif
#include "charset.h"
/*************
* Functions *
*************/
char* FLAC_plugin__charset_get_current (void)
{
char *charset = getenv("CHARSET");
#ifdef HAVE_LANGINFO_CODESET
if (!charset)
charset = nl_langinfo(CODESET);
#endif
if (!charset)
charset = "ISO-8859-1";
return charset;
}
#ifdef HAVE_ICONV
char* FLAC_plugin__charset_convert_string (const char *string, char *from, char *to)
{
size_t outleft, outsize, length;
iconv_t cd;
char *out, *outptr;
const char *input = string;
if (!string)
return NULL;
length = strlen(string);
if ((cd = iconv_open(to, from)) == (iconv_t)-1)
{
#ifndef NDEBUG
fprintf(stderr, "convert_string(): Conversion not supported. Charsets: %s -> %s", from, to);
#endif
return strdup(string);
}
/* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
/* + 1 for nul in case len == 1 */
outsize = ((length + 3) & ~3) + 1;
if(outsize < length) /* overflow check */
return NULL;
out = malloc(outsize);
outleft = outsize - 1;
outptr = out;
retry:
if (iconv(cd, (char**)&input, &length, &outptr, &outleft) == (size_t)(-1))
{
int used;
switch (errno)
{
case E2BIG:
used = outptr - out;
if((outsize - 1) * 2 + 1 <= outsize) { /* overflow check */
free(out);
return NULL;
}
outsize = (outsize - 1) * 2 + 1;
out = realloc(out, outsize);
outptr = out + used;
outleft = outsize - 1 - used;
goto retry;
case EINVAL:
break;
case EILSEQ:
/* Invalid sequence, try to get the rest of the string */
input++;
length = strlen(input);
goto retry;
default:
#ifndef NDEBUG
fprintf(stderr, "convert_string(): Conversion failed. Inputstring: %s; Error: %s", string, strerror(errno));
#endif
break;
}
}
*outptr = '\0';
iconv_close(cd);
return out;
}
#else
char* FLAC_plugin__charset_convert_string (const char *string, char *from, char *to)
{
(void)from, (void)to;
if (!string)
return NULL;
return strdup(string);
}
#endif
#ifdef HAVE_ICONV
int FLAC_plugin__charset_test_conversion (char *from, char *to)
{
iconv_t cd;
if ((cd=iconv_open(to,from)) == (iconv_t)-1)
{
/* Conversion not supported */
return 0;
}
iconv_close(cd);
return 1;
}
#else
int FLAC_plugin__charset_test_conversion (char *from, char *to)
{
(void)from, (void)to;
return 1;
}
#endif