mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-30 02:19:26 -05:00
ITS#3066: properly detect duplicates
This commit is contained in:
parent
0d2d12cd23
commit
b217659088
3 changed files with 101 additions and 110 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue