From: Pierangelo Masarati Date: Tue, 14 Aug 2007 11:46:29 +0000 (+0000) Subject: merge attributes as required after mapping; avoid objectClass duplicates (ITS#5091) X-Git-Tag: OPENLDAP_REL_ENG_2_4_MP~221 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5ec09e2f0a5823f94ca80561f96b4f82a7a2ad81;p=openldap merge attributes as required after mapping; avoid objectClass duplicates (ITS#5091) --- diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 1f508b19f7..dc59751975 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -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; diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index 82a15e00de..61523b398c 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -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; }