diff options
Diffstat (limited to 'ldap/servers/plugins/syntaxes')
-rw-r--r-- | ldap/servers/plugins/syntaxes/Makefile | 87 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/bin.c | 201 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/ces.c | 168 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/cis.c | 298 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/debug.c | 20 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/dllmain.c | 133 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/dn.c | 98 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/int.c | 188 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/libsyntax.def | 24 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/phonetic.c | 461 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/sicis.c | 139 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/string.c | 612 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/syntax.h | 42 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/tel.c | 135 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/value.c | 209 |
15 files changed, 2815 insertions, 0 deletions
diff --git a/ldap/servers/plugins/syntaxes/Makefile b/ldap/servers/plugins/syntaxes/Makefile new file mode 100644 index 00000000..edc9bd9c --- /dev/null +++ b/ldap/servers/plugins/syntaxes/Makefile @@ -0,0 +1,87 @@ +# +# BEGIN COPYRIGHT BLOCK +# Copyright 2001 Sun Microsystems, Inc. +# Portions copyright 1999, 2001-2003 Netscape Communications Corporation. +# All rights reserved. +# END COPYRIGHT BLOCK +# +# +# GNU Makefile for Directory Server syntax-plugin.so syntax plugins +# + +LDAP_SRC = ../../.. +MCOM_ROOT = ../../../../.. + +NOSTDCLEAN=true # don't let nsconfig.mk define target clean +NOSTDSTRIP=true # don't let nsconfig.mk define target strip +NSPR20=true # probably should be defined somewhere else (not sure where) + +OBJDEST = $(OBJDIR)/lib/libsyntax +LIBDIR = $(LIB_RELDIR) + +include $(MCOM_ROOT)/ldapserver/nsconfig.mk +include $(LDAP_SRC)/nsldap.mk + +ifeq ($(ARCH), WINNT) +DEF_FILE:=./libsyntax.def +endif + +CFLAGS+=$(SLCFLAGS) + +INCLUDES += -I$(LDAP_SRC)/servers/slapd + +SYNTAX_OBJS= phonetic.o string.o cis.o sicis.o ces.o bin.o tel.o dn.o int.o \ + value.o debug.o + +OBJS = $(addprefix $(OBJDEST)/, $(SYNTAX_OBJS)) + +ifeq ($(ARCH), WINNT) +LIBSYNTAX_DLL_OBJ = $(addprefix $(OBJDEST)/, dllmain.o) +endif + +LIBSYNTAX= $(addprefix $(LIBDIR)/, $(SYNTAX_DLL).$(DLL_SUFFIX)) + +ifeq ($(ARCH), WINNT) +EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAP_LIBUTIL_DEP) +EXTRA_LIBS_DEP += $(LDAPSDK_DEP) +EXTRA_LIBS += $(LIBSLAPD) $(LDAP_SDK_LIBLDAP_DLL) +endif +ifeq ($(ARCH), AIX) +EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAP_LIBUTIL_DEP) +EXTRA_LIBS_DEP += $(LDAPSDK_DEP) +EXTRA_LIBS += $(LIBSLAPD) $(LDAP_SDK_LIBLDAP_DLL) +endif + +ifeq ($(ARCH), WINNT) +DLL_LDFLAGS += -def:"./libsyntax.def" +CFLAGS+= /WX +endif # WINNT + +ifeq ($(ARCH), HPUX) +EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAPSDK_DEP) $(NSPR_DEP) $(SECURITY_DEP) +EXTRA_LIBS += $(DYN_NSHTTPD) $(ADMINUTIL_LINK) $(LDAPLINK) $(SECURITYLINK) $(NSPRLINK) $(ICULINK) +endif + +ifeq ($(ARCH), AIX) +EXTRA_LIBS += $(DLL_EXTRA_LIBS) +LD=ld +endif + +clientSDK: + +all: $(OBJDEST) $(LIBDIR) $(LIBSYNTAX) + +$(LIBSYNTAX): $(OBJS) $(LIBSYNTAX_DLL_OBJ) $(DEF_FILE) + $(LINK_DLL) $(LIBSYNTAX_DLL_OBJ) $(EXTRA_LIBS) + +veryclean: clean + +clean: + $(RM) $(OBJS) +ifeq ($(ARCH), WINNT) + $(RM) $(LIBSYNTAX_DLL_OBJ) +endif + $(RM) $(LIBSYNTAX) + +$(OBJDEST): + $(MKDIR) $(OBJDEST) diff --git a/ldap/servers/plugins/syntaxes/bin.c b/ldap/servers/plugins/syntaxes/bin.c new file mode 100644 index 00000000..da06e55e --- /dev/null +++ b/ldap/servers/plugins/syntaxes/bin.c @@ -0,0 +1,201 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* bin.c - bin syntax routines */ + +/* + * This file actually implements two syntax plugins: OctetString and Binary. + * We treat them identically for now. XXXmcs: check if that is correct. + */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int bin_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int bin_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals, + Slapi_Value ***ivals, int ftype ); +static int bin_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *bval, + Slapi_Value ***ivals, int ftype ); + +/* + * Attribute syntaxes. We treat all of these the same for now, even though + * the specifications (e.g., RFC 2252) impose various constraints on the + * the format for each of these. + * + * Note: the first name is the official one from RFC 2252. + */ +static char *bin_names[] = { "Binary", "bin", BINARY_SYNTAX_OID, 0 }; + +static char *octetstring_names[] = { "OctetString", OCTETSTRING_SYNTAX_OID, 0 }; + +static char *jpeg_names[] = { "JPEG", JPEG_SYNTAX_OID, 0 }; + + +static Slapi_PluginDesc bin_pdesc = { + "bin-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "binary attribute syntax plugin" +}; + +static Slapi_PluginDesc octetstring_pdesc = { + "octetstring-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "octet string attribute syntax plugin" +}; + +static Slapi_PluginDesc jpeg_pdesc = { + "jpeg-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "JPEG attribute syntax plugin" +}; + + +/* + * register_bin_like_plugin(): register all items for a bin-like plugin. + */ +static int +register_bin_like_plugin( Slapi_PBlock *pb, Slapi_PluginDesc *pdescp, + char **names, char *oid ) +{ + int rc; + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)pdescp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) bin_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) bin_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) bin_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) oid ); + + return( rc ); +} + + +int +bin_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> bin_init\n", 0, 0, 0 ); + rc = register_bin_like_plugin( pb, &bin_pdesc, bin_names, + BINARY_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= bin_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +int +octetstring_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> octetstring_init\n", 0, 0, 0 ); + rc = register_bin_like_plugin( pb, &octetstring_pdesc, octetstring_names, + OCTETSTRING_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= octetstring_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +int +jpeg_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> jpeg_init\n", 0, 0, 0 ); + rc = register_bin_like_plugin( pb, &jpeg_pdesc, jpeg_names, + JPEG_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= jpeg_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +static int +bin_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ) +{ + int i; + + for ( i = 0; bvals[i] != NULL; i++ ) { + if ( slapi_value_get_length(bvals[i]) == bvfilter->bv_len && + 0 == memcmp( slapi_value_get_string(bvals[i]), bvfilter->bv_val, bvfilter->bv_len )) + { + if(retVal!=NULL) + { + *retVal= bvals[i]; + } + return( 0 ); + } + } + if(retVal!=NULL) + { + *retVal= NULL; + } + return( -1 ); +} + +static int +bin_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals, + Slapi_Value ***ivals, int ftype ) +{ + int i; + + if ( ftype != LDAP_FILTER_EQUALITY ) { + return( LDAP_PROTOCOL_ERROR ); + } + + for ( i = 0; bvals[i] != NULL; i++ ) { + /* NULL */ + } + (*ivals) = (Slapi_Value **) slapi_ch_malloc(( i + 1 ) * + sizeof(Slapi_Value *) ); + + for ( i = 0; bvals[i] != NULL; i++ ) + { + (*ivals)[i] = slapi_value_dup(bvals[i]); + } + (*ivals)[i] = NULL; + + return( 0 ); +} + +static int +bin_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *bval, + Slapi_Value ***ivals, int ftype ) +{ + Slapi_Value *tmpval=NULL; + size_t len; + + if (( ftype != LDAP_FILTER_EQUALITY ) && + ( ftype != LDAP_FILTER_EQUALITY_FAST)) + { + return( LDAP_PROTOCOL_ERROR ); + } + if(ftype == LDAP_FILTER_EQUALITY_FAST) { + /* With the fast option, we are trying to avoid creating and freeing + * a bunch of structures - we just do one malloc here - see + * ava_candidates in filterentry.c + */ + len=slapi_value_get_length(bval); + tmpval=(*ivals)[0]; + if (len > tmpval->bv.bv_len) { + tmpval->bv.bv_val=(char *)slapi_ch_malloc(len); + } + tmpval->bv.bv_len=len; + memcpy(tmpval->bv.bv_val,slapi_value_get_string(bval),len); + } else { + (*ivals) = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) ); + (*ivals)[0] = slapi_value_dup( bval ); + (*ivals)[1] = NULL; + } + return( 0 ); +} diff --git a/ldap/servers/plugins/syntaxes/ces.c b/ldap/servers/plugins/syntaxes/ces.c new file mode 100644 index 00000000..075da03b --- /dev/null +++ b/ldap/servers/plugins/syntaxes/ces.c @@ -0,0 +1,168 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* ces.c - caseexactstring syntax routines */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int ces_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int ces_filter_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value **bvals ); +static int ces_values2keys( Slapi_PBlock *pb, Slapi_Value **val, + Slapi_Value ***ivals, int ftype ); +static int ces_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int ces_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value ***ivals ); +static int ces_compare(struct berval *v1, struct berval *v2); + +/* the first name is the official one from RFC 2252 */ +static char *ia5_names[] = { "IA5String", "ces", "caseexactstring", + IA5STRING_SYNTAX_OID, 0 }; + +/* the first name is the official one from RFC 2252 */ +static char *uri_names[] = { "URI", "1.3.6.1.4.1.4401.1.1.1",0}; + +static Slapi_PluginDesc ia5_pdesc = { "ces-syntax", PLUGIN_MAGIC_VENDOR_STR, + PRODUCTTEXT, "caseExactString attribute syntax plugin" }; + +static Slapi_PluginDesc uri_pdesc = { "uri-syntax", PLUGIN_MAGIC_VENDOR_STR, + PRODUCTTEXT, "uri attribute syntax plugin" }; + + +/* + * register_ces_like_plugin(): register all items for a cis-like plugin. + */ +static int +register_ces_like_plugin( Slapi_PBlock *pb, Slapi_PluginDesc *pdescp, + char **names, char *oid ) +{ + int rc, flags; + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *) pdescp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) ces_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB, + (void *) ces_filter_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) ces_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) ces_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB, + (void *) ces_assertion2keys_sub ); + flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING; + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS, + (void *) &flags ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) oid ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE, + (void *) ces_compare ); + + return( rc ); +} + +int +ces_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> ces_init\n", 0, 0, 0 ); + + rc = register_ces_like_plugin(pb,&ia5_pdesc,ia5_names,IA5STRING_SYNTAX_OID); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= ces_init %d\n", rc, 0, 0 ); + return( rc ); +} + +int +uri_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> uri_init\n", 0, 0, 0 ); + + rc = register_ces_like_plugin(pb,&uri_pdesc,uri_names, + "1.3.6.1.4.1.4401.1.1.1"); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= uri_init %d\n", rc, 0, 0 ); + return( rc ); +} + +static int +ces_filter_ava( + Slapi_PBlock *pb, + struct berval *bvfilter, + Slapi_Value **bvals, + int ftype, + Slapi_Value **retVal +) +{ + return( string_filter_ava( bvfilter, bvals, SYNTAX_CES, ftype, + retVal) ); +} + +static int +ces_filter_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value **bvals +) +{ + return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CES ) ); +} + +static int +ces_values2keys( + Slapi_PBlock *pb, + Slapi_Value **vals, + Slapi_Value ***ivals, + int ftype +) +{ + return( string_values2keys( pb, vals, ivals, SYNTAX_CES, ftype ) ); +} + +static int +ces_assertion2keys_ava( + Slapi_PBlock *pb, + Slapi_Value *val, + Slapi_Value ***ivals, + int ftype +) +{ + return(string_assertion2keys_ava( pb, val, ivals, SYNTAX_CES, ftype )); +} + +static int +ces_assertion2keys_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value ***ivals +) +{ + return( string_assertion2keys_sub( pb, initial, any, final, ivals, + SYNTAX_CES ) ); +} + +static int ces_compare( + struct berval *v1, + struct berval *v2 +) +{ + return value_cmp(v1,v2,SYNTAX_CES,3 /* Normalise both values */); +} diff --git a/ldap/servers/plugins/syntaxes/cis.c b/ldap/servers/plugins/syntaxes/cis.c new file mode 100644 index 00000000..e2047fbc --- /dev/null +++ b/ldap/servers/plugins/syntaxes/cis.c @@ -0,0 +1,298 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* cis.c - caseignorestring syntax routines */ + +/* + * This file actually implements three syntax plugins: + * DirectoryString + * Boolean + * GeneralizedTime + * + * We treat them identically for now. XXXmcs: we could do some validation on + * Boolean and GeneralizedTime values (someday, maybe). + */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int cis_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int cis_filter_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value **bvals ); +static int cis_values2keys( Slapi_PBlock *pb, Slapi_Value **val, + Slapi_Value ***ivals, int ftype ); +static int cis_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int cis_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value ***ivals ); +static int cis_compare(struct berval *v1, struct berval *v2); + +/* + * Attribute syntaxes. We treat all of these the same for now, even though + * the specifications (e.g., RFC 2252) impose various constraints on the + * the format for each of these. + * + * Note: the first name is the official one from RFC 2252. + */ +static char *dirstring_names[] = { "DirectoryString", "cis", + "caseignorestring", DIRSTRING_SYNTAX_OID, 0 }; + +static char *boolean_names[] = { "Boolean", BOOLEAN_SYNTAX_OID, 0 }; + +static char *time_names[] = { "GeneralizedTime", "time", + GENERALIZEDTIME_SYNTAX_OID, 0 }; + +static char *country_names[] = { "Country String", + COUNTRYSTRING_SYNTAX_OID, 0}; + +static char *postal_names[] = { "Postal Address", + POSTALADDRESS_SYNTAX_OID, 0}; + +static char *oid_names[] = { "OID", + OID_SYNTAX_OID, 0}; + + +/* + TBD (XXX) + + "1.3.6.1.4.1.1466.115.121.1.16 \"DIT Content Rule Description +\" " + "1.3.6.1.4.1.1466.115.121.1.17 \"DIT Structure Rule Descripti +on\" " + "1.3.6.1.4.1.1466.115.121.1.20 \"DSE Type\" " + "1.3.6.1.4.1.1466.115.121.1.30 \"Matching Rule Description\" +" + "1.3.6.1.4.1.1466.115.121.1.31 \"Matching Rule Use Descriptio +n\" " + "1.3.6.1.4.1.1466.115.121.1.35 \"Name Form Description\" " + + "1.3.6.1.4.1.1466.115.121.1.44 \"Printable String\" " + "1.3.6.1.4.1.1466.115.121.1.45 \"Subtree Specification\" " + "1.3.6.1.4.1.1466.115.121.1.54 \"LDAP Syntax Description\" " + "1.3.6.1.4.1.1466.115.121.1.55 \"Modify Rights\" " + "1.3.6.1.4.1.1466.115.121.1.56 \"LDAP Schema Description\" " + "1.3.6.1.4.1.1466.115.121.1.25 \"Guide\" " + "1.3.6.1.4.1.1466.115.121.1.52 \"Telex Number\" " + "1.3.6.1.4.1.1466.115.121.1.51 \"Teletex Terminal Identifier\ +" " + "1.3.6.1.4.1.1466.115.121.1.14 \"Delivery Method\" " + "1.3.6.1.4.1.1466.115.121.1.43 \"Presentation Address\" " + "1.3.6.1.4.1.1466.115.121.1.21 \"Enhanced Guide\" " + "1.3.6.1.4.1.1466.115.121.1.34 \"Name and Optional UID\" " + "1.2.840.113556.1.4.905 \"CaseIgnoreString\" " + "1.3.6.1.1.1.0.0 \"nisNetgroupTripleSyntax\" " + "1.3.6.1.1.1.0.1 \"bootParameterSyntax\" "); + */ + + +static Slapi_PluginDesc dirstring_pdesc = { "directorystring-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "DirectoryString attribute syntax plugin" }; + +static Slapi_PluginDesc boolean_pdesc = { "boolean-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "Boolean attribute syntax plugin" }; + +static Slapi_PluginDesc time_pdesc = { "time-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "GeneralizedTime attribute syntax plugin" }; + +static Slapi_PluginDesc country_pdesc = { "countrystring-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "Country String attribute syntax plugin" }; + +static Slapi_PluginDesc postal_pdesc = { "postaladdress-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "Postal Address attribute syntax plugin" }; + +static Slapi_PluginDesc oid_pdesc = { "oid-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "OID attribute syntax plugin" }; + + +/* + * register_cis_like_plugin(): register all items for a cis-like plugin. + */ +static int +register_cis_like_plugin( Slapi_PBlock *pb, Slapi_PluginDesc *pdescp, + char **names, char *oid ) +{ + int rc, flags; + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *) pdescp ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) cis_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB, + (void *) cis_filter_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) cis_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) cis_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB, + (void *) cis_assertion2keys_sub ); + flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING; + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS, + (void *) &flags ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) oid ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE, + (void *) cis_compare ); + + return( rc ); +} + + +int +cis_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> cis_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &dirstring_pdesc, dirstring_names, + DIRSTRING_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= cis_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +int +boolean_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> boolean_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &boolean_pdesc, boolean_names, + BOOLEAN_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= boolean_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +int +time_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> time_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &time_pdesc, time_names, + GENERALIZEDTIME_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= time_init %d\n", rc, 0, 0 ); + return( rc ); +} + +int +country_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> country_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &country_pdesc, country_names, + COUNTRYSTRING_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= country_init %d\n", rc, 0, 0 ); + return( rc ); +} + +int +postal_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> postal_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &postal_pdesc, postal_names, + POSTALADDRESS_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= postal_init %d\n", rc, 0, 0 ); + return( rc ); +} + + +int +oid_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> oid_init\n", 0, 0, 0 ); + rc = register_cis_like_plugin( pb, &oid_pdesc, oid_names, OID_SYNTAX_OID ); + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= oid_init %d\n", rc, 0, 0 ); + return( rc ); +} + + + +static int +cis_filter_ava( + Slapi_PBlock *pb, + struct berval *bvfilter, + Slapi_Value **bvals, + int ftype, + Slapi_Value **retVal +) +{ + return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS, ftype, + retVal ) ); +} + + +static int +cis_filter_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value **bvals +) +{ + return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) ); +} + +static int +cis_values2keys( + Slapi_PBlock *pb, + Slapi_Value **vals, + Slapi_Value ***ivals, + int ftype +) +{ + return( string_values2keys( pb, vals, ivals, SYNTAX_CIS, ftype ) ); +} + +static int +cis_assertion2keys_ava( + Slapi_PBlock *pb, + Slapi_Value *val, + Slapi_Value ***ivals, + int ftype +) +{ + return(string_assertion2keys_ava( pb, val, ivals, SYNTAX_CIS, ftype )); +} + +static int +cis_assertion2keys_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value ***ivals +) +{ + return( string_assertion2keys_sub( pb, initial, any, final, ivals, + SYNTAX_CIS ) ); +} + +static int cis_compare( + struct berval *v1, + struct berval *v2 +) +{ + return value_cmp(v1,v2,SYNTAX_CIS,3 /* Normalise both values */); +} diff --git a/ldap/servers/plugins/syntaxes/debug.c b/ldap/servers/plugins/syntaxes/debug.c new file mode 100644 index 00000000..e4d69202 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/debug.c @@ -0,0 +1,20 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* debug.c - syntax debug stuff */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +#ifdef _WIN32 +int *module_ldap_debug = 0; + +void plugin_init_debug_level(int *level_ptr) +{ + module_ldap_debug = level_ptr; +} +#endif diff --git a/ldap/servers/plugins/syntaxes/dllmain.c b/ldap/servers/plugins/syntaxes/dllmain.c new file mode 100644 index 00000000..1f7aa331 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/dllmain.c @@ -0,0 +1,133 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* + * Microsoft Windows specifics for syntax-plugin DLL + */ +#include "ldap.h" +#include "syntax.h" + + +#ifdef _WIN32 +/* Lifted from Q125688 + * How to Port a 16-bit DLL to a Win32 DLL + * on the MSVC 4.0 CD + */ +BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) +{ + WSADATA wsadata; + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + /* Code from LibMain inserted here. Return TRUE to keep the + DLL loaded or return FALSE to fail loading the DLL. + + You may have to modify the code in your original LibMain to + account for the fact that it may be called more than once. + You will get one DLL_PROCESS_ATTACH for each process that + loads the DLL. This is different from LibMain which gets + called only once when the DLL is loaded. The only time this + is critical is when you are using shared data sections. + If you are using shared data sections for statically + allocated data, you will need to be careful to initialize it + only once. Check your code carefully. + + Certain one-time initializations may now need to be done for + each process that attaches. You may also not need code from + your original LibMain because the operating system may now + be doing it for you. + */ + /* + * 16 bit code calls UnlockData() + * which is mapped to UnlockSegment in windows.h + * in 32 bit world UnlockData is not defined anywhere + * UnlockSegment is mapped to GlobalUnfix in winbase.h + * and the docs for both UnlockSegment and GlobalUnfix say + * ".. function is oboslete. Segments have no meaning + * in the 32-bit environment". So we do nothing here. + */ + + if( errno = WSAStartup(0x0101, &wsadata ) != 0 ) + return FALSE; + + break; + + case DLL_THREAD_ATTACH: + /* Called each time a thread is created in a process that has + already loaded (attached to) this DLL. Does not get called + for each thread that exists in the process before it loaded + the DLL. + + Do thread-specific initialization here. + */ + break; + + case DLL_THREAD_DETACH: + /* Same as above, but called when a thread in the process + exits. + + Do thread-specific cleanup here. + */ + break; + + case DLL_PROCESS_DETACH: + /* Code from _WEP inserted here. This code may (like the + LibMain) not be necessary. Check to make certain that the + operating system is not doing it for you. + */ + WSACleanup(); + + break; + } + /* The return value is only used for DLL_PROCESS_ATTACH; all other + conditions are ignored. */ + return TRUE; // successful DLL_PROCESS_ATTACH +} +#else +int CALLBACK +LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) +{ + /*UnlockData( 0 );*/ + return( 1 ); +} +#endif + +#ifdef LDAP_DEBUG +#ifndef _WIN32 +#include <stdarg.h> +#include <stdio.h> + +void LDAPDebug( int level, char* fmt, ... ) +{ + static char debugBuf[1024]; + + if (module_ldap_debug && (*module_ldap_debug & level)) + { + va_list ap; + va_start (ap, fmt); + _snprintf (debugBuf, sizeof(debugBuf), fmt, ap); + va_end (ap); + + OutputDebugString (debugBuf); + } +} +#endif +#endif + +#ifndef _WIN32 + +/* The 16-bit version of the RTL does not implement perror() */ + +#include <stdio.h> + +void perror( const char *msg ) +{ + char buf[128]; + wsprintf( buf, "%s: error %d\n", msg, WSAGetLastError()) ; + OutputDebugString( buf ); +} + +#endif diff --git a/ldap/servers/plugins/syntaxes/dn.c b/ldap/servers/plugins/syntaxes/dn.c new file mode 100644 index 00000000..e6a90df0 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/dn.c @@ -0,0 +1,98 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* dn.c - dn syntax routines */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int dn_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int dn_filter_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value **bvals ); +static int dn_values2keys( Slapi_PBlock *pb, Slapi_Value **vals, + Slapi_Value ***ivals, int ftype ); +static int dn_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int dn_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value ***ivals ); + +/* the first name is the official one from RFC 2252 */ +static char *names[] = { "DN", DN_SYNTAX_OID, 0 }; + +static Slapi_PluginDesc pdesc = { "dn-syntax", PLUGIN_MAGIC_VENDOR_STR, + PRODUCTTEXT, "distinguished name attribute syntax plugin" }; + +int +dn_init( Slapi_PBlock *pb ) +{ + int rc; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> dn_init\n", 0, 0, 0 ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) dn_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB, + (void *) dn_filter_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) dn_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) dn_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB, + (void *) dn_assertion2keys_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) DN_SYNTAX_OID ); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= dn_init %d\n", rc, 0, 0 ); + return( rc ); +} + +static int +dn_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ) +{ + return( string_filter_ava( bvfilter, bvals, SYNTAX_CIS | SYNTAX_DN, + ftype, retVal ) ); +} + +static int +dn_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, + Slapi_Value **bvals ) +{ + return( string_filter_sub( pb, initial, any, final, bvals, + SYNTAX_CIS | SYNTAX_DN ) ); +} + +static int +dn_values2keys( Slapi_PBlock *pb, Slapi_Value **vals, Slapi_Value ***ivals, + int ftype ) +{ + return( string_values2keys( pb, vals, ivals, SYNTAX_CIS | SYNTAX_DN, + ftype ) ); +} + +static int +dn_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ) +{ + return( string_assertion2keys_ava( pb, val, ivals, + SYNTAX_CIS | SYNTAX_DN, ftype ) ); +} + +static int +dn_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, + Slapi_Value ***ivals ) +{ + return( string_assertion2keys_sub( pb, initial, any, final, ivals, + SYNTAX_CIS | SYNTAX_DN ) ); +} diff --git a/ldap/servers/plugins/syntaxes/int.c b/ldap/servers/plugins/syntaxes/int.c new file mode 100644 index 00000000..f81167f2 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/int.c @@ -0,0 +1,188 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* int.c - integer syntax routines */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int int_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int int_values2keys( Slapi_PBlock *pb, Slapi_Value **val, + Slapi_Value ***ivals ); +static int int_assertion2keys( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int int_compare(struct berval *v1, struct berval *v2); +static long int_to_canonical( long num ); + +/* the first name is the official one from RFC 2252 */ +static char *names[] = { "INTEGER", "int", INTEGER_SYNTAX_OID, 0 }; + +static Slapi_PluginDesc pdesc = { "int-syntax", PLUGIN_MAGIC_VENDOR_STR, + PRODUCTTEXT, "integer attribute syntax plugin" }; + +int +int_init( Slapi_PBlock *pb ) +{ + int rc, flags; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> int_init\n", 0, 0, 0 ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) int_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) int_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) int_assertion2keys ); + flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING; + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS, + (void *) &flags ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) INTEGER_SYNTAX_OID ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE, + (void *) int_compare ); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= int_init %d\n", rc, 0, 0 ); + return( rc ); +} + +static int +int_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ) +{ + int i, rc; + long flong, elong; + + if ( ftype == LDAP_FILTER_APPROX ) { + return( LDAP_PROTOCOL_ERROR ); + } + if(retVal) { + *retVal=NULL; + } + flong = atol( bvfilter->bv_val ); + for ( i = 0; bvals[i] != NULL; i++ ) { + elong = atol ( slapi_value_get_string(bvals[i]) ); + rc = elong - flong; + switch ( ftype ) { + case LDAP_FILTER_GE: + if ( rc >= 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + return( 0 ); + } + break; + case LDAP_FILTER_LE: + if ( rc <= 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + return( 0 ); + } + break; + case LDAP_FILTER_EQUALITY: + if ( rc == 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + return( 0 ); + } + break; + } + } + + return( -1 ); +} + +static int +int_values2keys( Slapi_PBlock *pb, Slapi_Value **vals, Slapi_Value ***ivals ) +{ + long num; + int i; + + for ( i = 0; vals[i] != NULL; i++ ) { + /* NULL */ + } + + *ivals = (Slapi_Value **) slapi_ch_malloc(( i + 1 ) * sizeof(Slapi_Value *) ); + + for ( i = 0; vals[i] != NULL; i++ ) + { + num = atol( slapi_value_get_string(vals[i]) ); + num = int_to_canonical( num ); + (*ivals)[i] = slapi_value_new(); + slapi_value_set((*ivals)[i],&num,sizeof(long)); + } + (*ivals)[i] = NULL; + + return( 0 ); +} + +static int +int_assertion2keys( Slapi_PBlock *pb, Slapi_Value *val, Slapi_Value ***ivals, int ftype ) +{ + long num; + size_t len; + unsigned char *b; + Slapi_Value *tmpval=NULL; + + num = atol( slapi_value_get_string(val) ); + num = int_to_canonical( num ); + /* similar to string.c to optimize equality path: avoid malloc/free */ + if(ftype == LDAP_FILTER_EQUALITY_FAST) { + len=sizeof(long); + tmpval=(*ivals)[0]; + if ( len > tmpval->bv.bv_len) { + tmpval->bv.bv_val=(char *)slapi_ch_malloc(len); + } + tmpval->bv.bv_len=len; + b = (unsigned char *)# + memcpy(tmpval->bv.bv_val,b,len); + } else { + *ivals = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) ); + (*ivals)[0] = (Slapi_Value *) slapi_ch_malloc( sizeof(Slapi_Value) ); + /* XXXSD initialize memory */ + memset((*ivals)[0],0,sizeof(Slapi_Value)); + slapi_value_set((*ivals)[0],&num,sizeof(long)); + (*ivals)[1] = NULL; + } + return( 0 ); +} + +static int int_compare( + struct berval *v1, + struct berval *v2 +) +{ + long value1 = atol(v1->bv_val); + long value2 = atol(v2->bv_val); + + if (value1 == value2) { + return 0; + } + return ( ((value1 - value2) > 0) ? 1 : -1); +} + +static long +int_to_canonical( long num ) +{ + long ret = 0L; + unsigned char *b = (unsigned char *)&ret; + + b[0] = (unsigned char)(num >> 24); + b[1] = (unsigned char)(num >> 16); + b[2] = (unsigned char)(num >> 8); + b[3] = (unsigned char)num; + + return ret; +} diff --git a/ldap/servers/plugins/syntaxes/libsyntax.def b/ldap/servers/plugins/syntaxes/libsyntax.def new file mode 100644 index 00000000..30cb6b40 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/libsyntax.def @@ -0,0 +1,24 @@ +; BEGIN COPYRIGHT BLOCK +; Copyright 2001 Sun Microsystems, Inc. +; Portions copyright 1999, 2001-2003 Netscape Communications Corporation. +; All rights reserved. +; END COPYRIGHT BLOCK +; +DESCRIPTION 'Directory Server 7 syntaxes Plugin' +EXPORTS + cis_init @2 + ces_init @3 + tel_init @4 + dn_init @5 + bin_init @6 + int_init @7 + plugin_init_debug_level @8 + octetstring_init @9 + boolean_init @10 + time_init @11 + uri_init @12 + country_init @13 + postal_init @14 + jpeg_init @15 + oid_init @16 + sicis_init @17 diff --git a/ldap/servers/plugins/syntaxes/phonetic.c b/ldap/servers/plugins/syntaxes/phonetic.c new file mode 100644 index 00000000..1c1c8ba5 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/phonetic.c @@ -0,0 +1,461 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* phonetic.c - routines to do phonetic matching */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> +#include "syntax.h" +#include "portable.h" + +#if !defined(METAPHONE) && !defined(SOUNDEX) +#define METAPHONE +#endif + +#define iswordbreak(s) \ +(isascii(*(s)) \ +? (isspace(*(s)) || \ + ispunct(*(s)) || \ + isdigit(*(s)) || \ + *(s) == '\0') \ +: utf8iswordbreak(s)) + +static int +utf8iswordbreak( const char* s ) +{ + switch( LDAP_UTF8GETCC( s )) { + case 0x00A0: /* non-breaking space */ + case 0x3000: /* ideographic space */ + case 0xFEFF: /* zero-width non-breaking space */ + return 1; + default: break; + } + return 0; +} + +char * +first_word( char *s ) +{ + if ( s == NULL ) { + return( NULL ); + } + + while ( iswordbreak( s ) ) { + if ( *s == '\0' ) { + return( NULL ); + } else { + LDAP_UTF8INC( s ); + } + } + + return( s ); +} + +char * +next_word( char *s ) +{ + if ( s == NULL ) { + return( NULL ); + } + + while ( ! iswordbreak( s ) ) { + LDAP_UTF8INC( s ); + } + + while ( iswordbreak( s ) ) { + if ( *s == '\0' ) { + return( NULL ); + } else { + LDAP_UTF8INC( s ); + } + } + + return( s ); +} + +char * +word_dup( char *w ) +{ + char *s, *ret; + char save; + + for ( s = w; !iswordbreak( s ); LDAP_UTF8INC( s )) + ; /* NULL */ + save = *s; + *s = '\0'; + ret = slapi_ch_strdup( w ); + *s = save; + + return( ret ); +} + +#ifndef MAXPHONEMELEN +#define MAXPHONEMELEN 4 +#endif + +#if defined(SOUNDEX) + +/* lifted from isode-8.0 */ +char * +phonetic( char *s ) +{ + char code, adjacent, ch; + char *p; + char **c; + int i, cmax; + char phoneme[MAXPHONEMELEN + 1]; + + p = s; + if ( p == NULL || *p == '\0' ) { + return( NULL ); + } + + adjacent = '0'; + phoneme[0] = TOUPPER(*p); + + phoneme[1] = '\0'; + for ( i = 0; i < 99 && (! iswordbreak(p)); LDAP_UTF8INC( p )) { + ch = TOUPPER (*p); + + code = '0'; + + switch (ch) { + case 'B': + case 'F': + case 'P': + case 'V': + code = (adjacent != '1') ? '1' : '0'; + break; + case 'S': + case 'C': + case 'G': + case 'J': + case 'K': + case 'Q': + case 'X': + case 'Z': + code = (adjacent != '2') ? '2' : '0'; + break; + case 'D': + case 'T': + code = (adjacent != '3') ? '3' : '0'; + break; + case 'L': + code = (adjacent != '4') ? '4' : '0'; + break; + case 'M': + case 'N': + code = (adjacent != '5') ? '5' : '0'; + break; + case 'R': + code = (adjacent != '6') ? '6' : '0'; + break; + default: + adjacent = '0'; + } + + if ( i == 0 ) { + adjacent = code; + i++; + } else if ( code != '0' ) { + if ( i == MAXPHONEMELEN ) + break; + adjacent = phoneme[i] = code; + i++; + } + } + + if ( i > 0 ) + phoneme[i] = '\0'; + + return( slapi_ch_strdup( phoneme ) ); +} + +#else +#if defined(METAPHONE) + +/* + * Metaphone copied from C Gazette, June/July 1991, pp 56-57, + * author Gary A. Parker, with changes by Bernard Tiffany of the + * University of Michigan, and more changes by Tim Howes of the + * University of Michigan. + */ + +/* Character coding array */ +static char vsvfn[26] = { + 1, 16, 4, 16, 9, 2, 4, 16, 9, 2, 0, 2, 2, + /* A B C D E F G H I J K L M */ + 2, 1, 4, 0, 2, 4, 4, 1, 0, 0, 0, 8, 0}; + /* N O P Q R S T U V W X Y Z */ + +/* Macros to access character coding array */ +#define vowel(x) ((x) != '\0' && vsvfn[(x) - 'A'] & 1) /* AEIOU */ +#define same(x) ((x) != '\0' && vsvfn[(x) - 'A'] & 2) /* FJLMNR */ +#define varson(x) ((x) != '\0' && vsvfn[(x) - 'A'] & 4) /* CGPST */ +#define frontv(x) ((x) != '\0' && vsvfn[(x) - 'A'] & 8) /* EIY */ +#define noghf(x) ((x) != '\0' && vsvfn[(x) - 'A'] & 16) /* BDH */ + +char * +phonetic( char *Word ) +{ + char *n, *n_start, *n_end; /* pointers to string */ + char *metaph_end; /* pointers to metaph */ + char ntrans[42]; /* word with uppercase letters */ + int KSflag; /* state flag for X -> KS */ + char buf[MAXPHONEMELEN + 2]; + char *Metaph; + + /* + * Copy Word to internal buffer, dropping non-alphabetic characters + * and converting to upper case + */ + n = ntrans + 4; n_end = ntrans + 35; + while (!iswordbreak( Word ) && n < n_end) { + if (isascii(*Word)) { + if (isalpha(*Word)) { + *n++ = TOUPPER(*Word); + } + ++Word; + } else { + auto const size_t len = LDAP_UTF8COPY(n, Word); + n += len; Word += len; + } + } + Metaph = buf; + *Metaph = '\0'; + if (n == ntrans + 4) { + return( slapi_ch_strdup( buf ) ); /* Return if null */ + } + n_end = n; /* Set n_end to end of string */ + + /* ntrans[0] will always be == 0 */ + ntrans[0] = '\0'; + ntrans[1] = '\0'; + ntrans[2] = '\0'; + ntrans[3] = '\0'; + *n++ = 0; + *n++ = 0; + *n++ = 0; + *n = 0; /* Pad with nulls */ + n = ntrans + 4; /* Assign pointer to start */ + + /* Check for PN, KN, GN, AE, WR, WH, and X at start */ + switch (*n) { + case 'P': + case 'K': + case 'G': + /* 'PN', 'KN', 'GN' becomes 'N' */ + if (*(n + 1) == 'N') + *n++ = 0; + break; + case 'A': + /* 'AE' becomes 'E' */ + if (*(n + 1) == 'E') + *n++ = 0; + break; + case 'W': + /* 'WR' becomes 'R', and 'WH' to 'H' */ + if (*(n + 1) == 'R') + *n++ = 0; + else if (*(n + 1) == 'H') { + *(n + 1) = *n; + *n++ = 0; + } + break; + case 'X': + /* 'X' becomes 'S' */ + *n = 'S'; + break; + } + + /* + * Now, loop step through string, stopping at end of string or when + * the computed 'metaph' is MAXPHONEMELEN characters long + */ + + KSflag = 0; /* state flag for KS translation */ + for (metaph_end = Metaph + MAXPHONEMELEN, n_start = n; + n <= n_end && Metaph < metaph_end; n++) { + if (KSflag) { + KSflag = 0; + *Metaph++ = 'S'; + } else if (!isascii(*n)) { + *Metaph++ = *n; + } else { + /* Drop duplicates except for CC */ + if (*(n - 1) == *n && *n != 'C') + continue; + /* Check for F J L M N R or first letter vowel */ + if (same(*n) || (n == n_start && vowel(*n))) { + *Metaph++ = *n; + } else { + switch (*n) { + case 'B': + + /* + * B unless in -MB + */ + if (n < (n_end - 1) && *(n - 1) != 'M') { + *Metaph++ = *n; + } + break; + case 'C': + + /* + * X if in -CIA-, -CH- else S if in + * -CI-, -CE-, -CY- else dropped if + * in -SCI-, -SCE-, -SCY- else K + */ + if (*(n - 1) != 'S' || !frontv(*(n + 1))) { + if (*(n + 1) == 'I' && *(n + 2) == 'A') { + *Metaph++ = 'X'; + } else if (frontv(*(n + 1))) { + *Metaph++ = 'S'; + } else if (*(n + 1) == 'H') { + *Metaph++ = ((n == n_start && !vowel(*(n + 2))) + || *(n - 1) == 'S') + ? (char) 'K' : (char) 'X'; + } else { + *Metaph++ = 'K'; + } + } + break; + case 'D': + + /* + * J if in DGE or DGI or DGY else T + */ + *Metaph++ = (*(n + 1) == 'G' && frontv(*(n + 2))) + ? (char) 'J' : (char) 'T'; + break; + case 'G': + + /* + * F if in -GH and not B--GH, D--GH, + * -H--GH, -H---GH else dropped if + * -GNED, -GN, -DGE-, -DGI-, -DGY- + * else J if in -GE-, -GI-, -GY- and + * not GG else K + */ + if ((*(n + 1) != 'J' || vowel(*(n + 2))) && + (*(n + 1) != 'N' || ((n + 1) < n_end && + (*(n + 2) != 'E' || *(n + 3) != 'D'))) && + (*(n - 1) != 'D' || !frontv(*(n + 1)))) + *Metaph++ = (frontv(*(n + 1)) && + *(n + 2) != 'G') ? (char) 'G' : (char) 'K'; + else if (*(n + 1) == 'H' && !noghf(*(n - 3)) && + *(n - 4) != 'H') + *Metaph++ = 'F'; + break; + case 'H': + + /* + * H if before a vowel and not after + * C, G, P, S, T else dropped + */ + if (!varson(*(n - 1)) && (!vowel(*(n - 1)) || + vowel(*(n + 1)))) + *Metaph++ = 'H'; + break; + case 'K': + + /* + * dropped if after C else K + */ + if (*(n - 1) != 'C') + *Metaph++ = 'K'; + break; + case 'P': + + /* + * F if before H, else P + */ + *Metaph++ = *(n + 1) == 'H' ? + (char) 'F' : (char) 'P'; + break; + case 'Q': + + /* + * K + */ + *Metaph++ = 'K'; + break; + case 'S': + + /* + * X in -SH-, -SIO- or -SIA- else S + */ + *Metaph++ = (*(n + 1) == 'H' || + (*(n + 1) == 'I' && (*(n + 2) == 'O' || + *(n + 2) == 'A'))) + ? (char) 'X' : (char) 'S'; + break; + case 'T': + + /* + * X in -TIA- or -TIO- else 0 (zero) + * before H else dropped if in -TCH- + * else T + */ + if (*(n + 1) == 'I' && (*(n + 2) == 'O' || + *(n + 2) == 'A')) + *Metaph++ = 'X'; + else if (*(n + 1) == 'H') + *Metaph++ = '0'; + else if (*(n + 1) != 'C' || *(n + 2) != 'H') + *Metaph++ = 'T'; + break; + case 'V': + + /* + * F + */ + *Metaph++ = 'F'; + break; + case 'W': + + /* + * W after a vowel, else dropped + */ + case 'Y': + + /* + * Y unless followed by a vowel + */ + if (vowel(*(n + 1))) + *Metaph++ = *n; + break; + case 'X': + + /* + * KS + */ + if (n == n_start) + *Metaph++ = 'S'; + else { + *Metaph++ = 'K'; /* Insert K, then S */ + KSflag = 1; + } + break; + case 'Z': + + /* + * S + */ + *Metaph++ = 'S'; + break; + } + } + } + } + + *Metaph = 0; /* Null terminate */ + return( slapi_ch_strdup( buf ) ); +} + +#endif /* METAPHONE */ +#endif /* !SOUNDEX */ diff --git a/ldap/servers/plugins/syntaxes/sicis.c b/ldap/servers/plugins/syntaxes/sicis.c new file mode 100644 index 00000000..4bd6623d --- /dev/null +++ b/ldap/servers/plugins/syntaxes/sicis.c @@ -0,0 +1,139 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2002 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +/* + * sicis.c - space insensitive string syntax routines. + * these strings are also case insensitive. + */ +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int sicis_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int sicis_filter_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value **bvals ); +static int sicis_values2keys( Slapi_PBlock *pb, Slapi_Value **val, + Slapi_Value ***ivals, int ftype ); +static int sicis_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int sicis_assertion2keys_sub( Slapi_PBlock *pb, char *initial, + char **any, char *final, Slapi_Value ***ivals ); +static int sicis_compare(struct berval *v1, struct berval *v2); + +/* the first name is the official one from RFC 2252 */ +static char *names[] = { "SpaceInsensitiveString", + SPACE_INSENSITIVE_STRING_SYNTAX_OID, 0 }; + +static Slapi_PluginDesc pdesc = { "spaceinsensitivestring-syntax", + PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "space insensitive string attribute syntax plugin" }; + +int +sicis_init( Slapi_PBlock *pb ) +{ + int rc, flags; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> sicis_init\n", 0, 0, 0 ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) sicis_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB, + (void *) sicis_filter_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) sicis_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) sicis_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB, + (void *) sicis_assertion2keys_sub ); + flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING; + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS, + (void *) &flags ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) SPACE_INSENSITIVE_STRING_SYNTAX_OID ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE, + (void *) sicis_compare ); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= sicis_init %d\n", rc, 0, 0 ); + return( rc ); +} + +static int +sicis_filter_ava( + Slapi_PBlock *pb, + struct berval *bvfilter, + Slapi_Value **bvals, + int ftype, + Slapi_Value **retVal +) +{ + return( string_filter_ava( bvfilter, bvals, SYNTAX_SI | SYNTAX_CIS, + ftype, retVal ) ); +} + + +static int +sicis_filter_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value **bvals +) +{ + return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_SI | SYNTAX_CIS ) ); +} + +static int +sicis_values2keys( + Slapi_PBlock *pb, + Slapi_Value **vals, + Slapi_Value ***ivals, + int ftype +) +{ + return( string_values2keys( pb, vals, ivals, SYNTAX_SI | SYNTAX_CIS, + ftype ) ); +} + +static int +sicis_assertion2keys_ava( + Slapi_PBlock *pb, + Slapi_Value *val, + Slapi_Value ***ivals, + int ftype +) +{ + return(string_assertion2keys_ava( pb, val, ivals, + SYNTAX_SI | SYNTAX_CIS, ftype )); +} + +static int +sicis_assertion2keys_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value ***ivals +) +{ + return( string_assertion2keys_sub( pb, initial, any, final, ivals, + SYNTAX_SI | SYNTAX_CIS ) ); +} + +static int sicis_compare( + struct berval *v1, + struct berval *v2 +) +{ + return value_cmp(v1, v2, SYNTAX_SI|SYNTAX_CIS, 3 /* Normalise both values */); +} diff --git a/ldap/servers/plugins/syntaxes/string.c b/ldap/servers/plugins/syntaxes/string.c new file mode 100644 index 00000000..d06a15f5 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/string.c @@ -0,0 +1,612 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* string.c - common string syntax routines */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" +#if defined(IRIX) +#include <unistd.h> +#endif +#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX ) +#include "regex.h" +#endif + +static int string_filter_approx( struct berval *bvfilter, + Slapi_Value **bvals, Slapi_Value **retVal ); +static void substring_comp_keys( Slapi_Value ***ivals, int *nsubs, char *str, + int prepost, int syntax ); + +int +string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax, + int ftype, Slapi_Value **retVal ) +{ + int i, rc; + struct berval bvfilter_norm; + + if(retVal) { + *retVal = NULL; + } + if ( ftype == LDAP_FILTER_APPROX ) { + return( string_filter_approx( bvfilter, bvals, retVal ) ); + } + + bvfilter_norm.bv_val = slapi_ch_malloc( bvfilter->bv_len + 1 ); + SAFEMEMCPY( bvfilter_norm.bv_val, bvfilter->bv_val, bvfilter->bv_len ); + bvfilter_norm.bv_val[bvfilter->bv_len] = '\0'; + value_normalize( bvfilter_norm.bv_val, syntax, 1 /* trim leading blanks */ ); + + for ( i = 0; bvals[i] != NULL; i++ ) { + rc = value_cmp( (struct berval*)slapi_value_get_berval(bvals[i]), &bvfilter_norm, syntax, 1/* Normalise the first value only */ ); + switch ( ftype ) { + case LDAP_FILTER_GE: + if ( rc >= 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + slapi_ch_free ((void**)&bvfilter_norm.bv_val); + return( 0 ); + } + break; + case LDAP_FILTER_LE: + if ( rc <= 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + slapi_ch_free ((void**)&bvfilter_norm.bv_val); + return( 0 ); + } + break; + case LDAP_FILTER_EQUALITY: + if ( rc == 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + slapi_ch_free ((void**)&bvfilter_norm.bv_val); + return( 0 ); + } + break; + } + } + + slapi_ch_free ((void**)&bvfilter_norm.bv_val); + return( -1 ); +} + +static int +string_filter_approx( struct berval *bvfilter, Slapi_Value **bvals, + Slapi_Value **retVal) +{ + int i, rc; + int ava_wordcount; + char *w1, *w2, *c1, *c2; + + /* + * try to match words in each filter value in order + * in the attribute value. + * XXX should do this once for the filter and save it XXX + */ + rc = -1; + if(retVal) { + *retVal = NULL; + } + for ( i = 0; bvals[i] != NULL; i++ ) { + w2 = (char*)slapi_value_get_string(bvals[i]); /* JCM cast */ + ava_wordcount = 0; + /* for each word in the filter value */ + for ( w1 = first_word( bvfilter->bv_val ); w1 != NULL; + w1 = next_word( w1 ) ) { + ++ava_wordcount; + if ( (c1 = phonetic( w1 )) == NULL ) { + break; + } + + /* + * for each word in the attribute value from + * where we left off... + */ + for ( w2 = first_word( w2 ); w2 != NULL; + w2 = next_word( w2 ) ) { + c2 = phonetic( w2 ); + rc = strcmp( c1, c2 ); + slapi_ch_free((void**)&c2 ); + if ( rc == 0 ) { + if(retVal) { + *retVal = bvals[i]; + } + break; + } + } + slapi_ch_free((void**)&c1 ); + + /* + * if we stopped because we ran out of words + * before making a match, go on to the next + * value. otherwise try to keep matching + * words in this value from where we left off. + */ + if ( w2 == NULL ) { + break; + } else { + w2 = next_word( w2 ); + } + } + /* + * if we stopped because we ran out of words and + * we found at leasy one word, we have a match. + */ + if ( w1 == NULL && ava_wordcount > 0 ) { + rc = 0; + break; + } + } + LDAPDebug( LDAP_DEBUG_TRACE, "<= string_filter_approx %d\n", + rc, 0, 0 ); + + return( rc ); +} + +int +string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, + Slapi_Value **bvals, int syntax ) +{ + int i, j, rc; + char *p, *end, *realval, *tmpbuf; + size_t tmpbufsize; + char pat[BUFSIZ]; + char buf[BUFSIZ]; + char ebuf[BUFSIZ]; + + LDAPDebug( LDAP_DEBUG_FILTER, "=> string_filter_sub\n", + 0, 0, 0 ); + + /* + * construct a regular expression corresponding to the + * filter and let regex do the work for each value + * XXX should do this once and save it somewhere XXX + */ + pat[0] = '\0'; + p = pat; + end = pat + sizeof(pat) - 2; /* leave room for null */ + if ( initial != NULL ) { + value_normalize( initial, syntax, 1 /* trim leading blanks */ ); + strcpy( p, "^" ); + p = strchr( p, '\0' ); + /* 2 * in case every char is special */ + if ( p + 2 * strlen( initial ) > end ) { + LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n", + 0, 0, 0 ); + return( -1 ); + } + filter_strcpy_special( p, initial ); + p = strchr( p, '\0' ); + } + if ( any != NULL ) { + for ( i = 0; any[i] != NULL; i++ ) { + value_normalize( any[i], syntax, 0 /* DO NOT trim leading blanks */ ); + /* ".*" + value */ + if ( p + 2 * strlen( any[i] ) + 2 > end ) { + LDAPDebug( LDAP_DEBUG_ANY, + "not enough pattern space\n", 0, 0, 0 ); + return( -1 ); + } + strcpy( p, ".*" ); + p = strchr( p, '\0' ); + filter_strcpy_special( p, any[i] ); + p = strchr( p, '\0' ); + } + } + if ( final != NULL ) { + value_normalize( final, syntax, 0 /* DO NOT trim leading blanks */ ); + /* ".*" + value */ + if ( p + 2 * strlen( final ) + 2 > end ) { + LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n", + 0, 0, 0 ); + return( -1 ); + } + strcpy( p, ".*" ); + p = strchr( p, '\0' ); + filter_strcpy_special( p, final ); + p = strchr( p, '\0' ); + strcpy( p, "$" ); + } + + /* compile the regex */ + slapd_re_lock(); + if ( (p = slapd_re_comp( pat )) != 0 ) { + LDAPDebug( LDAP_DEBUG_ANY, "re_comp (%s) failed (%s)\n", + pat, p, 0 ); + slapd_re_unlock(); + return( -1 ); + } else { + LDAPDebug( LDAP_DEBUG_TRACE, "re_comp (%s)\n", + escape_string( pat, ebuf ), 0, 0 ); + } + + /* + * test the regex against each value + */ + rc = -1; + tmpbuf = NULL; + tmpbufsize = 0; + for ( j = 0; bvals[j] != NULL; j++ ) { + int tmprc; + size_t len; + const struct berval *bvp = slapi_value_get_berval(bvals[j]); + + len = bvp->bv_len; + if ( len < sizeof(buf) ) { + strcpy( buf, bvp->bv_val ); + realval = buf; + } else if ( len < tmpbufsize ) { + strcpy( buf, bvp->bv_val ); + realval = tmpbuf; + } else { + tmpbuf = (char *) slapi_ch_realloc( tmpbuf, len + 1 ); + strcpy( tmpbuf, bvp->bv_val ); + realval = tmpbuf; + } + value_normalize( realval, syntax, 1 /* trim leading blanks */ ); + + tmprc = slapd_re_exec( realval ); + + LDAPDebug( LDAP_DEBUG_TRACE, "re_exec (%s) %i\n", + escape_string( realval, ebuf ), tmprc, 0 ); + if ( tmprc != 0 ) { + rc = 0; + break; + } + } + slapd_re_unlock(); + if ( tmpbuf != NULL ) { + slapi_ch_free((void**)&tmpbuf ); + } + + LDAPDebug( LDAP_DEBUG_FILTER, "<= string_filter_sub %d\n", + rc, 0, 0 ); + return( rc ); +} + +int +string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals, + Slapi_Value ***ivals, int syntax, int ftype ) +{ + int nsubs, numbvals, i, n, j; + Slapi_Value **nbvals; + char *w, *c, *p; + char buf[SUBLEN+1]; + + switch ( ftype ) { + case LDAP_FILTER_EQUALITY: + /* allocate a new array for the normalized values */ + for ( numbvals = 0; bvals[numbvals] != NULL; numbvals++ ) { + /* NULL */ + } + nbvals = (Slapi_Value **) slapi_ch_malloc( (numbvals+1) * sizeof(Slapi_Value *)); + + for ( i = 0; i < numbvals; i++ ) + { + c = slapi_ch_strdup(slapi_value_get_string(bvals[i])); + value_normalize( c, syntax, 1 /* trim leading blanks */ ); + nbvals[i] = slapi_value_new_string_passin(c); + } + nbvals[i] = NULL; + *ivals = nbvals; + break; + + case LDAP_FILTER_APPROX: + /* XXX should not do this twice! XXX */ + /* get an upper bound on the number of ivals */ + numbvals = 0; + for ( i = 0; bvals[i] != NULL; i++ ) { + for ( w = first_word( (char*)slapi_value_get_string(bvals[i]) ); w != NULL; + w = next_word( w ) ) { + numbvals++; + } + } + nbvals = (Slapi_Value **) slapi_ch_malloc( (numbvals + 1) * sizeof(Slapi_Value *) ); + + n = 0; + for ( i = 0; bvals[i] != NULL; i++ ) { + for ( w = first_word( (char*)slapi_value_get_string(bvals[i]) ); w != NULL; + w = next_word( w ) ) { + if ( (c = phonetic( w )) != NULL ) { + nbvals[n] = slapi_value_new_string_passin(c); + n++; + } + } + } + nbvals[n] = NULL; + + if ( n == 0 ) { + slapi_ch_free((void**)ivals ); + return( 0 ); + } + *ivals = nbvals; + break; + + case LDAP_FILTER_SUBSTRINGS: + { + /* XXX should remove duplicates! XXX */ + Slapi_Value *bvdup; + const struct berval *bvp; + nsubs = 0; + for ( i = 0; bvals[i] != NULL; i++ ) { + /* + * Note: this calculation may err on the high side, + * because value_normalize(), which is called below + * before we actually create the substring keys, may + * reduce the length of the value in some cases. For + * example, spaces are removed when space insensitive + * strings are normalized. But it's okay for nsubs to + * be too big. Since the ivals array is NULL terminated, + * the only downside is that we allocate more space than + * we really need. + */ + nsubs += slapi_value_get_length(bvals[i]) - SUBLEN + 3; + } + *ivals = (Slapi_Value **) slapi_ch_malloc( (nsubs + 1) * sizeof(Slapi_Value *) ); + + buf[SUBLEN] = '\0'; + n = 0; + + bvdup= slapi_value_new(); + for ( i = 0; bvals[i] != NULL; i++ ) + { + c = slapi_ch_strdup(slapi_value_get_string(bvals[i])); + value_normalize( c, syntax, 1 /* trim leading blanks */ ); + slapi_value_set_string_passin(bvdup, c); + + bvp = slapi_value_get_berval(bvdup); + + /* leading */ + if ( bvp->bv_len > SUBLEN - 2 ) { + buf[0] = '^'; + for ( j = 0; j < SUBLEN - 1; j++ ) { + buf[j + 1] = bvp->bv_val[j]; + } + (*ivals)[n] = slapi_value_new_string(buf); + n++; + } + + /* any */ + for ( p = bvp->bv_val; + p < (bvp->bv_val + bvp->bv_len - SUBLEN + 1); + p++ ) { + for ( j = 0; j < SUBLEN; j++ ) { + buf[j] = p[j]; + } + buf[SUBLEN] = '\0'; + (*ivals)[n] = slapi_value_new_string(buf); + n++; + } + + /* trailing */ + if ( bvp->bv_len > SUBLEN - 2 ) { + p = bvp->bv_val + bvp->bv_len - SUBLEN + 1; + for ( j = 0; j < SUBLEN - 1; j++ ) { + buf[j] = p[j]; + } + buf[SUBLEN - 1] = '$'; + (*ivals)[n] = slapi_value_new_string(buf); + n++; + } + } + slapi_value_free(&bvdup); + (*ivals)[n] = NULL; + } + break; + } + + return( 0 ); +} + + +/* we've added code to make our equality filter processing faster */ + +int +string_assertion2keys_ava( + Slapi_PBlock *pb, + Slapi_Value *val, + Slapi_Value ***ivals, + int syntax, + int ftype +) +{ + int i, numbvals; + size_t len; + char *w, *c; + Slapi_Value *tmpval=NULL; + + switch ( ftype ) { + case LDAP_FILTER_EQUALITY_FAST: + /* this code is trying to avoid multiple malloc/frees */ + len=slapi_value_get_length(val); + tmpval=(*ivals)[0]; + if (len >= tmpval->bv.bv_len) { + tmpval->bv.bv_val=(char *)slapi_ch_malloc(len+1); + } + memcpy(tmpval->bv.bv_val,slapi_value_get_string(val),len); + tmpval->bv.bv_val[len]='\0'; + value_normalize(tmpval->bv.bv_val, syntax, 1 /* trim leading blanks */ ); + tmpval->bv.bv_len=strlen(tmpval->bv.bv_val); + break; + case LDAP_FILTER_EQUALITY: + (*ivals) = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) ); + (*ivals)[0] = slapi_value_dup( val ); + value_normalize( (*ivals)[0]->bv.bv_val, syntax, 1 /* trim leading blanks */ ); + (*ivals)[0]->bv.bv_len = strlen( (*ivals)[0]->bv.bv_val ); + (*ivals)[1] = NULL; + break; + + case LDAP_FILTER_APPROX: + /* XXX should not do this twice! XXX */ + /* get an upper bound on the number of ivals */ + numbvals = 0; + for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL; + w = next_word( w ) ) { + numbvals++; + } + (*ivals) = (Slapi_Value **) slapi_ch_malloc( (numbvals + 1) * + sizeof(Slapi_Value *) ); + + i = 0; + for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL; + w = next_word( w ) ) { + if ( (c = phonetic( w )) != NULL ) { + (*ivals)[i] = slapi_value_new_string_passin(c); + i++; + } + } + (*ivals)[i] = NULL; + + if ( i == 0 ) { + slapi_ch_free((void**)ivals ); + return( 0 ); + } + break; + default: + LDAPDebug( LDAP_DEBUG_ANY, + "string_assertion2keys_ava: unknown ftype 0x%x\n", + ftype, 0, 0 ); + break; + } + + return( 0 ); +} + +int +string_assertion2keys_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value ***ivals, + int syntax +) +{ + int nsubs, i, len; + + *ivals = NULL; + + /* + * First figure out how many keys we will return. The answer is based + * on the length of each assertion value. Since normalization may + * reduce the length (such as when spaces are removed from space + * insensitive strings), we call value_normalize() before checking + * the length. + */ + nsubs = 0; + if ( initial != NULL ) { + value_normalize( initial, syntax, 0 /* do not trim leading blanks */ ); + if ( strlen( initial ) > SUBLEN - 2 ) { + nsubs += strlen( initial ) - SUBLEN + 2; + } else { + initial = NULL; /* save some work later */ + } + } + for ( i = 0; any != NULL && any[i] != NULL; i++ ) { + value_normalize( any[i], syntax, 0 /* do not trim leading blanks */ ); + len = strlen( any[i] ); + if ( len >= SUBLEN ) { + nsubs += len - SUBLEN + 1; + } + } + if ( final != NULL ) { + value_normalize( final, syntax, 0 /* do not trim leading blanks */ ); + if ( strlen( final ) > SUBLEN - 2 ) { + nsubs += strlen( final ) - SUBLEN + 2; + } else { + final = NULL; /* save some work later */ + } + } + if ( nsubs == 0 ) { /* no keys to return */ + return( 0 ); + } + + /* + * Next, allocated the ivals array and fill it in with the actual + * keys. *ivals is a NULL terminated array of Slapi_Value pointers. + */ + + *ivals = (Slapi_Value **) slapi_ch_malloc( (nsubs + 1) * sizeof(Slapi_Value *) ); + + nsubs = 0; + if ( initial != NULL ) { + substring_comp_keys( ivals, &nsubs, initial, '^', syntax ); + } + for ( i = 0; any != NULL && any[i] != NULL; i++ ) { + if ( strlen( any[i] ) < SUBLEN ) { + continue; + } + substring_comp_keys( ivals, &nsubs, any[i], 0, syntax ); + } + if ( final != NULL ) { + substring_comp_keys( ivals, &nsubs, final, '$', syntax ); + } + (*ivals)[nsubs] = NULL; + + return( 0 ); +} + +static void +substring_comp_keys( + Slapi_Value ***ivals, + int *nsubs, + char *str, + int prepost, + int syntax +) +{ + int i, len; + char *p; + char buf[SUBLEN + 1]; + + LDAPDebug( LDAP_DEBUG_TRACE, "=> substring_comp_keys (%s) %d\n", + str, prepost, 0 ); + + len = strlen( str ); + + /* prepend ^ for initial substring */ + if ( prepost == '^' ) + { + buf[0] = '^'; + for ( i = 0; i < SUBLEN - 1; i++ ) + { + buf[i + 1] = str[i]; + } + buf[SUBLEN] = '\0'; + (*ivals)[*nsubs] = slapi_value_new_string(buf); + (*nsubs)++; + } + + for ( p = str; p < (str + len - SUBLEN + 1); p++ ) + { + for ( i = 0; i < SUBLEN; i++ ) + { + buf[i] = p[i]; + } + buf[SUBLEN] = '\0'; + (*ivals)[*nsubs] = slapi_value_new_string(buf); + (*nsubs)++; + } + + if ( prepost == '$' ) + { + p = str + len - SUBLEN + 1; + for ( i = 0; i < SUBLEN - 1; i++ ) + { + buf[i] = p[i]; + } + buf[SUBLEN - 1] = '$'; + buf[SUBLEN] = '\0'; + (*ivals)[*nsubs] = slapi_value_new_string(buf); + (*nsubs)++; + } + + LDAPDebug( LDAP_DEBUG_TRACE, "<= substring_comp_keys\n", 0, 0, 0 ); +} diff --git a/ldap/servers/plugins/syntaxes/syntax.h b/ldap/servers/plugins/syntaxes/syntax.h new file mode 100644 index 00000000..d6d883c9 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/syntax.h @@ -0,0 +1,42 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* syntax.h - string syntax definitions */ + +#ifndef _LIBSYNTAX_H_ +#define _LIBSYNTAX_H_ + +#define SLAPD_LOGGING 1 + +#include "slap.h" +#include "slapi-plugin.h" +#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */ + +#define SYNTAX_CIS 1 +#define SYNTAX_CES 2 +#define SYNTAX_TEL 4 /* telephone number: used with SYNTAX_CIS */ +#define SYNTAX_DN 8 /* distinguished name: used with SYNTAX_CIS */ +#define SYNTAX_SI 16 /* space insensitive: used with SYNTAX_CIS */ + +#define SUBLEN 3 + +#ifndef MIN +#define MIN( a, b ) (a < b ? a : b ) +#endif + +int string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,Slapi_Value **bvals, int syntax ); +int string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax,int ftype, Slapi_Value **retVal ); +int string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,Slapi_Value ***ivals, int syntax, int ftype ); +int string_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***ivals,int syntax,int ftype ); +int string_assertion2keys_sub(Slapi_PBlock *pb,char *initial,char **any,char *final,Slapi_Value ***ivals,int syntax); +int value_cmp(struct berval *v1,struct berval *v2,int syntax,int normalize); +void value_normalize(char *s,int syntax,int trim_leading_blanks); + +char *first_word( char *s ); +char *next_word( char *s ); +char *phonetic( char *s ); + + +#endif diff --git a/ldap/servers/plugins/syntaxes/tel.c b/ldap/servers/plugins/syntaxes/tel.c new file mode 100644 index 00000000..c2c80d1a --- /dev/null +++ b/ldap/servers/plugins/syntaxes/tel.c @@ -0,0 +1,135 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* tel.c - telephonenumber syntax routines */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +static int tel_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter, + Slapi_Value **bvals, int ftype, Slapi_Value **retVal ); +static int tel_filter_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value **bvals ); +static int tel_values2keys( Slapi_PBlock *pb, Slapi_Value **val, + Slapi_Value ***ivals, int ftype ); +static int tel_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val, + Slapi_Value ***ivals, int ftype ); +static int tel_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any, + char *final, Slapi_Value ***ivals ); +static int tel_compare(struct berval *v1, struct berval *v2); + +/* the first name is the official one from RFC 2252 */ +static char *names[] = { "TelephoneNumber", "tel", TELEPHONE_SYNTAX_OID, 0 }; + +static Slapi_PluginDesc pdesc = { "tele-syntax", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "telephoneNumber attribute syntax plugin" }; + +int +tel_init( Slapi_PBlock *pb ) +{ + int rc, flags; + + LDAPDebug( LDAP_DEBUG_PLUGIN, "=> tel_init\n", 0, 0, 0 ); + + rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + (void *) SLAPI_PLUGIN_VERSION_01 ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&pdesc ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA, + (void *) tel_filter_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB, + (void *) tel_filter_sub ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS, + (void *) tel_values2keys ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA, + (void *) tel_assertion2keys_ava ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB, + (void *) tel_assertion2keys_sub ); + flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING; + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS, + (void *) &flags ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES, + (void *) names ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID, + (void *) TELEPHONE_SYNTAX_OID ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE, + (void *) tel_compare ); + + LDAPDebug( LDAP_DEBUG_PLUGIN, "<= tel_init %d\n", rc, 0, 0 ); + return( rc ); +} + +static int +tel_filter_ava( + Slapi_PBlock *pb, + struct berval *bvfilter, + Slapi_Value **bvals, + int ftype, + Slapi_Value **retVal +) +{ + return( string_filter_ava( bvfilter, bvals, SYNTAX_TEL | SYNTAX_CIS, + ftype, retVal ) ); +} + + +static int +tel_filter_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value **bvals +) +{ + return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_TEL | SYNTAX_CIS ) ); +} + +static int +tel_values2keys( + Slapi_PBlock *pb, + Slapi_Value **vals, + Slapi_Value ***ivals, + int ftype +) +{ + return( string_values2keys( pb, vals, ivals, SYNTAX_TEL | SYNTAX_CIS, + ftype ) ); +} + +static int +tel_assertion2keys_ava( + Slapi_PBlock *pb, + Slapi_Value *val, + Slapi_Value ***ivals, + int ftype +) +{ + return(string_assertion2keys_ava( pb, val, ivals, + SYNTAX_TEL | SYNTAX_CIS, ftype )); +} + +static int +tel_assertion2keys_sub( + Slapi_PBlock *pb, + char *initial, + char **any, + char *final, + Slapi_Value ***ivals +) +{ + return( string_assertion2keys_sub( pb, initial, any, final, ivals, + SYNTAX_TEL | SYNTAX_CIS ) ); +} + +static int tel_compare( + struct berval *v1, + struct berval *v2 +) +{ + return value_cmp(v1, v2, SYNTAX_TEL|SYNTAX_CIS, 3 /* Normalise both values */); +} diff --git a/ldap/servers/plugins/syntaxes/value.c b/ldap/servers/plugins/syntaxes/value.c new file mode 100644 index 00000000..be496091 --- /dev/null +++ b/ldap/servers/plugins/syntaxes/value.c @@ -0,0 +1,209 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* value.c - routines for dealing with values */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "syntax.h" + +/* + * Do not use the SDK ldap_utf8isspace directly until it is faster + * than this one. + */ +static int +utf8isspace_fast( char* s ) +{ + register unsigned char c = *(unsigned char*)s; + if (0x80 & c) return(ldap_utf8isspace(s)); + switch (c) { + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x20: + return 1; + default: break; + } + return 0; +} + +/* +** This function is used to normalizes search filter components, +** and attribute values. +** +** jcm: I added the trim_spaces flag since this function +** was incorrectly modifying search filter components. A search +** of the form "cn=a* b*" (note the space) would be wrongly +** normalized into "cn=a*b*", because this function is called +** once for "a" and once for " b". +*/ +void +value_normalize( + char *s, + int syntax, + int trim_spaces +) +{ + char *d; + int prevspace, curspace; + + if ( ! (syntax & SYNTAX_CIS) && ! (syntax & SYNTAX_CES) ) { + return; + } + + if ( syntax & SYNTAX_DN ) { + (void) slapi_dn_normalize_case( s ); + return; + } + + d = s; + if (trim_spaces) { + /* strip leading blanks */ + while (utf8isspace_fast(s)) { + LDAP_UTF8INC(s); + } + } + /* handle value of all spaces - turn into single space */ + /* unless space insensitive syntax - turn into zero length string */ + if ( *s == '\0' && s != d ) { + if ( ! (syntax & SYNTAX_SI)) { + *d++ = ' '; + } + *d = '\0'; + return; + } + prevspace = 0; + while ( *s ) { + curspace = utf8isspace_fast(s); + + /* ignore spaces and '-' in telephone numbers */ + if ( (syntax & SYNTAX_TEL) && (curspace || *s == '-') ) { + LDAP_UTF8INC(s); + continue; + } + + /* ignore all spaces if this is a space insensitive value */ + if ( (syntax & SYNTAX_SI) && curspace ) { + LDAP_UTF8INC(s); + continue; + } + + /* compress multiple blanks */ + if ( prevspace && curspace ) { + LDAP_UTF8INC(s); + continue; + } + prevspace = curspace; + if ( syntax & SYNTAX_CIS ) { + int ssz, dsz; + slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz); + s += ssz; + d += dsz; + } else { + char *np; + int sz; + + np = ldap_utf8next(s); + if (np == NULL || np == s) break; + sz = np - s; + memcpy(d,s,sz); + d += sz; + s += sz; + } + } + *d = '\0'; + /* strip trailing blanks */ + if (prevspace && trim_spaces) { + char *nd; + + nd = ldap_utf8prev(d); + while (nd && utf8isspace_fast(nd)) { + d = nd; + nd = ldap_utf8prev(d); + *d = '\0'; + } + } +} + +int +value_cmp( + struct berval *v1, + struct berval *v2, + int syntax, + int normalize +) +{ + int rc; + struct berval bvcopy1; + struct berval bvcopy2; + char little_buffer[64]; + size_t buffer_space = sizeof(little_buffer); + int buffer_offset = 0; + int free_v1 = 0; + int free_v2 = 0; + + /* This code used to call malloc up to four times in the copying + * of attributes to be normalized. Now we attempt to keep everything + * on the stack and only malloc if the data is big + */ + if ( normalize & 1 ) { + /* Do we have space in the little buffer ? */ + if (v1->bv_len < buffer_space) { + bvcopy1.bv_len = v1->bv_len; + SAFEMEMCPY(&little_buffer[buffer_offset],v1->bv_val,v1->bv_len); + bvcopy1.bv_val = &little_buffer[buffer_offset]; + bvcopy1.bv_val[v1->bv_len] = '\0'; + v1 = &bvcopy1; + buffer_space-= v1->bv_len+1; + buffer_offset+= v1->bv_len+1; + } else { + v1 = ber_bvdup( v1 ); + free_v1 = 1; + } + value_normalize( v1->bv_val, syntax, 1 /* trim leading blanks */ ); + } + if ( normalize & 2 ) { + /* Do we have space in the little buffer ? */ + if (v2->bv_len < buffer_space) { + bvcopy2.bv_len = v2->bv_len; + SAFEMEMCPY(&little_buffer[buffer_offset],v2->bv_val,v2->bv_len); + bvcopy2.bv_val = &little_buffer[buffer_offset]; + bvcopy2.bv_val[v2->bv_len] = '\0'; + v2 = &bvcopy2; + buffer_space-= v2->bv_len+1; + buffer_offset+= v2->bv_len+1; + } else { + v2 = ber_bvdup( v2 ); + free_v2 = 1; + } + value_normalize( v2->bv_val, syntax, 1 /* trim leading blanks */ ); + } + + switch ( syntax ) { + case SYNTAX_CIS: + case (SYNTAX_CIS | SYNTAX_TEL): + case (SYNTAX_CIS | SYNTAX_DN): + case (SYNTAX_CIS | SYNTAX_SI): + rc = slapi_utf8casecmp( (unsigned char *)v1->bv_val, + (unsigned char *)v2->bv_val ); + break; + + case SYNTAX_CES: + rc = strcmp( v1->bv_val, v2->bv_val ); + break; + } + + if ( (normalize & 1) && free_v1) { + ber_bvfree( v1 ); + } + if ( (normalize & 2) && free_v2) { + ber_bvfree( v2 ); + } + + return( rc ); +} |