Blame src/plugin_common/charset.c

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