diff options
-rw-r--r-- | ldap/servers/plugins/cos/cos_cache.c | 75 |
1 files changed, 67 insertions, 8 deletions
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c index db99586c..971249c3 100644 --- a/ldap/servers/plugins/cos/cos_cache.c +++ b/ldap/servers/plugins/cos/cos_cache.c @@ -2367,9 +2367,10 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl /** class of service specifier **/ /* - now we need to iterate through the attributes to discover + Now we need to iterate through the attributes to discover if one fits all the criteria, we'll take the first that does - and blow off the rest + and blow off the rest unless the definition has merge-scheme + set. */ do { @@ -2397,8 +2398,9 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl continue; } - /* is this entry a child of the target tree(s)? */ - while(hit == 0 && pTargetTree) + /* If we haven't found a hit yet, or if we are in merge mode, look for + * hits. We only check if this entry is a child of the target tree(s). */ + while((hit == 0 || merge_mode) && pTargetTree) { { int rc = 0; @@ -2459,16 +2461,73 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl Note: we support one dn only, the result of multiple pointers is undefined */ Slapi_Value *indirectdn; + Slapi_ValueSet *tmp_vals = NULL; int pointer_flags = 0; + int hint = 0; - slapi_valueset_first_value( pAttrSpecs, &indirectdn ); + hint = slapi_valueset_first_value( pAttrSpecs, &indirectdn ); if(props) pointer_flags = *props; - if( indirectdn != NULL && - !cos_cache_follow_pointer( context, (char*)slapi_value_get_string(indirectdn), type, out_attr, test_this, result, pointer_flags)) - hit = 1; + while (indirectdn != NULL) + { + if (cos_cache_follow_pointer( context, (char*)slapi_value_get_string(indirectdn), + type, &tmp_vals, test_this, result, pointer_flags) == 0) + { + hit = 1; + /* If the caller requested values, set them. We need + * to append values when we follow multiple pointers DNs. */ + if (out_attr && tmp_vals) + { + if (*out_attr) + { + Slapi_Attr *attr = NULL; + Slapi_Value *val = NULL; + int idx = 0; + + /* Create an attr to use for duplicate detection. */ + attr = slapi_attr_new(); + slapi_attr_init(attr, type); + + /* Copy any values into out_attr if they don't already exist. */ + for (idx = slapi_valueset_first_value(tmp_vals, &val); + val && (idx != -1); + idx = slapi_valueset_next_value(tmp_vals, idx, &val)) + { + if (slapi_valueset_find(attr, *out_attr, val) == NULL) + { + slapi_valueset_add_value(*out_attr, val); + } + } + + slapi_attr_free(&attr); + slapi_valueset_free(tmp_vals); + tmp_vals = NULL; + } else { + *out_attr = tmp_vals; + tmp_vals = NULL; + } + } + } + + /* If this definition has merge-scheme set, we + * need to follow the rest of the pointers. */ + if (pAttr->attr_cos_merge) + { + hint = slapi_valueset_next_value(pAttrSpecs, hint, &indirectdn); + } else { + indirectdn = NULL; + } + } + + /* If merge-scheme is specified, set merge mode. This will allow + * us to merge in values from other CoS definitions for this attr. */ + if (pAttr->attr_cos_merge) + { + merge_mode = 1; + attr_matched_index = attr_index; + } } else { |