Fix bug # 177756 - eliminate dependency on libNLS.

If HAVE_LIBNLS is not defined, OS functions (iconv and Win32
	native APIs) are used for character set conversion of command
	line arguments.
Fix bug # 177766 - LDAP tools should reject second -h argument.
	A second -p argument is also rejected.
Fix bug # 159139 - HP/UX: LDAP command line tools do no charset conversion.
	Removed special case makefile rules for convutf8.cpp on HP/UX.
This commit is contained in:
mcs%netscape.com 2002-12-04 17:21:55 +00:00
parent 3832b1fc62
commit 150e89eb05
7 changed files with 267 additions and 93 deletions

View File

@ -92,7 +92,7 @@ LDAPMODIFY_OBJ = $(addprefix $(OBJDEST)/, ldapmodify.o)
LDAPSEARCH_OBJ = $(addprefix $(OBJDEST)/, ldapsearch.o)
LDAPCOMPARE_OBJ = $(addprefix $(OBJDEST)/, ldapcompare.o)
LDAPCMP_OBJ = $(addprefix $(OBJDEST)/, ldapcmp.o)
ifeq ($(OS_ARCH), HP-UX)
ifeq ($(OS_ARCH), used-to-use-this-on-HP-UX)
LDAPTOOLCOMMON_OBJ = $(addprefix $(OBJDEST)/, common.o) \
$(addprefix $(OBJDEST)/, fileurl.o)
else
@ -106,7 +106,7 @@ LDAPTOOLCOMMON_OBJ += $(addprefix $(OBJDEST)/, argpin.o) \
endif
endif
ifeq ($(OS_ARCH), HP-UX)
ifeq ($(OS_ARCH), used-to-use-this-on-HP-UX)
LDAPTOOLCPPCOMMON_OBJ = $(addprefix $(OBJDEST)/, convutf8.o)
endif
@ -238,7 +238,7 @@ LIBLOCATION = $(NSCP_DISTDIR)/$(OBJDIR_NAME)/lib
###########################################################################
all:: $(BINS) $(OBJDEST) linklibnls libdir $(BINS)
all:: $(OBJDEST) linklibnls libdir $(BINS)
libdir: linklibnls
ifeq ($(OS_ARCH), WINNT)
@ -324,7 +324,7 @@ endif
$(LDAPTOOLCOMMON_OBJ):
ifeq ($(OS_ARCH), HP-UX)
ifeq ($(OS_ARCH), used-to-use-this-on-HP-UX)
$(LDAPTOOLCPPCOMMON_OBJ): convutf8.cpp
ifneq ($(USE_64), 1)
/opt/aCC/bin/aCC -ext -DHPUX_ACC -D__STDC_EXT__ -D_POSIX_C_SOURCE=199506L -c -DHPUX11 -DHPUX11_00 +DAportable +DS1.1 -D_LARGEFILE64_SOURCE -D_PR_HAVE_OFF64_T -DNO_NODELOCK -DNO_LIBLCACHE -DXP_UNIX -DHPUX -DMCC_HTTPD -DNS_DOMESTIC -DNET_SSL -DCLIENT_AUTH -DNSPR20 -D_PR_NTHREAD -D_PR_USECPU -D_REENTRANT -DNS_DS -DSPAPI20 -DBUILD_NUM=\"01.081.1519\" -DCPU_hppa -DOS_hpux -D_NO_THREADS_ -Dhpux -Dhpux -D_HPUX_SOURCE -D_REENTRANT -Aa -DLDAP_REFERRALS -DLDAP_LDBM -DLDAP_LDIF -DLDBM_USE_DBBTREE -DSLAPD_PASSWD_SHA1 -D__DBINTERFACE_PRIVATE -DNO_LIBLCACHE -DNS_DIRECTORY -DNET_SSL -DUSE_NSPR_MT -O $(INCLUDES) convutf8.cpp -o $(OBJDIR_NAME)/convutf8.o

View File

@ -140,7 +140,8 @@ ldaptool_common_usage( int two_hosts )
}
/* globals */
char *ldaptool_charset = "";
char *ldaptool_charset = NULL;
char *ldaptool_convdir = NULL;
char *ldaptool_host = LDAPTOOL_DEFHOST;
char *ldaptool_host2 = LDAPTOOL_DEFHOST;
int ldaptool_port = LDAP_PORT;
@ -383,8 +384,13 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
case 'h': /* ldap host */
if ( hostnum == 0 ) {
ldaptool_host = strdup( optarg );
} else {
} else if ( two_hosts ) {
ldaptool_host2 = strdup( optarg );
} else {
fprintf( stderr,
"%s: only one host (-h option) should be specified\n",
ldaptool_progname );
return(-1); /* usage error */
}
++hostnum;
break;
@ -400,10 +406,16 @@ ldaptool_process_args( int argc, char **argv, char *extra_opts,
if ( !user_specified_port ) {
++user_specified_port;
ldaptool_port = atoi( optarg );
} else {
} else if ( two_hosts ) {
++user_specified_port2;
ldaptool_port2 = atoi( optarg );
} else {
fprintf( stderr,
"%s: only one port (-p option) should be specified\n",
ldaptool_progname );
return(-1); /* usage error */
}
break;
#if defined(NET_SSL)
case 'P': /* path to security database */
@ -1026,7 +1038,7 @@ ldaptool_bind( LDAP *ld )
/*
* do the bind, backing off one LDAP version if necessary
*/
conv = ldaptool_local2UTF8( binddn );
conv = ldaptool_local2UTF8( binddn, "bind DN" );
/*
* if using LDAPv3 and client auth., try a SASL EXTERNAL bind

View File

@ -20,55 +20,261 @@
* Contributor(s):
*/
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#define VC_EXTRALEAN
#include <afxwin.h>
#include <winnls.h>
static char *win_char_converter(const char *instr, int bFromUTF8);
#else
#include <locale.h>
#endif
#include "ldaptool.h"
#ifndef HAVE_LIBNLS
#ifndef _WIN32
#include <iconv.h>
#include <langinfo.h> /* for nl_langinfo() */
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern char *ldaptool_charset;
char *ldaptool_convdir = NULL;
static int charsetset = 0;
char *ldaptool_local2UTF8( const char *src );
/* OS name for the UTF-8 character set */
#if defined(_HPUX_SOURCE)
#define LDAPTOOL_CHARSET_UTF8 "utf8" /* HP/UX */
#else
#define LDAPTOOL_CHARSET_UTF8 "UTF-8" /* all others */
#endif
/* OS name for the default character set */
#if defined(_HPUX_SOURCE)
#define LDAPTOOL_CHARSET_DEFAULT "roma8" /* HP/UX */
#elif defined(__GLIBC__)
#define LDAPTOOL_CHARSET_DEFAULT "US-ASCII" /* glibc (Linux) */
#else
#define LDAPTOOL_CHARSET_DEFAULT "646" /* all others */
#endif
/* Type used for the src parameter to iconv() (the 2nd parameter) */
#if defined(_HPUX_SOURCE) || defined(__GLIBC__)
#define LDAPTOOL_ICONV_SRC_TYPE char ** /* HP/UX and glibc (Linux) */
#else
#define LDAPTOOL_ICONV_SRC_TYPE const char ** /* all others */
#endif
#if defined(SOLARIS)
/*
* On some versions of Solaris, the inbytesleft parameter can't be NULL
* even in calls to iconv() where inbuf itself is NULL
*/
#define LDAPTOOL_ICONV_NO_NULL_INBYTESLEFT 1
#endif
static char *convert_to_utf8( const char *src );
#ifndef _WIN32
static const char *GetCurrentCharset(void);
#endif
/* Version that uses OS functions */
char *
ldaptool_local2UTF8( const char *src )
ldaptool_local2UTF8( const char *src, const char *desc )
{
char *utf8;
char *utf8;
charsetset = 0;
if ( src == NULL ) { /* trivial case # 1 */
utf8 = NULL;
} else if ( *src == '\0' ) { /* trivial case # 2 */
utf8 = strdup( "" );
} else {
utf8 = convert_to_utf8( src ); /* the real deal */
if (src == NULL)
{
return NULL;
if ( NULL == utf8 ) {
utf8 = strdup( utf8); /* fallback: no conversion */
fprintf( stderr, "%s: warning: no conversion of %s to "
LDAPTOOL_CHARSET_UTF8 "\n", desc, ldaptool_progname );
}
}
utf8 = strdup(src);
return ( utf8 );
return utf8;
}
#else /* HAVE_LIBNLS */
#ifdef _WIN32
/*
* Try to convert src to a UTF-8.
* Returns a malloc'd string or NULL upon error (with messages logged).
* src should not be NULL.
*/
static char *
convert_to_utf8( const char *src ) /* returns NULL on error */
{
return win_char_converter( src, FALSE );
}
#else /* _WIN32 */
/*
* Try to convert src to a UTF-8.
* Returns a malloc'd string or NULL upon error (with messages logged).
* src should not be NULL.
*/
static char *
convert_to_utf8( const char *src )
{
static const char *src_charset = NULL;
iconv_t convdesc;
char *outbuf, *curoutbuf;
size_t inbytesleft, outbytesleft;
#ifdef LDAPTOOL_ICONV_NO_NULL_INBYTESLEFT
#define LDAPTOOL_ICONV_UNUSED_INBYTESLEFT &inbytesleft
#else
#define LDAPTOOL_ICONV_UNUSED_INBYTESLEFT NULL
#endif
/* Determine the source charset if not already done */
if ( NULL == src_charset ) {
if ( NULL != ldaptool_charset && 0 != strcmp( ldaptool_charset, "" )) {
src_charset = ldaptool_charset;
} else {
src_charset = GetCurrentCharset();
}
}
if ( NULL != src_charset
&& 0 == strcmp( LDAPTOOL_CHARSET_UTF8, src_charset )) {
/* no conversion needs to be done */
return strdup( src );
}
/* Get a converter */
convdesc = iconv_open( LDAPTOOL_CHARSET_UTF8, src_charset );
if ( (iconv_t)-1 == convdesc ) {
if ( errno == EINVAL ) {
fprintf( stderr, "%s: conversion from %s to %s is not supported\n",
ldaptool_progname, src_charset, LDAPTOOL_CHARSET_UTF8 );
} else {
perror( src_charset );
}
return NULL;
}
/* Allocate room for the UTF-8 equivalent (maximum expansion = 6 times) */
/* XXX is that correct? */
inbytesleft = strlen( src );
outbytesleft = 6 * inbytesleft + 1;
if ( NULL == ( outbuf = (char *)malloc( outbytesleft ))) {
perror( "convert_to_utf8 - malloc" );
iconv_close( convdesc );
return NULL;
}
curoutbuf = outbuf;
/*
* Three steps for a good conversion:
* 1) Insert the initial shift sequence if any.
* 2) Convert our characters.
* 3) Insert the closing shift sequence, if any.
*/
if ( (size_t)-1 == iconv( convdesc,
( LDAPTOOL_ICONV_SRC_TYPE )0, LDAPTOOL_ICONV_UNUSED_INBYTESLEFT,
&curoutbuf, &outbytesleft ) /* initial shift seq. */
|| (size_t)-1 == iconv( convdesc,
( LDAPTOOL_ICONV_SRC_TYPE ) &src, &inbytesleft,
&curoutbuf, &outbytesleft ) /* convert our chars. */
|| (size_t)-1 == iconv( convdesc,
( LDAPTOOL_ICONV_SRC_TYPE )0, LDAPTOOL_ICONV_UNUSED_INBYTESLEFT,
&curoutbuf, &outbytesleft )) { /* closing shift seq. */
perror( "convert_to_utf8 - iconv" );
iconv_close( convdesc );
free( outbuf );
return NULL;
}
iconv_close( convdesc );
*curoutbuf = '\0'; /* zero-terminate the resulting string */
return outbuf;
}
/* returns a malloc'd string */
static const char *
GetCurrentCharset(void)
{
static char *locale = NULL;
const char *charset;
if ( NULL == locale ) {
locale = setlocale(LC_CTYPE, ""); /* need to call this once */
}
charset = nl_langinfo( CODESET );
if ( NULL == charset || '\0' == *charset ) {
charset = LDAPTOOL_CHARSET_DEFAULT;
}
return strdup( charset );
}
#endif /* else _WIN32 */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !HAVE_LIBNLS */
#ifdef _WIN32
/* returns a malloc'd string */
static char *
win_char_converter(const char *instr, int bFromUTF8)
{
char *outstr = NULL;
int inlen, wclen, outlen;
LPWSTR wcstr;
if (instr == NULL)
return NULL;
if ((inlen = strlen(instr)) <= 0)
return NULL;
/* output never becomes longer than input, XXXmcs: really true?
** thus we don't have to ask for the length
*/
wcstr = (LPWSTR) malloc( sizeof( WCHAR ) * (inlen+1) );
if (!wcstr)
return NULL;
wclen = MultiByteToWideChar(bFromUTF8 ? CP_UTF8 : CP_ACP, 0, instr,
inlen, wcstr, inlen);
outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr,
wclen, NULL, 0, NULL, NULL);
if (outlen > 0) {
outstr = (char *) malloc(outlen + 2);
outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr,
wclen, outstr, outlen, NULL, NULL);
if (outlen > 0)
*(outstr+outlen) = _T('\0');
else
return NULL;
}
free( wcstr );
return outstr;
}
#endif /* _WIN32 */
#ifdef HAVE_LIBNLS
#define NSPR20
#ifdef XP_WIN32
#define VC_EXTRALEAN
#include <afxwin.h>
#include <winnls.h>
#endif
extern char *ldaptool_charset;
static int charsetset = 0;
extern "C" {
char *ldaptool_convdir = NULL;
char *ldaptool_local2UTF8( const char * );
}
#ifndef XP_WIN32
#ifndef _WIN32
char * GetNormalizedLocaleName(void);
#include "unistring.h"
@ -78,7 +284,8 @@ extern NLS_StaticConverterRegistry _STATICLINK_NSJPN_;
extern NLS_StaticConverterRegistry _STATICLINK_NSCCK_;
extern NLS_StaticConverterRegistry _STATICLINK_NSSB_;
char *
/* returns a malloc'd string */
static char *
GetNormalizedLocaleName(void)
{
#ifdef _HPUX_SOURCE
@ -472,52 +679,14 @@ GetCharsetFromLocale(char *locale)
return tmpcharset;
}
#endif /* Not defined XP_WIN32 */
#ifdef XP_WIN32
char *_convertor(const char *instr, int bFromUTF8)
{
char *outstr = NULL;
int inlen, wclen, outlen;
LPWSTR wcstr;
if (instr == NULL)
return NULL;
if ((inlen = strlen(instr)) <= 0)
return NULL;
/* output never becomes longer than input,
** thus we don't have to ask for the length
*/
wcstr = (LPWSTR) malloc( sizeof( WCHAR ) * (inlen+1) );
if (!wcstr)
return NULL;
wclen = MultiByteToWideChar(bFromUTF8 ? CP_UTF8 : CP_ACP, 0, instr,
inlen, wcstr, inlen);
outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr,
wclen, NULL, 0, NULL, NULL);
if (outlen > 0) {
outstr = (char *) malloc(outlen + 2);
outlen = WideCharToMultiByte(bFromUTF8 ? CP_ACP : CP_UTF8, 0, wcstr,
wclen, outstr, outlen, NULL, NULL);
if (outlen > 0)
*(outstr+outlen) = _T('\0');
else
return NULL;
}
free( wcstr );
return outstr;
}
#endif
#endif /* !_WIN32 */
/* version that uses libNLS */
char *
ldaptool_local2UTF8( const char *src )
ldaptool_local2UTF8( const char *src, const char *desc )
{
char *utf8;
#ifndef XP_WIN32
#ifndef _WIN32
char *locale, *newcharset;
size_t outLen, resultLen;
NLS_ErrorCode err;
@ -581,7 +750,7 @@ ldaptool_local2UTF8( const char *src )
NLS_EncTerminate();
#else
utf8 = _convertor(src, FALSE);
utf8 = win_char_converter(src, FALSE);
if( utf8 == NULL )
utf8 = strdup(src);
#endif
@ -589,10 +758,3 @@ ldaptool_local2UTF8( const char *src )
return utf8;
}
#endif /* HAVE_LIBNLS */
#ifndef HAVE_LIBNLS
#ifdef __cplusplus
}
#endif
#endif

View File

@ -91,7 +91,7 @@ main( int argc, char **argv )
usage( LDAP_PARAM_ERROR );
}
typeval = ldaptool_local2UTF8( argv[optind] );
typeval = ldaptool_local2UTF8( argv[optind], "type and value" );
if (( rc = typeval2berval( typeval, &type, &bv )) != LDAP_SUCCESS ) {
fprintf( stderr, "%s: unable to parse \"%s\"\n",
ldaptool_progname, argv[optind] );
@ -107,7 +107,7 @@ main( int argc, char **argv )
++optind ) {
char *conv;
conv = ldaptool_local2UTF8( argv[ optind ] );
conv = ldaptool_local2UTF8( argv[ optind ], "DN" );
rc = docompare( ld, conv, type, &bv, ldaptool_request_ctrls );
if ( conv != NULL ) {
free( conv );

View File

@ -89,7 +89,7 @@ main( int argc, char **argv )
for ( ; optind < argc; ++optind ) {
char *conv;
conv = ldaptool_local2UTF8( argv[ optind ] );
conv = ldaptool_local2UTF8( argv[ optind ], "DN" );
rc = dodelete( ld, conv, ldaptool_request_ctrls );
if( conv != NULL )
free( conv );

View File

@ -175,7 +175,7 @@ main( int argc, char **argv )
filtpattern = "%s";
} else { /* there are additional args (filter + attrs) */
if ( ldaptool_fp == NULL || strstr( argv[ optind ], "%s" ) != NULL ) {
filtpattern = ldaptool_local2UTF8( argv[ optind ] );
filtpattern = ldaptool_local2UTF8( argv[ optind ], "filter" );
++optind;
} else {
filtpattern = "%s";
@ -232,7 +232,7 @@ main( int argc, char **argv )
if ( ldaptool_fp == NULL ) {
char *conv;
conv = ldaptool_local2UTF8( base );
conv = ldaptool_local2UTF8( base, "base DN" );
rc = dosearch( ld, conv, scope, attrs, attrsonly, filtpattern, "" );
if( conv != NULL )
free( conv );

View File

@ -157,7 +157,7 @@ LDAPControl *ldaptool_create_proxyauth_control( LDAP *ld );
void ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array);
void ldaptool_reset_control_array( LDAPControl **array );
char *ldaptool_get_tmp_dir( void );
char *ldaptool_local2UTF8( const char * );
char *ldaptool_local2UTF8( const char *s, const char *desc );
int ldaptool_berval_is_ascii( const struct berval *bvp );
int ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism,
const struct berval *cred, LDAPControl **serverctrls,