merge attributes as required after mapping; avoid objectClass duplicates (ITS#5091)

This commit is contained in:
Pierangelo Masarati 2007-08-14 11:46:29 +00:00
parent 1f3d88f32b
commit 5ec09e2f0a
2 changed files with 131 additions and 4 deletions

View file

@ -1760,6 +1760,7 @@ meta_send_entry(
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
struct berval a, mapped;
int check_duplicate_attrs = 0;
Entry ent = { 0 };
BerElement ber = *e->lm_ber;
Attribute *attr, **attrp;
@ -1826,6 +1827,10 @@ meta_send_entry(
( void )ber_scanf( &ber, "x" /* [W] */ );
continue;
}
if ( mapped.bv_val != a.bv_val ) {
/* will need to check for duplicate attrs */
check_duplicate_attrs++;
}
attr = attr_alloc( NULL );
if ( attr == NULL ) {
continue;
@ -1898,6 +1903,7 @@ meta_send_entry(
ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
bv, &mapped, BACKLDAP_REMAP );
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
remove_oc:;
free( bv->bv_val );
BER_BVZERO( bv );
if ( --last < 0 ) {
@ -1908,8 +1914,23 @@ meta_send_entry(
bv--;
} else if ( mapped.bv_val != bv->bv_val ) {
free( bv->bv_val );
ber_dupbv( bv, &mapped );
int i;
for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
if ( &attr->a_vals[ i ] == bv ) {
continue;
}
if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
break;
}
}
if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
goto remove_oc;
}
ber_bvreplace( bv, &mapped );
}
}
/*
@ -1998,6 +2019,47 @@ meta_send_entry(
next_attr:;
}
/* only check if some mapping occurred */
if ( check_duplicate_attrs ) {
Attribute **ap;
for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
Attribute **tap;
for ( tap = &(*ap)->a_next; *tap != NULL; ) {
if ( (*tap)->a_desc == (*ap)->a_desc ) {
Entry e = { 0 };
Modification mod = { 0 };
const char *text = NULL;
char textbuf[ SLAP_TEXT_BUFLEN ];
Attribute *next = (*tap)->a_next;
BER_BVSTR( &e.e_name, "" );
BER_BVSTR( &e.e_nname, "" );
e.e_attrs = *ap;
mod.sm_op = LDAP_MOD_ADD;
mod.sm_desc = (*ap)->a_desc;
mod.sm_type = mod.sm_desc->ad_cname;
mod.sm_values = (*tap)->a_vals;
mod.sm_nvalues = (*tap)->a_nvals;
(void)modify_add_values( &e, &mod,
/* permissive */ 1,
&text, textbuf, sizeof( textbuf ) );
/* should not insert new attrs! */
assert( e.e_attrs == *ap );
attr_free( *tap );
*tap = next;
} else {
tap = &(*tap)->a_next;
}
}
}
}
ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
e, &rs->sr_ctrls );
rs->sr_entry = &ent;

View file

@ -986,6 +986,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
int rc;
Attribute **ap;
int isupdate;
int check_duplicate_attrs = 0;
/*
* Rewrite the dn attrs, if needed
@ -1010,7 +1011,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
for ( ap = a_first; *ap; ) {
struct ldapmapping *mapping = NULL;
int drop_missing;
int last=-1;
int last = -1;
Attribute *a;
if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
@ -1042,7 +1043,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
mapping->m_dst_ad->ad_type->sat_equality &&
mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
{
int i=0;
int i = 0;
for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
/* just count */ ;
@ -1070,8 +1071,12 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
BER_BVZERO( &(*ap)->a_nvals[i] );
}
}
/* rewrite the attribute description */
(*ap)->a_desc = mapping->m_dst_ad;
/* will need to check for duplicate attrs */
check_duplicate_attrs++;
}
}
@ -1110,6 +1115,7 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
remove_oc:;
ch_free( bv[0].bv_val );
BER_BVZERO( &bv[0] );
if ( &(*ap)->a_vals[last] > &bv[0] ) {
@ -1120,12 +1126,32 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
bv--;
} else if ( mapped.bv_val != bv[0].bv_val ) {
int i;
for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
if ( &(*ap)->a_vals[ i ] == bv ) {
continue;
}
if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
break;
}
}
if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
goto remove_oc;
}
/*
* FIXME: after LBER_FREEing
* the value is replaced by
* ch_alloc'ed memory
*/
ber_bvreplace( &bv[0], &mapped );
/* FIXME: will need to check
* if the structuralObjectClass
* changed */
}
}
@ -1170,6 +1196,45 @@ cleanup_attr:;
attr_free( a );
}
/* only check if some mapping occurred */
if ( check_duplicate_attrs ) {
for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
Attribute **tap;
for ( tap = &(*ap)->a_next; *tap != NULL; ) {
if ( (*tap)->a_desc == (*ap)->a_desc ) {
Entry e = { 0 };
Modification mod = { 0 };
const char *text = NULL;
char textbuf[ SLAP_TEXT_BUFLEN ];
Attribute *next = (*tap)->a_next;
BER_BVSTR( &e.e_name, "" );
BER_BVSTR( &e.e_nname, "" );
e.e_attrs = *ap;
mod.sm_op = LDAP_MOD_ADD;
mod.sm_desc = (*ap)->a_desc;
mod.sm_type = mod.sm_desc->ad_cname;
mod.sm_values = (*tap)->a_vals;
mod.sm_nvalues = (*tap)->a_nvals;
(void)modify_add_values( &e, &mod,
/* permissive */ 1,
&text, textbuf, sizeof( textbuf ) );
/* should not insert new attrs! */
assert( e.e_attrs == *ap );
attr_free( *tap );
*tap = next;
} else {
tap = &(*tap)->a_next;
}
}
}
}
return 0;
}