openldap/libraries/libldap/url.c

1617 lines
29 KiB
C
Raw Normal View History

/* LIBLDAP url.c -- LDAP URL (RFC 4516) related routines */
/* $OpenLDAP$ */
2003-11-26 15:16:36 +08:00
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
1998-08-09 08:43:13 +08:00
*
2007-01-03 04:00:42 +08:00
* Copyright 1998-2007 The OpenLDAP Foundation.
2003-11-26 15:16:36 +08:00
* All rights reserved.
1998-08-09 08:43:13 +08:00
*
2003-11-26 15:16:36 +08:00
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* Portions Copyright (c) 1996 Regents of the University of Michigan.
* All rights reserved.
*/
/*
1998-08-09 08:43:13 +08:00
* LDAP URLs look like this:
2007-04-03 11:27:24 +08:00
* ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
1998-08-09 08:43:13 +08:00
*
* where:
* attributes is a comma separated list
* scope is one of these three strings: base one sub (default=base)
* filter is an string-represented filter as in RFC 4515
1998-08-09 08:43:13 +08:00
*
2001-12-09 10:34:45 +08:00
* e.g., ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension
1998-08-09 08:43:13 +08:00
*
* We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
*/
#include "portable.h"
1998-08-09 08:43:13 +08:00
#include <stdio.h>
1999-06-03 08:37:44 +08:00
#include <ac/stdlib.h>
#include <ac/ctype.h>
1998-08-09 08:43:13 +08:00
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
1998-08-09 08:43:13 +08:00
#include "ldap-int.h"
/* local functions */
1999-07-20 03:32:47 +08:00
static const char* skip_url_prefix LDAP_P((
const char *url,
int *enclosedp,
const char **scheme ));
1998-08-09 08:43:13 +08:00
int ldap_pvt_url_scheme2proto( const char *scheme )
{
assert( scheme != NULL );
if( scheme == NULL ) {
return -1;
}
if( strcmp("ldap", scheme) == 0 ) {
return LDAP_PROTO_TCP;
}
if( strcmp("ldapi", scheme) == 0 ) {
return LDAP_PROTO_IPC;
}
if( strcmp("ldaps", scheme) == 0 ) {
return LDAP_PROTO_TCP;
}
#ifdef LDAP_CONNECTIONLESS
if( strcmp("cldap", scheme) == 0 ) {
return LDAP_PROTO_UDP;
}
#endif
return -1;
}
2004-08-28 11:53:31 +08:00
int ldap_pvt_url_scheme_port( const char *scheme, int port )
{
assert( scheme != NULL );
2004-08-28 11:53:31 +08:00
if( port ) return port;
if( scheme == NULL ) return port;
if( strcmp("ldap", scheme) == 0 ) {
return LDAP_PORT;
}
if( strcmp("ldapi", scheme) == 0 ) {
return -1;
}
if( strcmp("ldaps", scheme) == 0 ) {
return LDAPS_PORT;
}
#ifdef LDAP_CONNECTIONLESS
if( strcmp("cldap", scheme) == 0 ) {
return LDAP_PORT;
}
#endif
return -1;
}
2001-12-07 12:03:25 +08:00
int
ldap_pvt_url_scheme2tls( const char *scheme )
{
assert( scheme != NULL );
if( scheme == NULL ) {
return -1;
}
return strcmp("ldaps", scheme) == 0;
}
1998-08-09 08:43:13 +08:00
int
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
ldap_is_ldap_url( LDAP_CONST char *url )
1998-08-09 08:43:13 +08:00
{
int enclosed;
const char * scheme;
1998-08-09 08:43:13 +08:00
1999-07-20 03:32:47 +08:00
if( url == NULL ) {
return 0;
}
if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
1999-07-20 03:32:47 +08:00
return 0;
}
return 1;
1998-08-09 08:43:13 +08:00
}
1999-07-20 03:32:47 +08:00
int
ldap_is_ldaps_url( LDAP_CONST char *url )
{
int enclosed;
const char * scheme;
1999-07-20 03:32:47 +08:00
if( url == NULL ) {
return 0;
}
if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
1999-07-20 03:32:47 +08:00
return 0;
}
return strcmp(scheme, "ldaps") == 0;
}
int
ldap_is_ldapi_url( LDAP_CONST char *url )
{
int enclosed;
const char * scheme;
if( url == NULL ) {
return 0;
}
if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
return 0;
}
return strcmp(scheme, "ldapi") == 0;
1999-07-20 03:32:47 +08:00
}
1998-08-09 08:43:13 +08:00
#ifdef LDAP_CONNECTIONLESS
int
ldap_is_ldapc_url( LDAP_CONST char *url )
{
int enclosed;
const char * scheme;
if( url == NULL ) {
return 0;
}
if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
return 0;
}
return strcmp(scheme, "cldap") == 0;
}
#endif
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
static const char*
1999-07-20 03:32:47 +08:00
skip_url_prefix(
const char *url,
int *enclosedp,
const char **scheme )
1998-08-09 08:43:13 +08:00
{
2001-11-29 00:49:46 +08:00
/*
* return non-zero if this looks like a LDAP URL; zero if not
* if non-zero returned, *urlp will be moved past "ldap://" part of URL
*/
const char *p;
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
if ( url == NULL ) {
return( NULL );
1998-08-09 08:43:13 +08:00
}
p = url;
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
1998-08-09 08:43:13 +08:00
/* skip leading '<' (if any) */
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
if ( *p == '<' ) {
1998-08-09 08:43:13 +08:00
*enclosedp = 1;
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
++p;
1998-08-09 08:43:13 +08:00
} else {
*enclosedp = 0;
}
/* skip leading "URL:" (if any) */
if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
p += LDAP_URL_URLCOLON_LEN;
1998-08-09 08:43:13 +08:00
}
1999-07-20 03:32:47 +08:00
/* check for "ldap://" prefix */
if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldap://" prefix and return success */
p += LDAP_URL_PREFIX_LEN;
*scheme = "ldap";
1999-07-20 03:32:47 +08:00
return( p );
}
/* check for "ldaps://" prefix */
if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldaps://" prefix and return success */
p += LDAPS_URL_PREFIX_LEN;
*scheme = "ldaps";
return( p );
}
/* check for "ldapi://" prefix */
if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
/* skip over "ldapi://" prefix and return success */
p += LDAPI_URL_PREFIX_LEN;
*scheme = "ldapi";
1999-07-20 03:32:47 +08:00
return( p );
1998-08-09 08:43:13 +08:00
}
#ifdef LDAP_CONNECTIONLESS
/* check for "cldap://" prefix */
if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) {
/* skip over "cldap://" prefix and return success */
p += LDAPC_URL_PREFIX_LEN;
*scheme = "cldap";
return( p );
}
#endif
1999-07-20 03:32:47 +08:00
return( NULL );
1998-08-09 08:43:13 +08:00
}
2006-09-06 20:04:33 +08:00
int
ldap_pvt_scope2bv( int scope, struct berval *bv )
1999-07-20 03:32:47 +08:00
{
2006-09-06 20:04:33 +08:00
switch ( scope ) {
case LDAP_SCOPE_BASE:
BER_BVSTR( bv, "base" );
break;
1999-07-20 03:32:47 +08:00
2006-09-06 20:04:33 +08:00
case LDAP_SCOPE_ONELEVEL:
BER_BVSTR( bv, "one" );
break;
1999-07-20 03:32:47 +08:00
2006-09-06 20:04:33 +08:00
case LDAP_SCOPE_SUBTREE:
BER_BVSTR( bv, "sub" );
break;
1999-07-20 03:32:47 +08:00
2006-09-06 20:04:33 +08:00
case LDAP_SCOPE_SUBORDINATE:
BER_BVSTR( bv, "subordinate" );
break;
default:
return LDAP_OTHER;
}
1999-07-20 03:32:47 +08:00
2006-09-06 20:04:33 +08:00
return LDAP_SUCCESS;
}
2003-12-18 01:55:27 +08:00
2006-09-06 20:04:33 +08:00
const char *
ldap_pvt_scope2str( int scope )
{
struct berval bv;
2003-12-18 01:55:27 +08:00
2006-09-06 20:04:33 +08:00
if ( ldap_pvt_scope2bv( scope, &bv ) == LDAP_SUCCESS ) {
return bv.bv_val;
}
return NULL;
}
int
ldap_pvt_bv2scope( struct berval *bv )
{
static struct {
struct berval bv;
int scope;
} v[] = {
{ BER_BVC( "one" ), LDAP_SCOPE_ONELEVEL },
{ BER_BVC( "onelevel" ), LDAP_SCOPE_ONELEVEL },
{ BER_BVC( "base" ), LDAP_SCOPE_BASE },
{ BER_BVC( "sub" ), LDAP_SCOPE_SUBTREE },
{ BER_BVC( "subtree" ), LDAP_SCOPE_SUBTREE },
{ BER_BVC( "subord" ), LDAP_SCOPE_SUBORDINATE },
{ BER_BVC( "subordinate" ), LDAP_SCOPE_SUBORDINATE },
{ BER_BVC( "children" ), LDAP_SCOPE_SUBORDINATE },
{ BER_BVNULL, -1 }
};
int i;
for ( i = 0; v[ i ].scope != -1; i++ ) {
if ( ber_bvstrcasecmp( bv, &v[ i ].bv ) == 0 ) {
return v[ i ].scope;
}
1999-07-20 03:32:47 +08:00
}
return( -1 );
}
2006-09-06 20:04:33 +08:00
int
ldap_pvt_str2scope( const char *p )
{
struct berval bv;
ber_str2bv( p, 0, 0, &bv );
return ldap_pvt_bv2scope( &bv );
}
static const char hex[] = "0123456789ABCDEF";
#define URLESC_NONE 0x0000U
#define URLESC_COMMA 0x0001U
#define URLESC_SLASH 0x0002U
static int
hex_escape_len( const char *s, unsigned list )
2001-09-25 02:30:57 +08:00
{
int len;
2001-09-25 02:30:57 +08:00
if ( s == NULL ) {
return 0;
}
2001-09-25 02:30:57 +08:00
for ( len = 0; s[0]; s++ ) {
switch ( s[0] ) {
/* RFC 2396: reserved */
case '?':
len += 3;
break;
case ',':
if ( list & URLESC_COMMA ) {
len += 3;
} else {
len++;
}
break;
case '/':
if ( list & URLESC_SLASH ) {
len += 3;
} else {
len++;
}
break;
case ';':
case ':':
case '@':
case '&':
case '=':
case '+':
case '$':
/* RFC 2396: unreserved mark */
case '-':
case '_':
case '.':
case '!':
case '~':
case '*':
case '\'':
case '(':
case ')':
len++;
break;
/* RFC 2396: unreserved alphanum */
default:
if ( !isalnum( (unsigned char) s[0] ) ) {
len += 3;
} else {
len++;
}
break;
}
}
return len;
}
static int
hex_escape( char *buf, int len, const char *s, unsigned list )
{
int i;
int pos;
if ( s == NULL ) {
return 0;
}
for ( pos = 0, i = 0; s[i] && pos < len; i++ ) {
int escape = 0;
switch ( s[i] ) {
/* RFC 2396: reserved */
case '?':
escape = 1;
break;
case ',':
if ( list & URLESC_COMMA ) {
2001-09-25 02:30:57 +08:00
escape = 1;
}
break;
2001-09-25 02:30:57 +08:00
case '/':
if ( list & URLESC_SLASH ) {
escape = 1;
}
break;
case ';':
case ':':
case '@':
case '&':
case '=':
case '+':
case '$':
/* RFC 2396: unreserved mark */
case '-':
case '_':
case '.':
case '!':
case '~':
case '*':
case '\'':
case '(':
case ')':
break;
/* RFC 2396: unreserved alphanum */
default:
if ( !isalnum( (unsigned char) s[i] ) ) {
escape = 1;
}
break;
2001-09-25 02:30:57 +08:00
}
if ( escape ) {
2001-09-25 02:30:57 +08:00
buf[pos++] = '%';
buf[pos++] = hex[ (s[i] >> 4) & 0x0f ];
buf[pos++] = hex[ s[i] & 0x0f ];
2001-09-25 02:30:57 +08:00
} else {
buf[pos++] = s[i];
}
}
2001-10-26 10:01:42 +08:00
buf[pos] = '\0';
2001-09-25 02:30:57 +08:00
return pos;
}
static int
hex_escape_len_list( char **s, unsigned flags )
2001-09-25 02:30:57 +08:00
{
int len;
int i;
if ( s == NULL ) {
return 0;
}
len = 0;
for ( i = 0; s[i] != NULL; i++ ) {
if ( len ) {
len++;
}
len += hex_escape_len( s[i], flags );
}
return len;
}
static int
hex_escape_list( char *buf, int len, char **s, unsigned flags )
{
int pos;
int i;
2001-09-25 02:30:57 +08:00
if ( s == NULL ) {
return 0;
}
2001-09-25 02:30:57 +08:00
pos = 0;
for ( i = 0; s[i] != NULL; i++ ) {
int curlen;
if ( pos ) {
2001-09-25 02:30:57 +08:00
buf[pos++] = ',';
len--;
2001-09-25 02:30:57 +08:00
}
curlen = hex_escape( &buf[pos], len, s[i], flags );
len -= curlen;
pos += curlen;
2001-09-25 02:30:57 +08:00
}
return pos;
}
static int
desc2str_len( LDAPURLDesc *u )
2001-09-25 02:30:57 +08:00
{
2006-09-06 20:04:33 +08:00
int sep = 0;
int len = 0;
2007-04-03 11:27:24 +08:00
int is_ipc = 0;
2006-09-06 20:04:33 +08:00
struct berval scope;
if ( u == NULL || u->lud_scheme == NULL ) {
return -1;
}
if ( !strcmp( "ldapi", u->lud_scheme )) {
2007-04-03 11:27:24 +08:00
is_ipc = 1;
}
if ( u->lud_exts ) {
len += hex_escape_len_list( u->lud_exts, URLESC_COMMA );
if ( !sep ) {
sep = 5;
2001-09-25 02:30:57 +08:00
}
}
if ( u->lud_filter ) {
2007-06-20 06:59:53 +08:00
len += hex_escape_len( u->lud_filter, URLESC_NONE );
if ( !sep ) {
sep = 4;
}
2001-09-25 02:30:57 +08:00
}
2006-09-06 20:04:33 +08:00
if ( ldap_pvt_scope2bv( u->lud_scope, &scope ) == LDAP_SUCCESS ) {
len += scope.bv_len;
if ( !sep ) {
sep = 3;
}
2001-09-25 02:30:57 +08:00
}
if ( u->lud_attrs ) {
2007-06-20 06:59:53 +08:00
len += hex_escape_len_list( u->lud_attrs, URLESC_NONE );
if ( !sep ) {
sep = 2;
2001-09-25 02:30:57 +08:00
}
}
2001-09-25 02:30:57 +08:00
if ( u->lud_dn && u->lud_dn[0] ) {
len += hex_escape_len( u->lud_dn, URLESC_NONE );
if ( !sep ) {
sep = 1;
}
2001-09-25 02:30:57 +08:00
};
len += sep;
if ( u->lud_port ) {
char buf[ STRLENOF(":65535") + 1 ];
len += snprintf( buf, sizeof( buf ), ":%d", u->lud_port );
if ( u->lud_host && u->lud_host[0] ) {
len += strlen( u->lud_host );
}
} else {
if ( u->lud_host && u->lud_host[0] ) {
len += hex_escape_len( u->lud_host, URLESC_SLASH );
2007-04-03 11:27:24 +08:00
if ( !is_ipc && strchr( u->lud_host, ':' )) {
len += 2; /* IPv6, [] */
}
}
}
len += strlen( u->lud_scheme ) + STRLENOF( "://" );
return len;
}
2007-04-03 11:27:24 +08:00
static int
desc2str( LDAPURLDesc *u, char *s, int len )
{
2006-09-06 20:04:33 +08:00
int i;
int sep = 0;
int sofar = 0;
2007-04-03 11:27:24 +08:00
int is_v6 = 0;
int is_ipc = 0;
2006-09-06 20:04:33 +08:00
struct berval scope = BER_BVNULL;
if ( u == NULL ) {
return -1;
2001-09-25 02:30:57 +08:00
}
if ( s == NULL ) {
return -1;
2001-09-25 02:30:57 +08:00
}
2007-04-03 11:27:24 +08:00
if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) {
is_ipc = 1;
}
2006-09-06 20:04:33 +08:00
ldap_pvt_scope2bv( u->lud_scope, &scope );
2001-09-25 02:30:57 +08:00
if ( u->lud_exts ) {
sep = 5;
} else if ( u->lud_filter ) {
sep = 4;
2006-09-06 20:04:33 +08:00
} else if ( !BER_BVISEMPTY( &scope ) ) {
sep = 3;
} else if ( u->lud_attrs ) {
sep = 2;
} else if ( u->lud_dn && u->lud_dn[0] ) {
sep = 1;
}
2001-09-25 02:30:57 +08:00
2007-04-03 11:27:24 +08:00
if ( !is_ipc && u->lud_host && strchr( u->lud_host, ':' )) {
is_v6 = 1;
}
if ( u->lud_port ) {
2007-04-03 11:27:24 +08:00
len -= sprintf( s, "%s://%s%s%s:%d%n", u->lud_scheme,
is_v6 ? "[" : "",
u->lud_host ? u->lud_host : "",
2007-04-03 11:27:24 +08:00
is_v6 ? "]" : "",
u->lud_port, &sofar );
2001-09-25 02:30:57 +08:00
} else {
len -= sprintf( s, "%s://%n", u->lud_scheme, &sofar );
if ( u->lud_host && u->lud_host[0] ) {
2007-04-03 11:27:24 +08:00
if ( is_v6 ) {
s[sofar++] = '[';
len--;
}
i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH );
sofar += i;
len -= i;
2007-04-03 11:27:24 +08:00
if ( is_v6 ) {
s[sofar++] = ']';
len--;
}
}
2001-09-25 02:30:57 +08:00
}
assert( len >= 0 );
if ( sep < 1 ) {
goto done;
}
2001-09-25 02:30:57 +08:00
s[sofar++] = '/';
len--;
assert( len >= 0 );
2001-09-25 02:30:57 +08:00
if ( u->lud_dn && u->lud_dn[0] ) {
i = hex_escape( &s[sofar], len, u->lud_dn, URLESC_NONE );
sofar += i;
len -= i;
2001-09-25 02:30:57 +08:00
assert( len >= 0 );
}
if ( sep < 2 ) {
goto done;
}
2001-09-25 02:30:57 +08:00
s[sofar++] = '?';
len--;
2001-09-25 02:30:57 +08:00
assert( len >= 0 );
2001-09-25 02:30:57 +08:00
i = hex_escape_list( &s[sofar], len, u->lud_attrs, URLESC_NONE );
sofar += i;
len -= i;
assert( len >= 0 );
if ( sep < 3 ) {
goto done;
}
2001-09-25 02:30:57 +08:00
s[sofar++] = '?';
len--;
2001-09-25 02:30:57 +08:00
assert( len >= 0 );
2006-09-06 20:04:33 +08:00
if ( !BER_BVISNULL( &scope ) ) {
strcpy( &s[sofar], scope.bv_val );
sofar += scope.bv_len;
len -= scope.bv_len;
2001-09-25 02:30:57 +08:00
}
assert( len >= 0 );
if ( sep < 4 ) {
goto done;
}
2001-09-25 02:30:57 +08:00
s[sofar++] = '?';
len--;
assert( len >= 0 );
2001-09-25 02:30:57 +08:00
i = hex_escape( &s[sofar], len, u->lud_filter, URLESC_NONE );
sofar += i;
len -= i;
2001-09-25 02:30:57 +08:00
assert( len >= 0 );
if ( sep < 5 ) {
goto done;
}
2001-09-25 02:30:57 +08:00
s[sofar++] = '?';
len--;
assert( len >= 0 );
i = hex_escape_list( &s[sofar], len, u->lud_exts, URLESC_COMMA );
sofar += i;
len -= i;
2001-09-25 02:30:57 +08:00
assert( len >= 0 );
2001-09-25 02:30:57 +08:00
done:
if ( len < 0 ) {
return -1;
}
return sofar;
}
char *
ldap_url_desc2str( LDAPURLDesc *u )
{
int len;
char *s;
if ( u == NULL ) {
return NULL;
}
len = desc2str_len( u );
if ( len < 0 ) {
return NULL;
}
/* allocate enough to hex escape everything -- overkill */
s = LDAP_MALLOC( len + 1 );
if ( s == NULL ) {
return NULL;
}
if ( desc2str( u, s, len ) != len ) {
LDAP_FREE( s );
return NULL;
}
s[len] = '\0';
2001-09-25 02:30:57 +08:00
return s;
}
1998-08-09 08:43:13 +08:00
int
ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags )
1998-08-09 08:43:13 +08:00
{
/*
* Pick apart the pieces of an LDAP URL.
*/
LDAPURLDesc *ludp;
char *p, *q, *r;
2007-04-03 11:27:24 +08:00
int i, enclosed, proto, is_v6 = 0;
const char *scheme = NULL;
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
const char *url_tmp;
char *url;
1998-08-09 08:43:13 +08:00
int check_dn = 1;
2001-04-13 07:05:19 +08:00
if( url_in == NULL || ludpp == NULL ) {
1999-07-20 03:32:47 +08:00
return LDAP_URL_ERR_PARAM;
}
#ifndef LDAP_INT_IN_KERNEL
2000-06-13 13:50:23 +08:00
/* Global options may not be created yet
* We can't test if the global options are initialized
* because a call to LDAP_INT_GLOBAL_OPT() will try to allocate
* the options and cause infinite recursion
*/
Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 );
#endif
1998-08-09 08:43:13 +08:00
*ludpp = NULL; /* pessimistic */
url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
if ( url_tmp == NULL ) {
return LDAP_URL_ERR_BADSCHEME;
1998-08-09 08:43:13 +08:00
}
assert( scheme != NULL );
2007-04-03 11:27:24 +08:00
proto = ldap_pvt_url_scheme2proto( scheme );
if ( proto == -1 ) {
return LDAP_URL_ERR_BADSCHEME;
}
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
/* make working copy of the remainder of the URL */
2000-06-13 13:50:23 +08:00
url = LDAP_STRDUP( url_tmp );
if ( url == NULL ) {
return LDAP_URL_ERR_MEM;
1998-08-09 08:43:13 +08:00
}
1999-07-20 03:32:47 +08:00
if ( enclosed ) {
p = &url[strlen(url)-1];
1998-08-09 08:43:13 +08:00
1999-07-20 03:32:47 +08:00
if( *p != '>' ) {
LDAP_FREE( url );
return LDAP_URL_ERR_BADENCLOSURE;
}
Vienna Bulk Commit This commit includes many changes. All changes compile under NT but have not been tested under UNIX. A Summary of changes (likely incomplete): NT changes: Removed lint. Clean up configuration support for "Debug", "Release", "SDebug", and "SRelease" configurations. Share output directories for clients, libraries, and slapd. (maybe they should be combined further and moved to build/{,S}{Debug,Release}). Enable threading when _MT is defined. Enable debuging when _DEBUG is defined. Disable setting of NDEBUG under Release/SRelease. Asserts are disabled in <ac/assert.h> when LDAP_DEBUG is not defined. Added 'build/main.dsp' Master project. Removed non-slapd projects from slapd.dsp (see main.dsp). Removed replaced many uses of _WIN32 macro with feature based macros. ldap_cdefs.h changes #define LDAP_CONST const (see below) #define LDAP_F(type) LDAP_F_PRE type LDAP_F_POST To allow specifiers to be added before and after the type declaration. (For DLL handling) LBER/LDAP changes Namespace changes: s/lber_/ber_/ for here and there. s/NAME_ERROR/LDAP_NAME_ERROR/g Deleted NULLMSG and other NULL* macros for namespace reasons. "const" libraries. Installed headers (ie: lber.h, ldap.h) use LDAP_CONST macro. Normally set to 'const' when __STDC__. Can be set externally to enable/disable 'constification' of external interface. Internal interface always uses 'const'. Did not fix warnings in -lldif (in lieu of new LDIF parser). Added _ext API implementations (excepting search and bind). Need to implement ldap_int_get_controls() for reponses with controls. Added numberous assert() checks. LDAP_R _MT defines HAVE_NT_THREADS Added numberous assert() checks. Changed ldap_pthread_t back to unsigned long. Used cast to HANDLE in _join(). LDBM Replaced _WIN32 with HAVE_SYSLOG ud Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). slapd Made connection sockbuf field a pointer to a sockbuf. This removed slap.h dependency on lber-int.h. lber-int.h now only included by those files needing to mess with the sockbuf. Used ber_* functions/macros to access sockbuf internals whenever possible. Added version string if MKVERSION is not defined. (MKVERSION needs to be set under UNIX). Removed FD_SET unsigned lint slapd/tools Used EXEEXT to added ".exe" to routines. Need to define EXEEXT under UNIX. ldappasswd Added ldappasswd.dsp. Ported to NT. Used getpid() to seed rand(). nt_debug Minor cleanup. Added "portable.h" include and used <ac/*.h> where appropriate. Added const to char* format argument.
1999-05-19 09:12:33 +08:00
1998-08-09 08:43:13 +08:00
*p = '\0';
}
1999-07-20 03:32:47 +08:00
/* allocate return struct */
ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc ));
if ( ludp == NULL ) {
LDAP_FREE( url );
return LDAP_URL_ERR_MEM;
}
ludp->lud_next = NULL;
1999-07-20 03:32:47 +08:00
ludp->lud_host = NULL;
2001-09-25 02:30:57 +08:00
ludp->lud_port = 0;
ludp->lud_dn = NULL;
ludp->lud_attrs = NULL;
ludp->lud_scope = ( flags & LDAP_PVT_URL_PARSE_NODEF_SCOPE ) ? LDAP_SCOPE_BASE : LDAP_SCOPE_DEFAULT;
ludp->lud_filter = NULL;
ludp->lud_exts = NULL;
1999-07-24 06:02:57 +08:00
ludp->lud_scheme = LDAP_STRDUP( scheme );
1998-08-09 08:43:13 +08:00
if ( ludp->lud_scheme == NULL ) {
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
}
1998-08-09 08:43:13 +08:00
/* scan forward for '/' that marks end of hostport and begin. of dn */
1999-07-20 03:32:47 +08:00
p = strchr( url, '/' );
2007-04-03 11:27:24 +08:00
q = NULL;
1999-07-20 03:32:47 +08:00
if( p != NULL ) {
/* terminate hostport; point to start of dn */
*p++ = '\0';
2007-04-03 11:27:24 +08:00
} else {
/* check for Novell kludge, see below */
p = strchr( url, '?' );
if ( p ) {
*p++ = '\0';
q = p;
p = NULL;
}
1998-08-09 08:43:13 +08:00
}
2007-04-03 11:27:24 +08:00
if ( proto != LDAP_PROTO_IPC ) {
/* IPv6 syntax with [ip address]:port */
if ( *url == '[' ) {
r = strchr( url, ']' );
if ( r == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADURL;
}
*r++ = '\0';
q = strchr( r, ':' );
if ( q && q != r ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADURL;
}
is_v6 = 1;
} else {
q = strchr( url, ':' );
}
2000-06-13 13:50:23 +08:00
2007-04-03 11:27:24 +08:00
if ( q != NULL ) {
char *next;
2004-06-18 16:36:30 +08:00
2007-04-03 11:27:24 +08:00
*q++ = '\0';
ldap_pvt_hex_unescape( q );
1998-08-09 08:43:13 +08:00
2007-04-03 11:27:24 +08:00
if( *q == '\0' ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADURL;
}
1999-07-20 03:32:47 +08:00
2007-04-03 11:27:24 +08:00
ludp->lud_port = strtol( q, &next, 10 );
if ( next == q || next[0] != '\0' ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADURL;
}
/* check for Novell kludge */
if ( !p ) {
if ( *next != '\0' ) {
q = &next[1];
} else {
q = NULL;
}
2007-04-03 11:27:24 +08:00
}
2004-06-18 16:36:30 +08:00
}
1998-08-09 08:43:13 +08:00
2007-04-03 11:27:24 +08:00
if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) {
if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
ludp->lud_port = LDAPS_PORT;
} else {
ludp->lud_port = LDAP_PORT;
}
}
}
ldap_pvt_hex_unescape( url );
/* If [ip address]:port syntax, url is [ip and we skip the [ */
2007-04-03 11:27:24 +08:00
ludp->lud_host = LDAP_STRDUP( url + is_v6 );
1999-07-20 03:32:47 +08:00
if( ludp->lud_host == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
}
if ( ( flags & LDAP_PVT_URL_PARSE_NOEMPTY_HOST )
&& ludp->lud_host != NULL
&& *ludp->lud_host == '\0' )
{
LDAP_FREE( ludp->lud_host );
ludp->lud_host = NULL;
}
/*
* Kludge. ldap://111.222.333.444:389??cn=abc,o=company
*
* On early Novell releases, search references/referrals were returned
* in this format, i.e., the dn was kind of in the scope position,
* but the required slash is missing. The whole thing is illegal syntax,
* but we need to account for it. Fortunately it can't be confused with
* anything real.
*/
2007-04-03 11:27:24 +08:00
if( (p == NULL) && (q != NULL) && (*q == '?') ) {
/* ? immediately followed by question */
2007-04-03 11:27:24 +08:00
q++;
if( *q != '\0' ) {
/* parse dn part */
ldap_pvt_hex_unescape( q );
ludp->lud_dn = LDAP_STRDUP( q );
2007-04-03 11:27:24 +08:00
} else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
ludp->lud_dn = LDAP_STRDUP( "" );
2007-04-03 11:27:24 +08:00
} else {
check_dn = 0;
}
2007-04-03 11:27:24 +08:00
if ( check_dn && ludp->lud_dn == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
}
}
if( p == NULL ) {
LDAP_FREE( url );
*ludpp = ludp;
return LDAP_URL_SUCCESS;
}
1999-07-20 03:32:47 +08:00
/* scan forward for '?' that may marks end of dn */
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate dn part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse dn part */
ldap_pvt_hex_unescape( p );
1999-07-20 03:32:47 +08:00
ludp->lud_dn = LDAP_STRDUP( p );
} else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) {
ludp->lud_dn = LDAP_STRDUP( "" );
} else {
check_dn = 0;
1998-08-09 08:43:13 +08:00
}
if( check_dn && ludp->lud_dn == NULL ) {
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
1998-08-09 08:43:13 +08:00
}
if( q == NULL ) {
/* no more */
LDAP_FREE( url );
*ludpp = ludp;
return LDAP_URL_SUCCESS;
}
1999-07-20 03:32:47 +08:00
/* scan forward for '?' that may marks end of attributes */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate attributes part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse attributes */
ldap_pvt_hex_unescape( p );
1999-07-20 03:32:47 +08:00
ludp->lud_attrs = ldap_str2charray( p, "," );
if( ludp->lud_attrs == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADATTRS;
1998-08-09 08:43:13 +08:00
}
}
if ( q == NULL ) {
/* no more */
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
*ludpp = ludp;
return LDAP_URL_SUCCESS;
}
/* scan forward for '?' that may marks end of scope */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate the scope part */
*q++ = '\0';
1999-07-20 03:32:47 +08:00
}
1999-07-20 03:32:47 +08:00
if( *p != '\0' ) {
/* parse the scope */
ldap_pvt_hex_unescape( p );
2006-09-06 20:04:33 +08:00
ludp->lud_scope = ldap_pvt_str2scope( p );
1999-07-20 03:32:47 +08:00
if( ludp->lud_scope == -1 ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADSCOPE;
1998-08-09 08:43:13 +08:00
}
}
if ( q == NULL ) {
/* no more */
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
*ludpp = ludp;
return LDAP_URL_SUCCESS;
}
/* scan forward for '?' that may marks end of filter */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate the filter part */
*q++ = '\0';
}
1999-07-20 03:32:47 +08:00
if( *p != '\0' ) {
/* parse the filter */
ldap_pvt_hex_unescape( p );
1999-07-20 03:32:47 +08:00
if( ! *p ) {
/* missing filter */
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADFILTER;
}
ludp->lud_filter = LDAP_STRDUP( p );
if( ludp->lud_filter == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_MEM;
}
}
if ( q == NULL ) {
/* no more */
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
*ludpp = ludp;
return LDAP_URL_SUCCESS;
}
/* scan forward for '?' that may marks end of extensions */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* extra '?' */
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADURL;
}
/* parse the extensions */
1999-07-20 03:32:47 +08:00
ludp->lud_exts = ldap_str2charray( p, "," );
if( ludp->lud_exts == NULL ) {
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADEXTS;
1999-07-22 04:44:40 +08:00
}
for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
ldap_pvt_hex_unescape( ludp->lud_exts[i] );
if( *ludp->lud_exts[i] == '!' ) {
/* count the number of critical extensions */
ludp->lud_crit_exts++;
}
1999-07-22 04:44:40 +08:00
}
if( i == 0 ) {
/* must have 1 or more */
1999-07-22 04:44:40 +08:00
LDAP_FREE( url );
ldap_free_urldesc( ludp );
return LDAP_URL_ERR_BADEXTS;
1998-08-09 08:43:13 +08:00
}
/* no more */
1998-08-09 08:43:13 +08:00
*ludpp = ludp;
1999-07-20 03:32:47 +08:00
LDAP_FREE( url );
return LDAP_URL_SUCCESS;
1998-08-09 08:43:13 +08:00
}
int
ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
{
return ldap_url_parse_ext( url_in, ludpp, LDAP_PVT_URL_PARSE_HISTORIC );
}
LDAPURLDesc *
ldap_url_dup ( LDAPURLDesc *ludp )
{
LDAPURLDesc *dest;
if ( ludp == NULL ) {
return NULL;
}
dest = LDAP_MALLOC( sizeof(LDAPURLDesc) );
if (dest == NULL)
return NULL;
*dest = *ludp;
dest->lud_scheme = NULL;
dest->lud_host = NULL;
dest->lud_dn = NULL;
dest->lud_filter = NULL;
dest->lud_attrs = NULL;
dest->lud_exts = NULL;
dest->lud_next = NULL;
if ( ludp->lud_scheme != NULL ) {
dest->lud_scheme = LDAP_STRDUP( ludp->lud_scheme );
if (dest->lud_scheme == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
if ( ludp->lud_host != NULL ) {
dest->lud_host = LDAP_STRDUP( ludp->lud_host );
if (dest->lud_host == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
if ( ludp->lud_dn != NULL ) {
dest->lud_dn = LDAP_STRDUP( ludp->lud_dn );
if (dest->lud_dn == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
if ( ludp->lud_filter != NULL ) {
dest->lud_filter = LDAP_STRDUP( ludp->lud_filter );
if (dest->lud_filter == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
if ( ludp->lud_attrs != NULL ) {
dest->lud_attrs = ldap_charray_dup( ludp->lud_attrs );
if (dest->lud_attrs == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
if ( ludp->lud_exts != NULL ) {
dest->lud_exts = ldap_charray_dup( ludp->lud_exts );
if (dest->lud_exts == NULL) {
ldap_free_urldesc(dest);
return NULL;
}
}
return dest;
}
LDAPURLDesc *
ldap_url_duplist (LDAPURLDesc *ludlist)
{
LDAPURLDesc *dest, *tail, *ludp, *newludp;
dest = NULL;
tail = NULL;
for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) {
newludp = ldap_url_dup(ludp);
if (newludp == NULL) {
ldap_free_urllist(dest);
return NULL;
}
if (tail == NULL)
dest = newludp;
else
tail->lud_next = newludp;
tail = newludp;
}
return dest;
}
static int
ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
{
int i, rc;
LDAPURLDesc *ludp;
char **urls;
assert( ludlist != NULL );
assert( url != NULL );
*ludlist = NULL;
if ( sep == NULL ) {
sep = ", ";
}
urls = ldap_str2charray( url, sep );
if (urls == NULL)
2004-07-24 19:15:13 +08:00
return LDAP_URL_ERR_MEM;
/* count the URLs... */
for (i = 0; urls[i] != NULL; i++) ;
/* ...and put them in the "stack" backward */
while (--i >= 0) {
rc = ldap_url_parse_ext( urls[i], &ludp, flags );
if ( rc != 0 ) {
ldap_charray_free( urls );
ldap_free_urllist( *ludlist );
*ludlist = NULL;
return rc;
}
ludp->lud_next = *ludlist;
*ludlist = ludp;
}
ldap_charray_free( urls );
2004-07-24 19:15:13 +08:00
return LDAP_URL_SUCCESS;
}
int
ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
{
return ldap_url_parselist_int( ludlist, url, ", ", LDAP_PVT_URL_PARSE_HISTORIC );
}
int
ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep, unsigned flags )
{
return ldap_url_parselist_int( ludlist, url, sep, flags );
}
int
2000-09-02 07:03:17 +08:00
ldap_url_parsehosts(
LDAPURLDesc **ludlist,
const char *hosts,
int port )
{
int i;
LDAPURLDesc *ludp;
char **specs, *p;
assert( ludlist != NULL );
2002-06-06 00:39:15 +08:00
assert( hosts != NULL );
*ludlist = NULL;
specs = ldap_str2charray(hosts, ", ");
if (specs == NULL)
return LDAP_NO_MEMORY;
/* count the URLs... */
for (i = 0; specs[i] != NULL; i++) /* EMPTY */;
/* ...and put them in the "stack" backward */
while (--i >= 0) {
ludp = LDAP_CALLOC( 1, sizeof(LDAPURLDesc) );
if (ludp == NULL) {
ldap_charray_free(specs);
ldap_free_urllist(*ludlist);
*ludlist = NULL;
return LDAP_NO_MEMORY;
}
2000-09-02 07:03:17 +08:00
ludp->lud_port = port;
ludp->lud_host = specs[i];
specs[i] = NULL;
p = strchr(ludp->lud_host, ':');
if (p != NULL) {
/* more than one :, IPv6 address */
if ( strchr(p+1, ':') != NULL ) {
/* allow [address] and [address]:port */
if ( *ludp->lud_host == '[' ) {
p = LDAP_STRDUP(ludp->lud_host+1);
/* copied, make sure we free source later */
specs[i] = ludp->lud_host;
ludp->lud_host = p;
p = strchr( ludp->lud_host, ']' );
2006-04-01 04:36:53 +08:00
if ( p == NULL ) {
LDAP_FREE(ludp);
ldap_charray_free(specs);
return LDAP_PARAM_ERROR;
2006-04-01 04:36:53 +08:00
}
*p++ = '\0';
if ( *p != ':' ) {
2006-04-01 04:36:53 +08:00
if ( *p != '\0' ) {
LDAP_FREE(ludp);
ldap_charray_free(specs);
return LDAP_PARAM_ERROR;
2006-04-01 04:36:53 +08:00
}
p = NULL;
}
} else {
p = NULL;
}
}
if (p != NULL) {
2004-06-18 16:36:30 +08:00
char *next;
*p++ = 0;
ldap_pvt_hex_unescape(p);
2004-06-18 16:36:30 +08:00
ludp->lud_port = strtol( p, &next, 10 );
2005-11-24 09:10:05 +08:00
if ( next == p || next[0] != '\0' ) {
2006-04-01 04:36:53 +08:00
LDAP_FREE(ludp);
ldap_charray_free(specs);
2004-06-18 16:36:30 +08:00
return LDAP_PARAM_ERROR;
}
}
}
ldap_pvt_hex_unescape(ludp->lud_host);
ludp->lud_scheme = LDAP_STRDUP("ldap");
ludp->lud_next = *ludlist;
*ludlist = ludp;
}
/* this should be an array of NULLs now */
/* except entries starting with [ */
ldap_charray_free(specs);
return LDAP_SUCCESS;
}
char *
ldap_url_list2hosts (LDAPURLDesc *ludlist)
{
LDAPURLDesc *ludp;
int size;
char *s, *p, buf[32]; /* big enough to hold a long decimal # (overkill) */
if (ludlist == NULL)
return NULL;
/* figure out how big the string is */
size = 1; /* nul-term */
for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) {
size += strlen(ludp->lud_host) + 1; /* host and space */
if (strchr(ludp->lud_host, ':')) /* will add [ ] below */
size += 2;
if (ludp->lud_port != 0)
size += sprintf(buf, ":%d", ludp->lud_port);
}
s = LDAP_MALLOC(size);
if (s == NULL)
return NULL;
p = s;
for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) {
if (strchr(ludp->lud_host, ':')) {
p += sprintf(p, "[%s]", ludp->lud_host);
} else {
strcpy(p, ludp->lud_host);
p += strlen(ludp->lud_host);
}
if (ludp->lud_port != 0)
p += sprintf(p, ":%d", ludp->lud_port);
*p++ = ' ';
}
if (p != s)
p--; /* nuke that extra space */
*p = 0;
return s;
}
char *
ldap_url_list2urls(
LDAPURLDesc *ludlist )
{
LDAPURLDesc *ludp;
int size, sofar;
char *s;
if ( ludlist == NULL ) {
return NULL;
}
/* figure out how big the string is */
for ( size = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) {
int len = desc2str_len( ludp );
if ( len < 0 ) {
return NULL;
}
size += len + 1;
}
s = LDAP_MALLOC( size );
if ( s == NULL ) {
return NULL;
}
for ( sofar = 0, ludp = ludlist; ludp != NULL; ludp = ludp->lud_next ) {
int len;
len = desc2str( ludp, &s[sofar], size );
if ( len < 0 ) {
LDAP_FREE( s );
return NULL;
}
sofar += len;
size -= len;
s[sofar++] = ' ';
size--;
assert( size >= 0 );
}
s[sofar - 1] = '\0';
return s;
}
void
ldap_free_urllist( LDAPURLDesc *ludlist )
{
LDAPURLDesc *ludp, *next;
for (ludp = ludlist; ludp != NULL; ludp = next) {
next = ludp->lud_next;
ldap_free_urldesc(ludp);
}
}
1998-08-09 08:43:13 +08:00
void
ldap_free_urldesc( LDAPURLDesc *ludp )
{
1999-07-20 03:32:47 +08:00
if ( ludp == NULL ) {
return;
}
if ( ludp->lud_scheme != NULL ) {
LDAP_FREE( ludp->lud_scheme );
}
1999-07-20 03:32:47 +08:00
if ( ludp->lud_host != NULL ) {
LDAP_FREE( ludp->lud_host );
1999-07-20 03:32:47 +08:00
}
if ( ludp->lud_dn != NULL ) {
LDAP_FREE( ludp->lud_dn );
1998-08-09 08:43:13 +08:00
}
1999-07-20 03:32:47 +08:00
if ( ludp->lud_filter != NULL ) {
LDAP_FREE( ludp->lud_filter);
}
if ( ludp->lud_attrs != NULL ) {
LDAP_VFREE( ludp->lud_attrs );
}
if ( ludp->lud_exts != NULL ) {
LDAP_VFREE( ludp->lud_exts );
}
LDAP_FREE( ludp );
1998-08-09 08:43:13 +08:00
}
static int
ldap_int_is_hexpair( char *s )
{
int i;
for ( i = 0; i < 2; i++ ) {
if ( s[i] >= '0' && s[i] <= '9' ) {
continue;
}
if ( s[i] >= 'A' && s[i] <= 'F' ) {
continue;
}
if ( s[i] >= 'a' && s[i] <= 'f' ) {
continue;
}
return 0;
}
return 1;
}
static int
ldap_int_unhex( int c )
1998-08-09 08:43:13 +08:00
{
return( c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
: c - 'a' + 10 );
1998-08-09 08:43:13 +08:00
}
void
ldap_pvt_hex_unescape( char *s )
1998-08-09 08:43:13 +08:00
{
/*
* Remove URL hex escapes from s... done in place. The basic concept for
* this routine is borrowed from the WWW library HTUnEscape() routine.
*/
char *p,
*save_s = s;
1998-08-09 08:43:13 +08:00
for ( p = s; *s != '\0'; ++s ) {
if ( *s == '%' ) {
/*
* FIXME: what if '%' is followed
* by non-hexpair chars?
*/
if ( !ldap_int_is_hexpair( s + 1 ) ) {
p = save_s;
break;
}
2002-07-16 10:38:14 +08:00
if ( *++s == '\0' ) {
break;
1998-08-09 08:43:13 +08:00
}
2002-07-16 10:38:14 +08:00
*p = ldap_int_unhex( *s ) << 4;
if ( *++s == '\0' ) {
break;
1998-08-09 08:43:13 +08:00
}
2002-07-16 10:38:14 +08:00
*p++ += ldap_int_unhex( *s );
1998-08-09 08:43:13 +08:00
} else {
*p++ = *s;
}
}
*p = '\0';
}