summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldap/servers/plugins/cos/cos_cache.c75
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
{