{
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;
( 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;
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 ) {
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 );
}
}
/*
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;
int rc;
Attribute **ap;
int isupdate;
+ int check_duplicate_attrs = 0;
/*
* Rewrite the dn attrs, if needed
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 ) )
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 */ ;
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++;
}
}
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] ) {
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 */
}
}
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;
}