Commit c0712176 authored by David Woodhouse's avatar David Woodhouse

Add openconnect_utf8_to_legacy() helper function for charset conversion

In some cases, the library itself really is going to have to know about
legacy non-UTF8 locales — when opening files or setting environment
variables, for example.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent b504080d
......@@ -25,6 +25,7 @@ lib_srcs_openssl = openssl.c
lib_srcs_win32 = tun-win32.c sspi.c
lib_srcs_posix = tun.c
lib_srcs_gssapi = gssapi.c
lib_srcs_iconv = iconv.c
POTFILES = $(openconnect_SOURCES) $(lib_srcs_openssl) $(lib_srcs_gnutls) \
$(library_srcs) $(lib_srcs_win32) $(lib_srcs_posix) $(lib_srcs_gssapi)
......@@ -38,6 +39,9 @@ endif
if OPENCONNECT_OPENSSL
library_srcs += $(lib_srcs_openssl)
endif
if OPENCONNECT_ICONV
library_srcs += $(lib_srcs_iconv)
endif
if OPENCONNECT_WIN32
library_srcs += $(lib_srcs_win32)
else
......@@ -46,7 +50,7 @@ endif
libopenconnect_la_SOURCES = version.c $(library_srcs)
libopenconnect_la_CFLAGS = $(AM_CFLAGS) $(SSL_CFLAGS) $(DTLS_SSL_CFLAGS) $(LIBXML2_CFLAGS) $(LIBPROXY_CFLAGS) $(ZLIB_CFLAGS) $(P11KIT_CFLAGS) $(TSS_CFLAGS) $(LIBSTOKEN_CFLAGS) $(LIBOATH_CFLAGS) $(GSSAPI_CFLAGS)
libopenconnect_la_LIBADD = $(SSL_LIBS) $(DTLS_SSL_LIBS) $(LIBXML2_LIBS) $(LIBPROXY_LIBS) $(ZLIB_LIBS) $(LIBINTL) $(P11KIT_LIBS) $(TSS_LIBS) $(LIBSTOKEN_LIBS) $(LIBOATH_LIBS) $(GSSAPI_LIBS)
libopenconnect_la_LIBADD = $(SSL_LIBS) $(DTLS_SSL_LIBS) $(LIBXML2_LIBS) $(LIBPROXY_LIBS) $(ZLIB_LIBS) $(LIBINTL) $(P11KIT_LIBS) $(TSS_LIBS) $(LIBSTOKEN_LIBS) $(LIBOATH_LIBS) $(GSSAPI_LIBS) $(LIBICONV)
if OPENBSD_LIBTOOL
# OpenBSD's libtool doesn't have -version-number, but its -version-info arg
# does what GNU libtool's -version-number does. Which arguably is what the
......
......@@ -181,8 +181,8 @@ AC_DISABLE_STATIC
AC_CHECK_FUNC(nl_langinfo, [AC_DEFINE(HAVE_NL_LANGINFO, 1, [Have nl_langinfo() function])], [])
have_iconv=no
if test "$ac_cv_func_nl_langinfo" = "yes"; then
have_iconv=no
LIBICONV=
AC_MSG_CHECKING([for iconv support])
AC_LINK_IFELSE([AC_LANG_PROGRAM([
......@@ -205,6 +205,7 @@ if test "$ac_cv_func_nl_langinfo" = "yes"; then
AC_DEFINE(HAVE_ICONV, 1, [Have iconv() function])
fi
fi
AM_CONDITIONAL(OPENCONNECT_ICONV, [test "$have_iconv" = "yes"])
AC_ARG_ENABLE([nls],
[ --disable-nls do not use Native Language Support],
......
/*
* OpenConnect (SSL + DTLS) VPN client
*
* Copyright © 2008-2014 Intel Corporation.
*
* Author: David Woodhouse <dwmw2@infradead.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1, as published by the Free Software Foundation.
*
* 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
* Lesser General Public License for more details.
*/
#include <config.h>
#include <iconv.h>
#include <errno.h>
#include <string.h>
#include "openconnect-internal.h"
static char *convert_str(struct openconnect_info *vpninfo, iconv_t ic,
char *instr)
{
char *ic_in, *ic_out, *outstr;
size_t insize, outsize;
int addq = 0;
if (ic == (iconv_t)-1)
return instr;
iconv(ic, NULL, NULL, NULL, NULL);
insize = strlen(instr) + 1;
ic_in = instr;
outsize = insize;
ic_out = outstr = malloc(outsize);
if (!outstr)
return instr;
while (insize) {
if (iconv(ic, &ic_in, &insize, &ic_out, &outsize) == (size_t)-1) {
perror("iconv");
if (errno == EILSEQ) {
do {
ic_in++;
insize--;
} while (insize && (ic_in[0] & 0xc0) == 0x80);
addq = 1;
}
if (!outsize || errno == E2BIG) {
int outlen = ic_out - outstr;
realloc_inplace(outstr, outlen + 10);
if (!outstr)
return instr;
ic_out = outstr + outlen;
outsize = 10;
} else if (errno != EILSEQ) {
/* Should never happen */
free(outstr);
return instr;
}
if (addq) {
addq = 0;
*(ic_out++) = '?';
outsize--;
}
}
}
return outstr;
}
char *openconnect_legacy_to_utf8(struct openconnect_info *vpninfo,
const char *legacy)
{
return convert_str(vpninfo, vpninfo->ic_legacy_to_utf8, (char *)legacy);
}
char *openconnect_utf8_to_legacy(struct openconnect_info *vpninfo,
const char *utf8)
{
return convert_str(vpninfo, vpninfo->ic_utf8_to_legacy, (char *)utf8);
}
......@@ -45,10 +45,22 @@ struct openconnect_info *openconnect_vpninfo_new(char *useragent,
void *privdata)
{
struct openconnect_info *vpninfo = calloc(sizeof(*vpninfo), 1);
#ifdef HAVE_ICONV
char *charset = nl_langinfo(CODESET);
#endif
if (!vpninfo)
return NULL;
#ifdef HAVE_ICONV
if (charset && strcmp(charset, "UTF-8")) {
vpninfo->ic_utf8_to_legacy = iconv_open(charset, "UTF-8");
vpninfo->ic_legacy_to_utf8 = iconv_open("UTF-8", charset);
} else {
vpninfo->ic_utf8_to_legacy = (iconv_t)-1;
vpninfo->ic_legacy_to_utf8 = (iconv_t)-1;
}
#endif
#ifndef _WIN32
vpninfo->tun_fd = -1;
#endif
......@@ -141,6 +153,11 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
close(vpninfo->cmd_fd);
close(vpninfo->cmd_fd_write);
}
#ifdef HAVE_ICONV
iconv_close(vpninfo->ic_utf8_to_legacy);
iconv_close(vpninfo->ic_legacy_to_utf8);
#endif
#ifdef _WIN32
if (vpninfo->cmd_event)
CloseHandle(vpninfo->cmd_event);
......
......@@ -62,6 +62,11 @@
#endif
#endif
#ifdef HAVE_ICONV
#include <langinfo.h>
#include <iconv.h>
#endif
#include <zlib.h>
#include <stdint.h>
#include <sys/time.h>
......@@ -174,6 +179,10 @@ struct proxy_auth_state {
};
struct openconnect_info {
#ifdef HAVE_ICONV
iconv_t ic_legacy_to_utf8;
iconv_t ic_utf8_to_legacy;
#endif
char *redirect_url;
int redirect_type;
......@@ -521,6 +530,15 @@ int dumb_socketpair(int socks[2], int make_overlapped);
/****************************************************************************/
/* iconv.c */
#ifdef HAVE_ICONV
char *openconnect_utf8_to_legacy(struct openconnect_info *vpninfo, const char *utf8);
char *openconnect_legacy_to_utf8(struct openconnect_info *vpninfo, const char *legacy);
#else
#define openconnect_utf8_to_legacy(v, str) ((char *)str)
#define openconnect_legacy_to_utf8(v, str) ((char *)str)
#endif
/* script.c */
int setenv_int(const char *opt, int value);
void set_script_env(struct openconnect_info *vpninfo);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment