1*cf1d77f7Schristos /*	$NetBSD: cr.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
32de962bdSlukem /* cr.c - content rule routines */
433197c6aStron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem  *
7*cf1d77f7Schristos  * Copyright 1998-2021 The OpenLDAP Foundation.
82de962bdSlukem  * All rights reserved.
92de962bdSlukem  *
102de962bdSlukem  * Redistribution and use in source and binary forms, with or without
112de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
122de962bdSlukem  * Public License.
132de962bdSlukem  *
142de962bdSlukem  * A copy of this license is available in the file LICENSE in the
152de962bdSlukem  * top-level directory of the distribution or, alternatively, at
162de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
172de962bdSlukem  */
182de962bdSlukem 
198bd9f7cdSchristos #include <sys/cdefs.h>
20*cf1d77f7Schristos __RCSID("$NetBSD: cr.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
218bd9f7cdSchristos 
222de962bdSlukem #include "portable.h"
232de962bdSlukem 
242de962bdSlukem #include <stdio.h>
252de962bdSlukem 
262de962bdSlukem #include <ac/ctype.h>
272de962bdSlukem #include <ac/string.h>
282de962bdSlukem #include <ac/socket.h>
292de962bdSlukem 
302de962bdSlukem #include "slap.h"
312de962bdSlukem 
322de962bdSlukem struct cindexrec {
332de962bdSlukem 	struct berval	cir_name;
342de962bdSlukem 	ContentRule	*cir_cr;
352de962bdSlukem };
362de962bdSlukem 
372de962bdSlukem static Avlnode	*cr_index = NULL;
382de962bdSlukem static LDAP_STAILQ_HEAD(CRList, ContentRule) cr_list
392de962bdSlukem 	= LDAP_STAILQ_HEAD_INITIALIZER(cr_list);
402de962bdSlukem 
412de962bdSlukem static int
cr_index_cmp(const void * v_cir1,const void * v_cir2)422de962bdSlukem cr_index_cmp(
432de962bdSlukem     const void	*v_cir1,
442de962bdSlukem     const void	*v_cir2 )
452de962bdSlukem {
462de962bdSlukem 	const struct cindexrec	*cir1 = v_cir1;
472de962bdSlukem 	const struct cindexrec	*cir2 = v_cir2;
482de962bdSlukem 	int i = cir1->cir_name.bv_len - cir2->cir_name.bv_len;
492de962bdSlukem 	if (i) return i;
502de962bdSlukem 	return strcasecmp( cir1->cir_name.bv_val, cir2->cir_name.bv_val );
512de962bdSlukem }
522de962bdSlukem 
532de962bdSlukem static int
cr_index_name_cmp(const void * v_name,const void * v_cir)542de962bdSlukem cr_index_name_cmp(
552de962bdSlukem     const void	*v_name,
562de962bdSlukem     const void	*v_cir )
572de962bdSlukem {
582de962bdSlukem 	const struct berval    *name = v_name;
592de962bdSlukem 	const struct cindexrec *cir  = v_cir;
602de962bdSlukem 	int i = name->bv_len - cir->cir_name.bv_len;
612de962bdSlukem 	if (i) return i;
622de962bdSlukem 	return strncasecmp( name->bv_val, cir->cir_name.bv_val, name->bv_len );
632de962bdSlukem }
642de962bdSlukem 
652de962bdSlukem ContentRule *
cr_find(const char * crname)662de962bdSlukem cr_find( const char *crname )
672de962bdSlukem {
682de962bdSlukem 	struct berval bv;
692de962bdSlukem 
702de962bdSlukem 	bv.bv_val = (char *)crname;
712de962bdSlukem 	bv.bv_len = strlen( crname );
722de962bdSlukem 
732de962bdSlukem 	return( cr_bvfind( &bv ) );
742de962bdSlukem }
752de962bdSlukem 
762de962bdSlukem ContentRule *
cr_bvfind(struct berval * crname)772de962bdSlukem cr_bvfind( struct berval *crname )
782de962bdSlukem {
792de962bdSlukem 	struct cindexrec	*cir;
802de962bdSlukem 
81*cf1d77f7Schristos 	cir = ldap_avl_find( cr_index, crname, cr_index_name_cmp );
822de962bdSlukem 
832de962bdSlukem 	if ( cir != NULL ) {
842de962bdSlukem 		return( cir->cir_cr );
852de962bdSlukem 	}
862de962bdSlukem 
872de962bdSlukem 	return( NULL );
882de962bdSlukem }
892de962bdSlukem 
902de962bdSlukem static int
cr_destroy_one(ContentRule * c)912de962bdSlukem cr_destroy_one( ContentRule *c )
922de962bdSlukem {
932de962bdSlukem 	assert( c != NULL );
942de962bdSlukem 
952de962bdSlukem 	if (c->scr_auxiliaries) ldap_memfree(c->scr_auxiliaries);
962de962bdSlukem 	if (c->scr_required) ldap_memfree(c->scr_required);
972de962bdSlukem 	if (c->scr_allowed) ldap_memfree(c->scr_allowed);
982de962bdSlukem 	if (c->scr_precluded) ldap_memfree(c->scr_precluded);
992de962bdSlukem 	ldap_contentrule_free((LDAPContentRule *)c);
1002de962bdSlukem 
1012de962bdSlukem 	return 0;
1022de962bdSlukem }
1032de962bdSlukem 
1042de962bdSlukem void
cr_destroy(void)1052de962bdSlukem cr_destroy( void )
1062de962bdSlukem {
1072de962bdSlukem 	ContentRule *c;
1082de962bdSlukem 
109*cf1d77f7Schristos 	ldap_avl_free(cr_index, ldap_memfree);
1102de962bdSlukem 
1112de962bdSlukem 	while( !LDAP_STAILQ_EMPTY(&cr_list) ) {
1122de962bdSlukem 		c = LDAP_STAILQ_FIRST(&cr_list);
1132de962bdSlukem 		LDAP_STAILQ_REMOVE_HEAD(&cr_list, scr_next);
1142de962bdSlukem 
1152de962bdSlukem 		cr_destroy_one( c );
1162de962bdSlukem 	}
1172de962bdSlukem }
1182de962bdSlukem 
1192de962bdSlukem static int
cr_insert(ContentRule * scr,const char ** err)1202de962bdSlukem cr_insert(
1212de962bdSlukem     ContentRule		*scr,
1222de962bdSlukem     const char		**err
1232de962bdSlukem )
1242de962bdSlukem {
1252de962bdSlukem 	struct cindexrec	*cir;
1262de962bdSlukem 	char			**names;
1272de962bdSlukem 
12833197c6aStron 	assert( scr != NULL );
12933197c6aStron 
1302de962bdSlukem 	if ( scr->scr_oid ) {
1312de962bdSlukem 		cir = (struct cindexrec *)
1322de962bdSlukem 			ch_calloc( 1, sizeof(struct cindexrec) );
1332de962bdSlukem 		cir->cir_name.bv_val = scr->scr_oid;
1342de962bdSlukem 		cir->cir_name.bv_len = strlen( scr->scr_oid );
1352de962bdSlukem 		cir->cir_cr = scr;
1362de962bdSlukem 
137*cf1d77f7Schristos 		if ( ldap_avl_insert( &cr_index, (caddr_t) cir,
138*cf1d77f7Schristos 		                 cr_index_cmp, ldap_avl_dup_error ) )
1392de962bdSlukem 		{
1402de962bdSlukem 			*err = scr->scr_oid;
1412de962bdSlukem 			ldap_memfree(cir);
1422de962bdSlukem 			return SLAP_SCHERR_CR_DUP;
1432de962bdSlukem 		}
1442de962bdSlukem 
1452de962bdSlukem 		/* FIX: temporal consistency check */
1462de962bdSlukem 		assert( cr_bvfind(&cir->cir_name) != NULL );
1472de962bdSlukem 	}
1482de962bdSlukem 
1492de962bdSlukem 	if ( (names = scr->scr_names) ) {
1502de962bdSlukem 		while ( *names ) {
1512de962bdSlukem 			cir = (struct cindexrec *)
1522de962bdSlukem 				ch_calloc( 1, sizeof(struct cindexrec) );
1532de962bdSlukem 			cir->cir_name.bv_val = *names;
1542de962bdSlukem 			cir->cir_name.bv_len = strlen( *names );
1552de962bdSlukem 			cir->cir_cr = scr;
1562de962bdSlukem 
157*cf1d77f7Schristos 			if ( ldap_avl_insert( &cr_index, (caddr_t) cir,
158*cf1d77f7Schristos 			                 cr_index_cmp, ldap_avl_dup_error ) )
1592de962bdSlukem 			{
1602de962bdSlukem 				*err = *names;
1612de962bdSlukem 				ldap_memfree(cir);
1622de962bdSlukem 				return SLAP_SCHERR_CR_DUP;
1632de962bdSlukem 			}
1642de962bdSlukem 
1652de962bdSlukem 			/* FIX: temporal consistency check */
1662de962bdSlukem 			assert( cr_bvfind(&cir->cir_name) != NULL );
1672de962bdSlukem 
1682de962bdSlukem 			names++;
1692de962bdSlukem 		}
1702de962bdSlukem 	}
1712de962bdSlukem 
1722de962bdSlukem 	LDAP_STAILQ_INSERT_TAIL(&cr_list, scr, scr_next);
1732de962bdSlukem 
1742de962bdSlukem 	return 0;
1752de962bdSlukem }
1762de962bdSlukem 
1772de962bdSlukem static int
cr_add_auxiliaries(ContentRule * scr,int * op,const char ** err)1782de962bdSlukem cr_add_auxiliaries(
1792de962bdSlukem     ContentRule		*scr,
1802de962bdSlukem 	int			*op,
1812de962bdSlukem     const char		**err )
1822de962bdSlukem {
1832de962bdSlukem 	int naux;
1842de962bdSlukem 
1852de962bdSlukem 	if( scr->scr_oc_oids_aux == NULL ) return 0;
1862de962bdSlukem 
1872de962bdSlukem 	for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
1882de962bdSlukem 		/* count them */ ;
1892de962bdSlukem 	}
1902de962bdSlukem 
1912de962bdSlukem 	scr->scr_auxiliaries = ch_calloc( naux+1, sizeof(ObjectClass *));
1922de962bdSlukem 
1932de962bdSlukem 	for( naux=0; scr->scr_oc_oids_aux[naux]; naux++ ) {
1942de962bdSlukem 		ObjectClass *soc = scr->scr_auxiliaries[naux]
1952de962bdSlukem 			= oc_find(scr->scr_oc_oids_aux[naux]);
1962de962bdSlukem 		if ( !soc ) {
1972de962bdSlukem 			*err = scr->scr_oc_oids_aux[naux];
1982de962bdSlukem 			return SLAP_SCHERR_CLASS_NOT_FOUND;
1992de962bdSlukem 		}
2002de962bdSlukem 
2012de962bdSlukem 		if( soc->soc_flags & SLAP_OC_OPERATIONAL &&
2022de962bdSlukem 			soc != slap_schema.si_oc_extensibleObject )
2032de962bdSlukem 		{
2042de962bdSlukem 			(*op)++;
2052de962bdSlukem 		}
2062de962bdSlukem 
2072de962bdSlukem 		if( soc->soc_kind != LDAP_SCHEMA_AUXILIARY ) {
2082de962bdSlukem 			*err = scr->scr_oc_oids_aux[naux];
2092de962bdSlukem 			return SLAP_SCHERR_CR_BAD_AUX;
2102de962bdSlukem 		}
2112de962bdSlukem 	}
2122de962bdSlukem 
2132de962bdSlukem 	scr->scr_auxiliaries[naux] = NULL;
2142de962bdSlukem 	return 0;
2152de962bdSlukem }
2162de962bdSlukem 
2172de962bdSlukem static int
cr_create_required(ContentRule * scr,int * op,const char ** err)2182de962bdSlukem cr_create_required(
2192de962bdSlukem     ContentRule		*scr,
2202de962bdSlukem 	int			*op,
2212de962bdSlukem     const char		**err )
2222de962bdSlukem {
2232de962bdSlukem     char		**attrs = scr->scr_at_oids_must;
2242de962bdSlukem 	char		**attrs1;
2252de962bdSlukem 	AttributeType	*sat;
2262de962bdSlukem 
2272de962bdSlukem 	if ( attrs ) {
2282de962bdSlukem 		attrs1 = attrs;
2292de962bdSlukem 		while ( *attrs1 ) {
2302de962bdSlukem 			sat = at_find(*attrs1);
2312de962bdSlukem 			if ( !sat ) {
2322de962bdSlukem 				*err = *attrs1;
2332de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
2342de962bdSlukem 			}
2352de962bdSlukem 
2362de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
2372de962bdSlukem 
2382de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0) {
2392de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_required) ) {
2402de962bdSlukem 					*err = *attrs1;
2412de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
2422de962bdSlukem 				}
2432de962bdSlukem 			} else {
2442de962bdSlukem 				*err = *attrs1;
2452de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
2462de962bdSlukem 			}
2472de962bdSlukem 			attrs1++;
2482de962bdSlukem 		}
2492de962bdSlukem 	}
2502de962bdSlukem 	return 0;
2512de962bdSlukem }
2522de962bdSlukem 
2532de962bdSlukem static int
cr_create_allowed(ContentRule * scr,int * op,const char ** err)2542de962bdSlukem cr_create_allowed(
2552de962bdSlukem     ContentRule		*scr,
2562de962bdSlukem 	int			*op,
2572de962bdSlukem     const char		**err )
2582de962bdSlukem {
2592de962bdSlukem     char		**attrs = scr->scr_at_oids_may;
2602de962bdSlukem 	char		**attrs1;
2612de962bdSlukem 	AttributeType	*sat;
2622de962bdSlukem 
2632de962bdSlukem 	if ( attrs ) {
2642de962bdSlukem 		attrs1 = attrs;
2652de962bdSlukem 		while ( *attrs1 ) {
2662de962bdSlukem 			sat = at_find(*attrs1);
2672de962bdSlukem 			if ( !sat ) {
2682de962bdSlukem 				*err = *attrs1;
2692de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
2702de962bdSlukem 			}
2712de962bdSlukem 
2722de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
2732de962bdSlukem 
2742de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0 &&
2752de962bdSlukem 				at_find_in_list(sat, scr->scr_allowed) < 0 )
2762de962bdSlukem 			{
2772de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_allowed) ) {
2782de962bdSlukem 					*err = *attrs1;
2792de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
2802de962bdSlukem 				}
2812de962bdSlukem 			} else {
2822de962bdSlukem 				*err = *attrs1;
2832de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
2842de962bdSlukem 			}
2852de962bdSlukem 			attrs1++;
2862de962bdSlukem 		}
2872de962bdSlukem 	}
2882de962bdSlukem 	return 0;
2892de962bdSlukem }
2902de962bdSlukem 
2912de962bdSlukem static int
cr_create_precluded(ContentRule * scr,int * op,const char ** err)2922de962bdSlukem cr_create_precluded(
2932de962bdSlukem     ContentRule		*scr,
2942de962bdSlukem 	int			*op,
2952de962bdSlukem     const char		**err )
2962de962bdSlukem {
2972de962bdSlukem     char		**attrs = scr->scr_at_oids_not;
2982de962bdSlukem 	char		**attrs1;
2992de962bdSlukem 	AttributeType	*sat;
3002de962bdSlukem 
3012de962bdSlukem 	if ( attrs ) {
3022de962bdSlukem 		attrs1 = attrs;
3032de962bdSlukem 		while ( *attrs1 ) {
3042de962bdSlukem 			sat = at_find(*attrs1);
3052de962bdSlukem 			if ( !sat ) {
3062de962bdSlukem 				*err = *attrs1;
3072de962bdSlukem 				return SLAP_SCHERR_ATTR_NOT_FOUND;
3082de962bdSlukem 			}
3092de962bdSlukem 
3102de962bdSlukem 			if( is_at_operational( sat )) (*op)++;
3112de962bdSlukem 
3122de962bdSlukem 			/* FIXME: should also make sure attribute type is not
3132de962bdSlukem 				a required attribute of the structural class or
3142de962bdSlukem 				any auxiliary class */
3152de962bdSlukem 			if ( at_find_in_list(sat, scr->scr_required) < 0 &&
3162de962bdSlukem 				at_find_in_list(sat, scr->scr_allowed) < 0 &&
3172de962bdSlukem 				at_find_in_list(sat, scr->scr_precluded) < 0 )
3182de962bdSlukem 			{
3192de962bdSlukem 				if ( at_append_to_list(sat, &scr->scr_precluded) ) {
3202de962bdSlukem 					*err = *attrs1;
3212de962bdSlukem 					return SLAP_SCHERR_OUTOFMEM;
3222de962bdSlukem 				}
3232de962bdSlukem 			} else {
3242de962bdSlukem 				*err = *attrs1;
3252de962bdSlukem 				return SLAP_SCHERR_CR_BAD_AT;
3262de962bdSlukem 			}
3272de962bdSlukem 			attrs1++;
3282de962bdSlukem 		}
3292de962bdSlukem 	}
3302de962bdSlukem 	return 0;
3312de962bdSlukem }
3322de962bdSlukem 
3332de962bdSlukem int
cr_add(LDAPContentRule * cr,int user,ContentRule ** rscr,const char ** err)3342de962bdSlukem cr_add(
3352de962bdSlukem     LDAPContentRule	*cr,
3362de962bdSlukem 	int user,
3372de962bdSlukem 	ContentRule **rscr,
3382de962bdSlukem     const char		**err
3392de962bdSlukem )
3402de962bdSlukem {
3412de962bdSlukem 	ContentRule	*scr;
3422de962bdSlukem 	int		code;
3432de962bdSlukem 	int		op = 0;
3442de962bdSlukem 	char	*oidm = NULL;
3452de962bdSlukem 
3462de962bdSlukem 	if ( cr->cr_names != NULL ) {
3472de962bdSlukem 		int i;
3482de962bdSlukem 
3492de962bdSlukem 		for( i=0; cr->cr_names[i]; i++ ) {
3502de962bdSlukem 			if( !slap_valid_descr( cr->cr_names[i] ) ) {
3512de962bdSlukem 				return SLAP_SCHERR_BAD_DESCR;
3522de962bdSlukem 			}
3532de962bdSlukem 		}
3542de962bdSlukem 	}
3552de962bdSlukem 
3562de962bdSlukem 	if ( !OID_LEADCHAR( cr->cr_oid[0] )) {
3572de962bdSlukem 		/* Expand OID macros */
3582de962bdSlukem 		char *oid = oidm_find( cr->cr_oid );
3592de962bdSlukem 		if ( !oid ) {
3602de962bdSlukem 			*err = cr->cr_oid;
3612de962bdSlukem 			return SLAP_SCHERR_OIDM;
3622de962bdSlukem 		}
3632de962bdSlukem 		if ( oid != cr->cr_oid ) {
3642de962bdSlukem 			oidm = cr->cr_oid;
3652de962bdSlukem 			cr->cr_oid = oid;
3662de962bdSlukem 		}
3672de962bdSlukem 	}
3682de962bdSlukem 
3692de962bdSlukem 	scr = (ContentRule *) ch_calloc( 1, sizeof(ContentRule) );
3702de962bdSlukem 	AC_MEMCPY( &scr->scr_crule, cr, sizeof(LDAPContentRule) );
3712de962bdSlukem 
3722de962bdSlukem 	scr->scr_oidmacro = oidm;
3732de962bdSlukem 	scr->scr_sclass = oc_find(cr->cr_oid);
3742de962bdSlukem 	if ( !scr->scr_sclass ) {
3752de962bdSlukem 		*err = cr->cr_oid;
3762de962bdSlukem 		code = SLAP_SCHERR_CLASS_NOT_FOUND;
3772de962bdSlukem 		goto fail;
3782de962bdSlukem 	}
3792de962bdSlukem 
3802de962bdSlukem 	/* check object class usage */
3812de962bdSlukem 	if( scr->scr_sclass->soc_kind != LDAP_SCHEMA_STRUCTURAL )
3822de962bdSlukem 	{
3832de962bdSlukem 		*err = cr->cr_oid;
3842de962bdSlukem 		code = SLAP_SCHERR_CR_BAD_STRUCT;
3852de962bdSlukem 		goto fail;
3862de962bdSlukem 	}
3872de962bdSlukem 
3882de962bdSlukem 	if( scr->scr_sclass->soc_flags & SLAP_OC_OPERATIONAL ) op++;
3892de962bdSlukem 
3902de962bdSlukem 	code = cr_add_auxiliaries( scr, &op, err );
3912de962bdSlukem 	if ( code != 0 ) goto fail;
3922de962bdSlukem 
3932de962bdSlukem 	code = cr_create_required( scr, &op, err );
3942de962bdSlukem 	if ( code != 0 ) goto fail;
3952de962bdSlukem 
3962de962bdSlukem 	code = cr_create_allowed( scr, &op, err );
3972de962bdSlukem 	if ( code != 0 ) goto fail;
3982de962bdSlukem 
3992de962bdSlukem 	code = cr_create_precluded( scr, &op, err );
4002de962bdSlukem 	if ( code != 0 ) goto fail;
4012de962bdSlukem 
4022de962bdSlukem 	if( user && op ) {
4032de962bdSlukem 		code = SLAP_SCHERR_CR_BAD_AUX;
4042de962bdSlukem 		goto fail;
4052de962bdSlukem 	}
4062de962bdSlukem 
4072de962bdSlukem 	code = cr_insert(scr,err);
4082de962bdSlukem 	if ( code == 0 && rscr )
4092de962bdSlukem 		*rscr = scr;
4102de962bdSlukem 	return code;
4112de962bdSlukem fail:
4122de962bdSlukem 	ch_free( scr );
4132de962bdSlukem 	return code;
4142de962bdSlukem }
4152de962bdSlukem 
4162de962bdSlukem void
cr_unparse(BerVarray * res,ContentRule * start,ContentRule * end,int sys)4172de962bdSlukem cr_unparse( BerVarray *res, ContentRule *start, ContentRule *end, int sys )
4182de962bdSlukem {
4192de962bdSlukem 	ContentRule *cr;
4202de962bdSlukem 	int i, num;
4212de962bdSlukem 	struct berval bv, *bva = NULL, idx;
4222de962bdSlukem 	char ibuf[32];
4232de962bdSlukem 
4242de962bdSlukem 	if ( !start )
4252de962bdSlukem 		start = LDAP_STAILQ_FIRST( &cr_list );
4262de962bdSlukem 
4272de962bdSlukem 	/* count the result size */
4282de962bdSlukem 	i = 0;
4292de962bdSlukem 	for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
4302de962bdSlukem 		if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
4312de962bdSlukem 		i++;
4322de962bdSlukem 		if ( cr == end ) break;
4332de962bdSlukem 	}
4342de962bdSlukem 	if (!i) return;
4352de962bdSlukem 
4362de962bdSlukem 	num = i;
4372de962bdSlukem 	bva = ch_malloc( (num+1) * sizeof(struct berval) );
4382de962bdSlukem 	BER_BVZERO( bva );
4392de962bdSlukem 	idx.bv_val = ibuf;
4402de962bdSlukem 	if ( sys ) {
4412de962bdSlukem 		idx.bv_len = 0;
4422de962bdSlukem 		ibuf[0] = '\0';
4432de962bdSlukem 	}
4442de962bdSlukem 	i = 0;
4452de962bdSlukem 	for ( cr=start; cr; cr=LDAP_STAILQ_NEXT(cr, scr_next)) {
4462de962bdSlukem 		LDAPContentRule lcr, *lcrp;
4472de962bdSlukem 		if ( sys && !(cr->scr_flags & SLAP_CR_HARDCODE)) continue;
4482de962bdSlukem 		if ( cr->scr_oidmacro ) {
4492de962bdSlukem 			lcr = cr->scr_crule;
4502de962bdSlukem 			lcr.cr_oid = cr->scr_oidmacro;
4512de962bdSlukem 			lcrp = &lcr;
4522de962bdSlukem 		} else {
4532de962bdSlukem 			lcrp = &cr->scr_crule;
4542de962bdSlukem 		}
4552de962bdSlukem 		if ( ldap_contentrule2bv( lcrp, &bv ) == NULL ) {
4562de962bdSlukem 			ber_bvarray_free( bva );
4572de962bdSlukem 		}
4582de962bdSlukem 		if ( !sys ) {
4592de962bdSlukem 			idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
4602de962bdSlukem 		}
4612de962bdSlukem 		bva[i].bv_len = idx.bv_len + bv.bv_len;
4622de962bdSlukem 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
4632de962bdSlukem 		strcpy( bva[i].bv_val, ibuf );
4642de962bdSlukem 		strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
4652de962bdSlukem 		i++;
4662de962bdSlukem 		bva[i].bv_val = NULL;
4672de962bdSlukem 		ldap_memfree( bv.bv_val );
4682de962bdSlukem 		if ( cr == end ) break;
4692de962bdSlukem 	}
4702de962bdSlukem 	*res = bva;
4712de962bdSlukem }
4722de962bdSlukem 
4732de962bdSlukem int
cr_schema_info(Entry * e)4742de962bdSlukem cr_schema_info( Entry *e )
4752de962bdSlukem {
4762de962bdSlukem 	AttributeDescription *ad_ditContentRules
4772de962bdSlukem 		= slap_schema.si_ad_ditContentRules;
4782de962bdSlukem 	ContentRule	*cr;
4792de962bdSlukem 
4802de962bdSlukem 	struct berval	val;
4812de962bdSlukem 	struct berval	nval;
4822de962bdSlukem 
4832de962bdSlukem 	LDAP_STAILQ_FOREACH(cr, &cr_list, scr_next) {
4842de962bdSlukem 		if ( ldap_contentrule2bv( &cr->scr_crule, &val ) == NULL ) {
4852de962bdSlukem 			return -1;
4862de962bdSlukem 		}
4872de962bdSlukem 
4882de962bdSlukem #if 0
4892de962bdSlukem 		if( cr->scr_flags & SLAP_CR_HIDE ) continue;
4902de962bdSlukem #endif
4912de962bdSlukem #if 0
4922de962bdSlukem 		Debug( LDAP_DEBUG_TRACE, "Merging cr [%ld] %s\n",
493*cf1d77f7Schristos 	       (long) val.bv_len, val.bv_val );
4942de962bdSlukem #endif
4952de962bdSlukem 
4962de962bdSlukem 		nval.bv_val = cr->scr_oid;
4972de962bdSlukem 		nval.bv_len = strlen(cr->scr_oid);
4982de962bdSlukem 
4992de962bdSlukem 		if( attr_merge_one( e, ad_ditContentRules, &val, &nval ) )
5002de962bdSlukem 		{
5012de962bdSlukem 			return -1;
5022de962bdSlukem 		}
5032de962bdSlukem 		ldap_memfree( val.bv_val );
5042de962bdSlukem 	}
5052de962bdSlukem 	return 0;
5062de962bdSlukem }
507