ITS#3066: properly detect duplicates

This commit is contained in:
Kurt Zeilenga 2004-04-08 06:44:50 +00:00
parent 0d2d12cd23
commit b217659088
3 changed files with 101 additions and 110 deletions

View file

@ -112,8 +112,7 @@ do_modify(
tmp.sml_nvalues = NULL;
if ( ber_scanf( op->o_ber, "{i{m[W]}}", &mop,
&tmp.sml_type, &tmp.sml_values )
== LBER_ERROR )
&tmp.sml_type, &tmp.sml_values ) == LBER_ERROR )
{
send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR,
"decoding modlist error" );
@ -766,6 +765,64 @@ int slap_mods_check(
ml->sml_nvalues[nvals].bv_val = NULL;
ml->sml_nvalues[nvals].bv_len = 0;
}
if( nvals ) {
/* check for duplicates */
int i, j;
MatchingRule *mr = ad->ad_type->sat_equality;
/* check if the values we're adding already exist */
if( mr == NULL || !mr->smr_match ) {
for ( i = 1; ml->sml_values[i].bv_val != NULL; i++ ) {
/* test asserted values against themselves */
for( j = 0; j < i; j++ ) {
if ( bvmatch( &ml->sml_values[i],
&ml->sml_values[j] ) )
{
/* value exists already */
snprintf( textbuf, textlen,
"%s: value #%d provided more than once",
ml->sml_desc->ad_cname.bv_val, j );
*text = textbuf;
return LDAP_TYPE_OR_VALUE_EXISTS;
}
}
}
} else {
int rc = LDAP_SUCCESS;
int match;
for ( i = 1; ml->sml_values[i].bv_val != NULL; i++ ) {
/* test asserted values against themselves */
for( j = 0; j < i; j++ ) {
rc = value_match( &match, ml->sml_desc, mr,
SLAP_MR_EQUALITY
| SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
ml->sml_nvalues
? &ml->sml_nvalues[i]
: &ml->sml_values[i],
ml->sml_nvalues
? &ml->sml_nvalues[j]
: &ml->sml_values[j],
text );
if ( rc == LDAP_SUCCESS && match == 0 ) {
/* value exists already */
snprintf( textbuf, textlen,
"%s: value #%d provided more than once",
ml->sml_desc->ad_cname.bv_val, j );
*text = textbuf;
return LDAP_TYPE_OR_VALUE_EXISTS;
}
}
}
if ( rc != LDAP_SUCCESS ) return rc;
}
}
}
}

View file

@ -29,22 +29,6 @@
#include "slap.h"
int
modify_check_duplicates(
AttributeDescription *ad,
MatchingRule *mr,
BerVarray vals,
BerVarray mods,
int permissive,
const char **text,
char *textbuf, size_t textlen )
{
int i, j, numvals = 0, nummods,
rc = LDAP_SUCCESS, matched;
/* this function is no longer used */
return rc;
}
int
modify_add_values(
Entry *e,
@ -91,32 +75,14 @@ modify_add_values(
return LDAP_INAPPROPRIATE_MATCHING;
}
for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
/* test asserted values against existing values */
if( a ) {
for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
if ( bvmatch( &mod->sm_bvalues[i], &a->a_vals[j] ) ) {
if ( permissive ) {
matched++;
continue;
}
/* value exists already */
*text = textbuf;
snprintf( textbuf, textlen,
"modify/%s: %s: value #%i already exists",
op, mod->sm_desc->ad_cname.bv_val, j );
return LDAP_TYPE_OR_VALUE_EXISTS;
for( matched = 0, j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
if ( bvmatch( &mod->sm_values[i], &a->a_vals[j] ) ) {
if ( permissive ) {
matched++;
continue;
}
}
if ( permissive && matched == j ) {
/* values already exist; do nothing */
return LDAP_SUCCESS;
}
}
/* test asserted values against themselves */
for( j = 0; j < i; j++ ) {
if ( bvmatch( &mod->sm_bvalues[i], &mod->sm_bvalues[j] ) ) {
/* value exists already */
*text = textbuf;
snprintf( textbuf, textlen,
@ -125,77 +91,52 @@ modify_add_values(
return LDAP_TYPE_OR_VALUE_EXISTS;
}
}
if ( permissive && matched == j ) {
/* values already exist; do nothing */
return LDAP_SUCCESS;
}
}
} else {
} else if ( a != NULL ) {
/* no normalization is done in this routine nor
* in the matching routines called by this routine.
* values are now normalized once on input to the
* server (whether from LDAP or from the underlying
* database).
* This should outperform the old code. No numbers
* are available yet.
*/
int rc;
if ( mod->sm_bvalues[1].bv_val == 0 ) {
if ( a != NULL ) {
int i;
for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) {
int match;
for ( matched = 0, i = 0; a->a_vals[ i ].bv_val; i++ ) {
int match;
if( mod->sm_nvalues ) {
rc = value_match( &match, mod->sm_desc, mr,
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
&a->a_nvals[i], &mod->sm_nvalues[0], text );
} else {
rc = value_match( &match, mod->sm_desc, mr,
SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
&a->a_vals[i], &mod->sm_values[0], text );
}
if( mod->sm_nvalues ) {
rc = value_match( &match, mod->sm_desc, mr,
SLAP_MR_EQUALITY
| SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
| SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
&a->a_nvals[i],
&mod->sm_nvalues[0],
text );
} else {
rc = value_match( &match, mod->sm_desc, mr,
SLAP_MR_EQUALITY
| SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
&a->a_vals[i],
&mod->sm_values[0],
text );
}
if( rc == LDAP_SUCCESS && match == 0 ) {
if ( permissive ) {
matched++;
continue;
}
*text = textbuf;
snprintf( textbuf, textlen,
"modify/%s: %s: value #0 already exists",
op, mod->sm_desc->ad_cname.bv_val );
return LDAP_TYPE_OR_VALUE_EXISTS;
}
}
if ( permissive && matched == i ) {
/* values already exist; do nothing */
return LDAP_SUCCESS;
if( rc == LDAP_SUCCESS && match == 0 ) {
if ( permissive ) {
matched++;
continue;
}
*text = textbuf;
snprintf( textbuf, textlen,
"modify/%s: %s: value #0 already exists",
op, mod->sm_desc->ad_cname.bv_val );
return LDAP_TYPE_OR_VALUE_EXISTS;
}
} else {
rc = modify_check_duplicates( mod->sm_desc, mr,
a ? a->a_vals : NULL, mod->sm_bvalues,
permissive, text, textbuf, textlen );
if ( permissive && rc == LDAP_TYPE_OR_VALUE_EXISTS ) {
return LDAP_SUCCESS;
}
if ( rc != LDAP_SUCCESS ) {
return rc;
}
}
if ( permissive && matched == i ) {
/* values already exist; do nothing */
return LDAP_SUCCESS;
}
}
@ -218,8 +159,7 @@ modify_delete_values(
Modification *mod,
int permissive,
const char **text,
char *textbuf, size_t textlen
)
char *textbuf, size_t textlen )
{
int i, j, k, rc = LDAP_SUCCESS;
Attribute *a;
@ -233,7 +173,7 @@ modify_delete_values(
*/
/* delete the entire attribute */
if ( mod->sm_bvalues == NULL ) {
if ( mod->sm_values == NULL ) {
rc = attr_delete( &e->e_attrs, mod->sm_desc );
if( permissive ) {
@ -270,7 +210,6 @@ modify_delete_values(
return LDAP_NO_SUCH_ATTRIBUTE;
}
for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
int found = 0;
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
@ -380,7 +319,7 @@ modify_replace_values(
{
(void) attr_delete( &e->e_attrs, mod->sm_desc );
if ( mod->sm_bvalues ) {
if ( mod->sm_values ) {
return modify_add_values( e, mod, permissive, text, textbuf, textlen );
}
@ -406,11 +345,10 @@ modify_increment_values(
return LDAP_NO_SUCH_ATTRIBUTE;
}
if ( !strcmp( a->a_desc->ad_type->sat_syntax_oid, SLAPD_INTEGER_SYNTAX )) {
int i;
char str[sizeof(long)*3 + 2]; /* overly long */
long incr = atol( mod->sm_bvalues[0].bv_val );
long incr = atol( mod->sm_values[0].bv_val );
/* treat zero and errors as a no-op */
if( incr == 0 ) {

View file

@ -688,10 +688,6 @@ LDAP_SLAPD_F( int ) slap_mods_opattrs(
/*
* mods.c
*/
LDAP_SLAPD_F( int ) modify_check_duplicates(
AttributeDescription *ad, MatchingRule *mr,
BerVarray vals, BerVarray mods, int permissive,
const char **text, char *textbuf, size_t textlen );
LDAP_SLAPD_F( int ) modify_add_values( Entry *e,
Modification *mod,
int permissive,