mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-28 02:29:34 -05:00
merge attributes as required after mapping; avoid objectClass duplicates (ITS#5091)
This commit is contained in:
parent
1f3d88f32b
commit
5ec09e2f0a
2 changed files with 131 additions and 4 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue