/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2008 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
}
v2 = &(*vals)[n];
- for ( ; !BER_BVISNULL( addvals ); v2++, addvals++ ) {
+ for ( n = 0 ; n < nn; v2++, addvals++ ) {
ber_dupbv( v2, addvals );
if ( BER_BVISNULL( v2 ) ) break;
}
rc = (mr->smr_syntax->ssyn_pretty)( mr->smr_syntax, in, &pval, ctx );
in = &pval;
- } else {
+ } else if ( mr->smr_syntax->ssyn_validate ) {
rc = (mr->smr_syntax->ssyn_validate)( mr->smr_syntax, in );
+
+ } else {
+ *text = "inappropriate matching request";
+ return LDAP_INAPPROPRIATE_MATCHING;
}
if( rc != LDAP_SUCCESS ) {
return LDAP_INAPPROPRIATE_MATCHING;
}
- assert(SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( flags ));
+ assert( SLAP_IS_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH( flags ) != 0 );
if( !SLAP_IS_MR_ASSERTED_VALUE_NORMALIZED_MATCH( flags ) &&
mr->smr_normalize )
{
rc = (mr->smr_normalize)(
flags & (SLAP_MR_TYPE_MASK|SLAP_MR_SUBTYPE_MASK|SLAP_MR_VALUE_OF_SYNTAX),
- ad ? ad->ad_type->sat_syntax : NULL,
+ ad->ad_type->sat_syntax,
mr, val, &nval, ctx );
if( rc != LDAP_SUCCESS ) {
/* assign new indexes to an attribute's ordered values */
void
-ordered_value_renumber( Attribute *a, int vals )
+ordered_value_renumber( Attribute *a )
{
char *ptr, ibuf[64]; /* many digits */
struct berval ibv, tmp, vtmp;
ibv.bv_val = ibuf;
- for (i=0; i<vals; i++) {
+ for (i=0; i<a->a_numvals; i++) {
ibv.bv_len = sprintf(ibv.bv_val, "{%d}", i);
vtmp = a->a_vals[i];
if ( vtmp.bv_val[0] == '{' ) {
- ptr = strchr(vtmp.bv_val, '}') + 1;
+ ptr = ber_bvchr(&vtmp, '}');
+ assert( ptr != NULL );
+ ++ptr;
vtmp.bv_len -= ptr - vtmp.bv_val;
vtmp.bv_val = ptr;
}
if ( a->a_nvals && a->a_nvals != a->a_vals ) {
vtmp = a->a_nvals[i];
if ( vtmp.bv_val[0] == '{' ) {
- ptr = strchr(vtmp.bv_val, '}') + 1;
+ ptr = ber_bvchr(&vtmp, '}');
+ assert( ptr != NULL );
+ ++ptr;
vtmp.bv_len -= ptr - vtmp.bv_val;
vtmp.bv_val = ptr;
}
if ( a->a_vals[i].bv_val[0] == '{' ) {
char *ptr;
index = 1;
- ptr = strchr( a->a_vals[i].bv_val, '}' );
- if ( !ptr || !ptr[1] )
+ ptr = ber_bvchr( &a->a_vals[i], '}' );
+ if ( !ptr )
return LDAP_INVALID_SYNTAX;
if ( noindex )
return LDAP_INVALID_SYNTAX;
a->a_nvals = ch_malloc( (vals+1)*sizeof(struct berval));
BER_BVZERO(a->a_nvals+vals);
for ( i=0; i<vals; i++ ) {
- ptr = strchr(a->a_vals[i].bv_val, '}') + 1;
+ char *ptr = ber_bvchr(&a->a_vals[i], '}') + 1;
a->a_nvals[i].bv_len = a->a_vals[i].bv_len -
(ptr - a->a_vals[i].bv_val);
a->a_nvals[i].bv_val = ch_malloc( a->a_nvals[i].bv_len + 1);
}
} else {
for ( i=0; i<vals; i++ ) {
- ptr = strchr(a->a_nvals[i].bv_val, '}') + 1;
+ char *ptr = ber_bvchr(&a->a_nvals[i], '}') + 1;
a->a_nvals[i].bv_len -= ptr - a->a_nvals[i].bv_val;
strcpy(a->a_nvals[i].bv_val, ptr);
}
#endif
indexes = ch_malloc( vals * sizeof(int) );
- for ( i=0; i<vals; i++)
- indexes[i] = strtol(a->a_vals[i].bv_val+1, NULL, 0);
+ for ( i=0; i<vals; i++) {
+ char *ptr;
+ indexes[i] = strtol(a->a_vals[i].bv_val+1, &ptr, 0);
+ if ( *ptr != '}' ) {
+ ch_free( indexes );
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
/* Insertion sort */
for ( i=1; i<vals; i++ ) {
if ( indexes[0] != 0 || indexes[vals-1] != vals-1 ) {
renumber = 1;
}
+ ch_free( indexes );
} else {
renumber = 1;
}
if ( do_renumber && renumber )
- ordered_value_renumber( a, vals );
+ ordered_value_renumber( a );
return 0;
}
+/*
+ * wrapper for validate function
+ * uses the validate function of the syntax after removing
+ * the index, if allowed and present
+ */
+int
+ordered_value_validate(
+ AttributeDescription *ad,
+ struct berval *in,
+ int mop )
+{
+ struct berval bv = *in;
+
+ assert( ad->ad_type->sat_syntax != NULL );
+ assert( ad->ad_type->sat_syntax->ssyn_validate != NULL );
+
+ if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
+
+ /* Skip past the assertion index */
+ if ( bv.bv_val[0] == '{' ) {
+ char *ptr;
+
+ ptr = ber_bvchr( &bv, '}' );
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
+
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv.bv_len -= ptr - bv.bv_val;
+ bv.bv_val = ptr;
+ in = &bv;
+ /* If deleting by index, just succeed */
+ if ( mop == LDAP_MOD_DELETE && BER_BVISEMPTY( &bv ) ) {
+ return LDAP_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return ad->ad_type->sat_syntax->ssyn_validate( ad->ad_type->sat_syntax, in );
+}
+
+/*
+ * wrapper for pretty function
+ * uses the pretty function of the syntax after removing
+ * the index, if allowed and present; in case, it's prepended
+ * to the pretty value
+ */
+int
+ordered_value_pretty(
+ AttributeDescription *ad,
+ struct berval *val,
+ struct berval *out,
+ void *ctx )
+{
+ struct berval bv = *val,
+ idx = BER_BVNULL;
+ int rc;
+
+ assert( ad->ad_type->sat_syntax != NULL );
+ assert( ad->ad_type->sat_syntax->ssyn_pretty != NULL );
+ assert( val != NULL );
+ assert( out != NULL );
+
+ if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
+
+ /* Skip past the assertion index */
+ if ( bv.bv_val[0] == '{' ) {
+ char *ptr;
+
+ ptr = ber_bvchr( &bv, '}' );
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
+
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
+
+ idx = bv;
+ idx.bv_len = ptr - bv.bv_val;
+
+ bv.bv_len -= idx.bv_len;
+ bv.bv_val = ptr;
+
+ val = &bv;
+ }
+ }
+ }
+ }
+
+ rc = ad->ad_type->sat_syntax->ssyn_pretty( ad->ad_type->sat_syntax, val, out, ctx );
+
+ if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &idx ) ) {
+ bv = *out;
+
+ out->bv_len = idx.bv_len + bv.bv_len;
+ out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx );
+
+ AC_MEMCPY( out->bv_val, idx.bv_val, idx.bv_len );
+ AC_MEMCPY( &out->bv_val[ idx.bv_len ], bv.bv_val, bv.bv_len + 1 );
+
+ ber_memfree_x( bv.bv_val, ctx );
+ }
+
+ return rc;
+}
+
+/*
+ * wrapper for normalize function
+ * uses the normalize function of the attribute description equality rule
+ * after removing the index, if allowed and present; in case, it's
+ * prepended to the value
+ */
+int
+ordered_value_normalize(
+ slap_mask_t usage,
+ AttributeDescription *ad,
+ MatchingRule *mr,
+ struct berval *val,
+ struct berval *normalized,
+ void *ctx )
+{
+ struct berval bv = *val,
+ idx = BER_BVNULL;
+ int rc;
+
+ assert( ad->ad_type->sat_equality != NULL );
+ assert( ad->ad_type->sat_equality->smr_normalize != NULL );
+ assert( val != NULL );
+ assert( normalized != NULL );
+
+ if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
+
+ /* Skip past the assertion index */
+ if ( bv.bv_val[ 0 ] == '{' ) {
+ char *ptr;
+
+ ptr = ber_bvchr( &bv, '}' );
+ if ( ptr != NULL ) {
+ struct berval ns;
+
+ ns.bv_val = bv.bv_val + 1;
+ ns.bv_len = ptr - ns.bv_val;
+
+ if ( numericStringValidate( NULL, &ns ) == LDAP_SUCCESS ) {
+ ptr++;
+
+ idx = bv;
+ idx.bv_len = ptr - bv.bv_val;
+
+ bv.bv_len -= idx.bv_len;
+ bv.bv_val = ptr;
+
+ /* validator will already prevent this for Adds */
+ if ( BER_BVISEMPTY( &bv )) {
+ ber_dupbv_x( normalized, &idx, ctx );
+ return LDAP_SUCCESS;
+ }
+ val = &bv;
+ }
+ }
+ }
+ }
+
+ rc = ad->ad_type->sat_equality->smr_normalize( usage,
+ ad->ad_type->sat_syntax, mr, val, normalized, ctx );
+
+ if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &idx ) ) {
+ bv = *normalized;
+
+ normalized->bv_len = idx.bv_len + bv.bv_len;
+ normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
+
+ AC_MEMCPY( normalized->bv_val, idx.bv_val, idx.bv_len );
+ AC_MEMCPY( &normalized->bv_val[ idx.bv_len ], bv.bv_val, bv.bv_len + 1 );
+
+ ber_memfree_x( bv.bv_val, ctx );
+ }
+
+ return rc;
+}
+
/* A wrapper for value match, handles Equality matches for attributes
* with ordered values.
*/
*/
if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) {
char *ptr;
- struct berval iv;
+ struct berval ns1 = BER_BVNULL, ns2 = BER_BVNULL;
bv1 = *v1;
bv2 = *v2;
- iv = bv2;
/* Skip past the assertion index */
if ( bv2.bv_val[0] == '{' ) {
- ptr = strchr( bv2.bv_val, '}' ) + 1;
- bv2.bv_len -= ptr - bv2.bv_val;
- bv2.bv_val = ptr;
- v2 = &bv2;
+ ptr = ber_bvchr( &bv2, '}' );
+ if ( ptr != NULL ) {
+ ns2.bv_val = bv2.bv_val + 1;
+ ns2.bv_len = ptr - ns2.bv_val;
+
+ if ( numericStringValidate( NULL, &ns2 ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv2.bv_len -= ptr - bv2.bv_val;
+ bv2.bv_val = ptr;
+ v2 = &bv2;
+ }
+ }
}
- if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
- if ( iv.bv_val[0] == '{' && bv1.bv_val[0] == '{' ) {
- /* compare index values first */
- long l1, l2, ret;
-
- l1 = strtol( bv1.bv_val+1, NULL, 0 );
- l2 = strtol( iv.bv_val+1, &ptr, 0 );
+ /* Skip past the attribute index */
+ if ( bv1.bv_val[0] == '{' ) {
+ ptr = ber_bvchr( &bv1, '}' );
+ if ( ptr != NULL ) {
+ ns1.bv_val = bv1.bv_val + 1;
+ ns1.bv_len = ptr - ns1.bv_val;
+
+ if ( numericStringValidate( NULL, &ns1 ) == LDAP_SUCCESS ) {
+ ptr++;
+ bv1.bv_len -= ptr - bv1.bv_val;
+ bv1.bv_val = ptr;
+ v1 = &bv1;
+ }
+ }
+ }
- ret = l1 - l2;
+ if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( flags )) {
+ if ( !BER_BVISNULL( &ns2 ) && !BER_BVISNULL( &ns1 ) ) {
+ /* compare index values first */
+ (void)octetStringOrderingMatch( match, 0, NULL, NULL, &ns1, &ns2 );
/* If not equal, or we're only comparing the index,
* return result now.
*/
- if ( ret || ptr == iv.bv_val + iv.bv_len - 1 ) {
- *match = ( ret < 0 ) ? -1 : (ret > 0 );
+ if ( *match != 0 || BER_BVISEMPTY( &bv2 ) ) {
return LDAP_SUCCESS;
}
}
}
- /* Skip past the attribute index */
- if ( bv1.bv_val[0] == '{' ) {
- ptr = strchr( bv1.bv_val, '}' ) + 1;
- bv1.bv_len -= ptr - bv1.bv_val;
- bv1.bv_val = ptr;
- v1 = &bv1;
- }
+
}
if ( !mr || !mr->smr_match ) {
vnum = i;
if ( a ) {
- for (i=0; !BER_BVISNULL( a->a_vals+i ); i++) ;
- anum = i;
ordered_value_sort( a, 0 );
} else {
Attribute **ap;
- anum = 0;
for ( ap=&e->e_attrs; *ap; ap = &(*ap)->a_next ) ;
- a = ch_calloc( 1, sizeof(Attribute) );
- a->a_desc = ad;
+ a = attr_alloc( ad );
*ap = a;
}
+ anum = a->a_numvals;
new = ch_malloc( (anum+vnum+1) * sizeof(struct berval));
- if ( a->a_nvals && a->a_nvals != a->a_vals ) {
+
+ /* sanity check: if normalized modifications come in, either
+ * no values are present or normalized existing values differ
+ * from non-normalized; if no normalized modifications come in,
+ * either no values are present or normalized existing values
+ * don't differ from non-normalized */
+ if ( nvals != NULL ) {
+ assert( nvals != vals );
+ assert( a->a_nvals == NULL || a->a_nvals != a->a_vals );
+
+ } else {
+ assert( a->a_nvals == NULL || a->a_nvals == a->a_vals );
+ }
+
+ if ( ( a->a_nvals && a->a_nvals != a->a_vals ) || nvals != NULL ) {
nnew = ch_malloc( (anum+vnum+1) * sizeof(struct berval));
/* Shouldn't happen... */
if ( !nvals ) nvals = vals;
}
if ( anum ) {
AC_MEMCPY( new, a->a_vals, anum * sizeof(struct berval));
- if ( nnew )
+ if ( nnew && a->a_nvals )
AC_MEMCPY( nnew, a->a_nvals, anum * sizeof(struct berval));
}
for (i=0; i<vnum; i++) {
+ char *next;
+
k = -1;
if ( vals[i].bv_val[0] == '{' ) {
- k = strtol( vals[i].bv_val+1, NULL, 0 );
+ /* FIXME: strtol() could go past end... */
+ k = strtol( vals[i].bv_val + 1, &next, 0 );
+ if ( next == vals[i].bv_val + 1 ||
+ next[ 0 ] != '}' ||
+ next - vals[i].bv_val > vals[i].bv_len )
+ {
+ ch_free( nnew );
+ ch_free( new );
+ return -1;
+ }
if ( k > anum ) k = -1;
}
/* No index, or index is greater than current number of
a->a_nvals = a->a_vals;
}
- ordered_value_renumber( a, anum );
+ a->a_numvals = anum;
+ ordered_value_renumber( a );
return 0;
}