From 49f81d98f87b034930b7993e5722b88ce7584483 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Wed, 26 Feb 2014 11:07:00 -0800 Subject: [PATCH 168/225] Ticket 47369 version2 - provide default syntax plugin Backported commit d779853f5fa6eeeea436627801718070824ca795 Author: Ludwig Krispenz Bug Description: syntax plugins are laoded during bootstrapping, but in that phase already attributes are handled eg in dse.ldif and schema files and no proper way to normalize or comare values is provided. This became visible with teh fix for ticket #346 where large attribute sets will be sorted Fix Description: when the first attribute syntax init is done, create a plugin for directory string syntax and register it with a dummy attribute name. if for any attribute the syntax lookup fails fall back to using this plugin. It will only be used until the syntax plugins are loaded and in the startup phase it is acceptable to use directory string. The impelemenation of the default plugin is reduce to the necessary minimum not to duplicate the code of the syntax plugins. A more rigorus solution would be to refactor the code and and move the common code from the syntax plugin to the slapd level and reuse it in the default plugin. But this would be a major change and should only be done with a review of the syntax plugin code, whic could probabyly be optimized. https://fedorahosted.org/389/ticket/47369 Reviewed by: RichM (cherry picked from commit 62d0dbf548e1d2b0d7f7e09809456393034e34a5) (cherry picked from commit ecafacefd47c20dcc01cb0c69b378b4203f77d0b) Note: removed SLAPI_ATTR_FLAG_NOEXPOSE (cherry picked from commit e4ddba7fb35bec4aa3b7352d13d283fb17b14755) --- ldap/servers/slapd/attr.c | 46 ++++++++++ ldap/servers/slapd/attrsyntax.c | 197 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 243 insertions(+) diff --git a/ldap/servers/slapd/attr.c b/ldap/servers/slapd/attr.c index 51621e5..9894393 100644 --- a/ldap/servers/slapd/attr.c +++ b/ldap/servers/slapd/attr.c @@ -229,6 +229,34 @@ slapi_attr_init(Slapi_Attr *a, const char *type) return slapi_attr_init_locking_optional(a, type, PR_TRUE); } +int +slapi_attr_init_syntax(Slapi_Attr *a) +{ + int rc = 1; + struct asyntaxinfo *asi = NULL; + char *tmp = 0; + const char *basetype= NULL; + char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH]; + + basetype = buf; + tmp = slapi_attr_basetype(a->a_type, buf, sizeof(buf)); + if (tmp) { + basetype = buf; + } + asi = attr_syntax_get_by_name_with_default (basetype); + if (asi) { + rc = 0; + a->a_plugin = asi->asi_plugin; + a->a_flags = asi->asi_flags; + a->a_mr_eq_plugin = asi->asi_mr_eq_plugin; + a->a_mr_ord_plugin = asi->asi_mr_ord_plugin; + a->a_mr_sub_plugin = asi->asi_mr_sub_plugin; + } + if (tmp) + slapi_ch_free_string(&tmp); + return rc; +} + Slapi_Attr * slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_lock) { @@ -408,6 +436,10 @@ slapi_attr_value_find( const Slapi_Attr *a, const struct berval *v ) return( -1 ); } + if ( a->a_flags == 0 && a->a_plugin == NULL ) { + slapi_attr_init_syntax ((Slapi_Attr *)a); + } + ava.ava_type = a->a_type; ava.ava_value = *v; if (a->a_flags & SLAPI_ATTR_FLAG_NORMALIZED) { @@ -519,6 +551,9 @@ attr_get_present_values(const Slapi_Attr *a) int slapi_attr_get_flags( const Slapi_Attr *a, unsigned long *flags ) { + if ( a->a_flags == 0 && a->a_plugin == NULL ) { + slapi_attr_init_syntax ((Slapi_Attr *)a); + } *flags = a->a_flags; return( 0 ); } @@ -526,6 +561,9 @@ slapi_attr_get_flags( const Slapi_Attr *a, unsigned long *flags ) int slapi_attr_flag_is_set( const Slapi_Attr *a, unsigned long flag ) { + if ( a->a_flags == 0 && a->a_plugin == NULL ) { + slapi_attr_init_syntax ((Slapi_Attr *)a); + } return( a->a_flags & flag ); } @@ -537,6 +575,10 @@ slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct Slapi_Value *cvals[2]; Slapi_Value tmpcval; + if ( a->a_flags == 0 && a->a_plugin == NULL ) { + slapi_attr_init_syntax ((Slapi_Attr *)a); + } + cvals[0] = &tmpcval; cvals[0]->v_csnset = NULL; cvals[0]->bv = *v1; @@ -559,6 +601,10 @@ slapi_attr_value_cmp_ext(const Slapi_Attr *a, Slapi_Value *v1, Slapi_Value *v2) unsigned long v2_flags = v2->v_flags; const struct berval *bv2 = slapi_value_get_berval(v2); + if ( a->a_flags == 0 && a->a_plugin == NULL ) { + slapi_attr_init_syntax ((Slapi_Attr *)a); + } + cvals[0] = v1; cvals[1] = NULL; a2.a_present_values.va = cvals; diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c index c0827e2..79736b5 100644 --- a/ldap/servers/slapd/attrsyntax.c +++ b/ldap/servers/slapd/attrsyntax.c @@ -74,6 +74,7 @@ static Slapi_RWLock *name2asi_lock = NULL; #define AS_UNLOCK_WRITE(l) slapi_rwlock_unlock(l) +static struct asyntaxinfo *default_asi = NULL; static void *attr_syntax_get_plugin_by_name_with_default( const char *type ); static void attr_syntax_delete_no_lock( struct asyntaxinfo *asip, @@ -323,6 +324,17 @@ attr_syntax_get_by_name(const char *name) return attr_syntax_get_by_name_locking_optional(name, PR_TRUE); } +struct asyntaxinfo * +attr_syntax_get_by_name_with_default(const char *name) +{ + struct asyntaxinfo *asi = NULL; + asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE); + if (asi == NULL) + asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX); + if ( asi == NULL ) + asi = default_asi; + return asi; +} /* * A version of attr_syntax_get_by_name() that allows you to bypass using @@ -538,6 +550,154 @@ attr_syntax_exists(const char *attr_name) return 0; } +static void default_dirstring_normalize_int(char *s, int trim_spaces); + +static +int default_dirstring_filter_ava( struct berval *bvfilter, Slapi_Value **bvals,int ftype, Slapi_Value **retVal ) +{ + return(0); +} + +static +int default_dirstring_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,Slapi_Value ***ivals, int ftype ) +{ + int numbvals = 0; + Slapi_Value **nbvals, **nbvlp; + Slapi_Value **bvlp; + char *c; + + if (NULL == ivals) { + return 1; + } + *ivals = NULL; + if (NULL == bvals) { + return 1; + } + switch ( ftype ) { + case LDAP_FILTER_EQUALITY: + /* allocate a new array for the normalized values */ + for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) { + numbvals++; + } + nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *)); + + for ( bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++ ) { + c = slapi_ch_strdup(slapi_value_get_string(*bvlp)); + default_dirstring_normalize_int( c, 1 ); + *nbvlp = slapi_value_new_string_passin(c); + c = NULL; + } + *ivals = nbvals; + break; + + case LDAP_FILTER_APPROX: + case LDAP_FILTER_SUBSTRINGS: + default: + /* default plugin only handles equality so far */ + LDAPDebug( LDAP_DEBUG_ANY, + "default_dirstring_values2keys: unsupported ftype 0x%x\n", + ftype, 0, 0 ); + break; + } + return(0); +} + +static +int default_dirstring_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***ivals,int ftype ) +{ + return(0); +} + +static +int default_dirstring_cmp(struct berval *v1,struct berval *v2, int normalize) +{ + return(0); +} + +static +void default_dirstring_normalize(Slapi_PBlock *pb, char *s, int trim_spaces, char **alt) +{ + default_dirstring_normalize_int(s, trim_spaces); +} + +static +void default_dirstring_normalize_int(char *s, int trim_spaces) +{ + char *head = s; + char *d; + int prevspace, curspace; + + if (NULL == s) { + return; + } + d = s; + if (trim_spaces) { + /* strip leading blanks */ + while (ldap_utf8isspace(s)) { + LDAP_UTF8INC(s); + } + } + + /* handle value of all spaces - turn into single space */ + if ( *s == '\0' && s != d ) { + *d++ = ' '; + *d = '\0'; + return; + } + prevspace = 0; + while ( *s ) { + int ssz, dsz; + curspace = ldap_utf8isspace(s); + + /* compress multiple blanks */ + if ( prevspace && curspace ) { + LDAP_UTF8INC(s); + continue; + } + prevspace = curspace; + slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz); + s += ssz; + d += dsz; + } + *d = '\0'; + /* strip trailing blanks */ + if (prevspace && trim_spaces) { + char *nd; + + nd = ldap_utf8prev(d); + while (nd && nd >= head && ldap_utf8isspace(nd)) { + d = nd; + nd = ldap_utf8prev(d); + *d = '\0'; + } + } +} + +static struct slapdplugin * +attr_syntax_default_plugin ( const char *nameoroid ) +{ + + struct slapdplugin *pi = NULL; + /* + * create a new plugin structure and + * set the plugin function pointers. + */ + pi = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin)); + + pi->plg_dn = slapi_ch_strdup("default plugin for directory string syntax"); + pi->plg_closed = 0; + pi->plg_syntax_oid = slapi_ch_strdup(nameoroid); + + + pi->plg_syntax_filter_ava = (IFP) default_dirstring_filter_ava; + pi->plg_syntax_values2keys = (IFP) default_dirstring_values2keys; + pi->plg_syntax_assertion2keys_ava = (IFP) default_dirstring_assertion2keys_ava; + pi->plg_syntax_compare = (IFP) default_dirstring_cmp; + pi->plg_syntax_normalize = (VFPV) default_dirstring_normalize; + + return (pi); + +} /* check syntax */ static void * @@ -556,11 +716,14 @@ attr_syntax_get_plugin_by_name_with_default( const char *type ) * attribute type that has that syntax. */ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX); + if (asi == NULL) + asi = default_asi; } if ( NULL != asi ) { plugin = asi->asi_plugin; attr_syntax_return( asi ); } + return( plugin ); } @@ -674,6 +837,32 @@ cleanup_and_return: return rc; } +static int +attr_syntax_create_default( const char *name, const char *oid, + const char *syntax, unsigned long extraflags ) +{ + int rc = 0; + char *names[2]; + unsigned long std_flags = SLAPI_ATTR_FLAG_STD_ATTR | SLAPI_ATTR_FLAG_OPATTR; + + names[0] = (char *)name; + names[1] = NULL; + + if (default_asi) + return (rc); + + rc = attr_syntax_create( oid, names, 1, + "internal server defined attribute type", + NULL, /* superior */ + NULL, NULL, NULL, /* matching rules */ + NULL, syntax, + SLAPI_SYNTAXLENGTH_NONE, + std_flags | extraflags, + &default_asi ); + if ( rc == 0 && default_asi->asi_plugin == 0) + default_asi->asi_plugin = attr_syntax_default_plugin (syntax ); + return (rc); +} /* * Returns an LDAP result code. @@ -1104,6 +1293,8 @@ attr_syntax_delete_all_for_schemareload(unsigned long flag) (void *)&fi); } +#define ATTR_DEFAULT_SYNTAX_OID "1.1" +#define ATTR_DEFAULT_SYNTAX "defaultdirstringsyntax" static int attr_syntax_init(void) { @@ -1135,6 +1326,12 @@ attr_syntax_init(void) "slapi_new_rwlock() for oid2asi lock failed\n" ); return 1; } + /* add a default syntax plugin as fallback, required during startup + */ + attr_syntax_create_default( ATTR_DEFAULT_SYNTAX, + ATTR_DEFAULT_SYNTAX_OID, + DIRSTRING_SYNTAX_OID, + SLAPI_ATTR_FLAG_NOUSERMOD ); } return 0; } -- 1.8.1.4