mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-27 03:20:22 +08:00
306 lines
6.7 KiB
C
306 lines
6.7 KiB
C
/*
|
|
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
|
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
|
*/
|
|
/*
|
|
* Copyright (c) 1995 Regents of the University of Michigan.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that this notice is preserved and that due credit is given
|
|
* to the University of Michigan at Ann Arbor. The name of the University
|
|
* may not be used to endorse or promote products derived from this
|
|
* software without specific prior written permission. This software
|
|
* is provided ``as is'' without express or implied warranty.
|
|
*/
|
|
|
|
#include "portable.h"
|
|
|
|
#include "slap.h"
|
|
|
|
int
|
|
modify_add_values(
|
|
Entry *e,
|
|
Modification *mod,
|
|
const char **text,
|
|
char *textbuf, size_t textlen
|
|
)
|
|
{
|
|
int i, j;
|
|
Attribute *a;
|
|
MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
|
|
const char *op;
|
|
|
|
switch( mod->sm_op ) {
|
|
case LDAP_MOD_ADD:
|
|
op = "add";
|
|
break;
|
|
case LDAP_MOD_REPLACE:
|
|
op = "replace";
|
|
break;
|
|
default:
|
|
op = "?";
|
|
assert( 0 );
|
|
}
|
|
|
|
a = attr_find( e->e_attrs, mod->sm_desc );
|
|
|
|
/* check if the values we're adding already exist */
|
|
if( mr == NULL || !mr->smr_match ) {
|
|
if ( a != NULL ) {
|
|
/* do not allow add of additional attribute
|
|
if no equality rule exists */
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/%s: %s: no equality matching rule",
|
|
op, mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
|
|
for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
|
|
/* test asserted values against existing values */
|
|
if( a ) {
|
|
for( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
|
|
int rc = ber_bvcmp( &mod->sm_bvalues[i],
|
|
&a->a_vals[j] );
|
|
|
|
if( rc == 0 ) {
|
|
/* 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* test asserted values against themselves */
|
|
for( j = 0; j < i; j++ ) {
|
|
int rc = ber_bvcmp( &mod->sm_bvalues[i],
|
|
&mod->sm_bvalues[j] );
|
|
|
|
if( rc == 0 ) {
|
|
/* 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
|
|
int rc, match;
|
|
struct berval asserted;
|
|
|
|
rc = value_normalize( mod->sm_desc,
|
|
SLAP_MR_EQUALITY,
|
|
&mod->sm_bvalues[i],
|
|
&asserted,
|
|
text );
|
|
|
|
if( rc != LDAP_SUCCESS ) return rc;
|
|
|
|
if( a ) {
|
|
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
|
|
int rc = value_match( &match, mod->sm_desc, mr,
|
|
SLAP_MR_VALUE_SYNTAX_MATCH,
|
|
&a->a_vals[j], &asserted, text );
|
|
|
|
if( rc == LDAP_SUCCESS && match == 0 ) {
|
|
free( asserted.bv_val );
|
|
return LDAP_TYPE_OR_VALUE_EXISTS;
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( j = 0; j < i; j++ ) {
|
|
int rc = value_match( &match, mod->sm_desc, mr,
|
|
SLAP_MR_VALUE_SYNTAX_MATCH,
|
|
&mod->sm_bvalues[j], &asserted, text );
|
|
|
|
if( rc == LDAP_SUCCESS && match == 0 ) {
|
|
free( asserted.bv_val );
|
|
return LDAP_TYPE_OR_VALUE_EXISTS;
|
|
}
|
|
}
|
|
|
|
free( asserted.bv_val );
|
|
}
|
|
}
|
|
|
|
/* no - add them */
|
|
if( attr_merge( e, mod->sm_desc, mod->sm_bvalues ) != 0 ) {
|
|
/* this should return result of attr_merge */
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/%s: %s: merge error",
|
|
op, mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_OTHER;
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
modify_delete_values(
|
|
Entry *e,
|
|
Modification *mod,
|
|
const char **text,
|
|
char *textbuf, size_t textlen
|
|
)
|
|
{
|
|
int i, j, k, found;
|
|
Attribute *a;
|
|
MatchingRule *mr = mod->sm_desc->ad_type->sat_equality;
|
|
|
|
/* delete the entire attribute */
|
|
if ( mod->sm_bvalues == NULL ) {
|
|
int rc = attr_delete( &e->e_attrs, mod->sm_desc );
|
|
|
|
if( rc != LDAP_SUCCESS ) {
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/delete: %s: no such attribute",
|
|
mod->sm_desc->ad_cname.bv_val );
|
|
rc = LDAP_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
if( mr == NULL || !mr->smr_match ) {
|
|
/* disallow specific attributes from being deleted if
|
|
no equality rule */
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/delete: %s: no equality matching rule",
|
|
mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
|
|
/* delete specific values - find the attribute first */
|
|
if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/delete: %s: no such attribute",
|
|
mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
|
|
/* find each value to delete */
|
|
for ( i = 0; mod->sm_bvalues[i].bv_val != NULL; i++ ) {
|
|
int rc;
|
|
struct berval asserted;
|
|
|
|
rc = value_normalize( mod->sm_desc,
|
|
SLAP_MR_EQUALITY,
|
|
&mod->sm_bvalues[i],
|
|
&asserted,
|
|
text );
|
|
|
|
if( rc != LDAP_SUCCESS ) return rc;
|
|
|
|
found = 0;
|
|
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
|
|
int match;
|
|
int rc = value_match( &match, mod->sm_desc, mr,
|
|
SLAP_MR_VALUE_SYNTAX_MATCH,
|
|
&a->a_vals[j], &asserted, text );
|
|
|
|
if( rc == LDAP_SUCCESS && match != 0 ) {
|
|
continue;
|
|
}
|
|
|
|
/* found a matching value */
|
|
found = 1;
|
|
|
|
/* delete it */
|
|
free( a->a_vals[j].bv_val );
|
|
for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
|
|
a->a_vals[k - 1] = a->a_vals[k];
|
|
}
|
|
a->a_vals[k - 1].bv_val = NULL;
|
|
a->a_vals[k - 1].bv_len = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
free( asserted.bv_val );
|
|
|
|
/* looked through them all w/o finding it */
|
|
if ( ! found ) {
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/delete: %s: no such value",
|
|
mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
}
|
|
|
|
/* if no values remain, delete the entire attribute */
|
|
if ( a->a_vals[0].bv_val == NULL ) {
|
|
if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
|
|
*text = textbuf;
|
|
snprintf( textbuf, textlen,
|
|
"modify/delete: %s: no such attribute",
|
|
mod->sm_desc->ad_cname.bv_val );
|
|
return LDAP_NO_SUCH_ATTRIBUTE;
|
|
}
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
int
|
|
modify_replace_values(
|
|
Entry *e,
|
|
Modification *mod,
|
|
const char **text,
|
|
char *textbuf, size_t textlen
|
|
)
|
|
{
|
|
(void) attr_delete( &e->e_attrs, mod->sm_desc );
|
|
|
|
if ( mod->sm_bvalues ) {
|
|
return modify_add_values( e, mod, text, textbuf, textlen );
|
|
}
|
|
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|
|
void
|
|
slap_mod_free(
|
|
Modification *mod,
|
|
int freeit
|
|
)
|
|
{
|
|
#if 0
|
|
if ( mod->sm_type.bv_val)
|
|
free( mod->sm_type.bv_val );
|
|
#endif
|
|
if ( mod->sm_bvalues != NULL )
|
|
ber_bvarray_free( mod->sm_bvalues );
|
|
|
|
if( freeit )
|
|
free( mod );
|
|
}
|
|
|
|
void
|
|
slap_mods_free(
|
|
Modifications *ml
|
|
)
|
|
{
|
|
Modifications *next;
|
|
|
|
for ( ; ml != NULL; ml = next ) {
|
|
next = ml->sml_next;
|
|
|
|
slap_mod_free( &ml->sml_mod, 0 );
|
|
free( ml );
|
|
}
|
|
}
|
|
|