]> git.sur5r.net Git - openldap/commitdiff
merge attributes as required after mapping; avoid objectClass duplicates (ITS#5091)
authorPierangelo Masarati <ando@openldap.org>
Tue, 14 Aug 2007 11:46:29 +0000 (11:46 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 14 Aug 2007 11:46:29 +0000 (11:46 +0000)
servers/slapd/back-meta/search.c
servers/slapd/overlays/rwm.c

index 1f508b19f74683f490c630d73812bbcc319874b8..dc597519758ba0ff205ec08f1cc3cd54083fb2c8 100644 (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;
index 82a15e00de00bc7edaeafd01ff37b1aaf0d62758..61523b398ce88c27155f267473c655824b3168c9 100644 (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;
 }