andykimpe / rpms / 389-ds-base

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