-#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;
- BerVarray nvals = NULL, nmods = NULL;
-
- /*
- * FIXME: better do the following
- *
- * - count the existing values
- * - count the new values
- *
- * - if the existing values are less than the new ones {
- * - normalize all the existing values
- * - for each new value {
- * - normalize
- * - check with existing
- * - cross-check with already normalized new vals
- * }
- * } else {
- * - for each new value {
- * - normalize
- * - cross-check with already normalized new vals
- * }
- * - for each existing value {
- * - normalize
- * - check with already normalized new values
- * }
- * }
- *
- * The first case is good when adding a lot of new values,
- * and significantly at first import of values (e.g. adding
- * a new group); the latter case seems to be quite important
- * as well, because it is likely to be the most frequently
- * used when administering the entry. The current
- * implementation will always normalize all the existing
- * values before checking. If there's no duplicate, the
- * performances should not change; they will in case of error.
- */
-
- for ( nummods = 0; mods[ nummods ].bv_val != NULL; nummods++ )
- /* count new values */ ;
-
- if ( vals ) {
- for ( numvals = 0; vals[ numvals ].bv_val != NULL; numvals++ )
- /* count existing values */ ;
-
- if ( numvals < nummods ) {
- nvals = SLAP_CALLOC( numvals + 1, sizeof( struct berval ) );
- if( nvals == NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY,
- "modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
-#endif
- goto return_results;
- }
-
- /* normalize the existing values first */
- for ( j = 0; vals[ j ].bv_val != NULL; j++ ) {
- rc = value_normalize( ad, SLAP_MR_EQUALITY,
- &vals[ j ], &nvals[ j ], text );
-
- /* existing attribute values must normalize */
- assert( rc == LDAP_SUCCESS );
-
- if ( rc != LDAP_SUCCESS ) {
- nvals[ j ].bv_val = NULL;
- goto return_results;
- }
- }
- nvals[ j ].bv_val = NULL;
- }
- }
-
- /*
- * If the existing values are less than the new values,
- * it is more convenient to normalize all the existing
- * values and test each new value against them first,
- * then to other already normalized values
- */
- nmods = SLAP_CALLOC( nummods + 1, sizeof( struct berval ) );
- if ( nmods == NULL ) {
-#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
-#else
- Debug( LDAP_DEBUG_ANY,
- "modify_check_duplicates: SLAP_CALLOC failed", 0, 0, 0 );
-#endif
- goto return_results;
- }
-
- for ( i = 0; mods[ i ].bv_val != NULL; i++ ) {
- rc = value_normalize( ad, SLAP_MR_EQUALITY,
- &mods[ i ], &nmods[ i ], text );
-
- if ( rc != LDAP_SUCCESS ) {
- nmods[ i ].bv_val = NULL;
- goto return_results;
- }
-
- if ( numvals > 0 && numvals < nummods ) {
- for ( matched = 0, j = 0; nvals[ j ].bv_val; j++ ) {
- int match;
-
- rc = (*mr->smr_match)( &match,
- SLAP_MR_VALUE_SYNTAX_MATCH,
- ad->ad_type->sat_syntax,
- mr, &nmods[ i ], &nvals[ j ] );
- if ( rc != LDAP_SUCCESS ) {
- nmods[ i + 1 ].bv_val = NULL;
- *text = textbuf;
- snprintf( textbuf, textlen,
- "%s: matching rule failed",
- ad->ad_cname.bv_val );
- goto return_results;
- }
-
- if ( match == 0 ) {
- if ( permissive ) {
- matched++;
- continue;
- }
- *text = textbuf;
- snprintf( textbuf, textlen,
- "%s: value #%d provided more than once",
- ad->ad_cname.bv_val, i );
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- nmods[ i + 1 ].bv_val = NULL;
- goto return_results;
- }
- }
-
- if ( permissive && matched == j ) {
- nmods[ i + 1 ].bv_val = NULL;
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- goto return_results;
- }
- }
-
- for ( matched = 0, j = 0; j < i; j++ ) {
- int match;
-
- rc = (*mr->smr_match)( &match,
- SLAP_MR_VALUE_SYNTAX_MATCH,
- ad->ad_type->sat_syntax,
- mr, &nmods[ i ], &nmods[ j ] );
- if ( rc != LDAP_SUCCESS ) {
- nmods[ i + 1 ].bv_val = NULL;
- *text = textbuf;
- snprintf( textbuf, textlen,
- "%s: matching rule failed",
- ad->ad_cname.bv_val );
- goto return_results;
- }
-
- if ( match == 0 ) {
- if ( permissive ) {
- matched++;
- continue;
- }
- *text = textbuf;
- snprintf( textbuf, textlen,
- "%s: value #%d provided more than once",
- ad->ad_cname.bv_val, j );
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- nmods[ i + 1 ].bv_val = NULL;
- goto return_results;
- }
- }
-
- if ( permissive && matched == j ) {
- nmods[ i + 1 ].bv_val = NULL;
- rc = LDAP_TYPE_OR_VALUE_EXISTS;
- goto return_results;
- }
- }
- nmods[ i ].bv_val = NULL;