Bläddra i källkod

Merge branch 'ticket159'

Mark Reynolds 14 år sedan
förälder
incheckning
3e845faf57
2 ändrade filer med 245 tillägg och 4 borttagningar
  1. 244 4
      ldap/servers/plugins/mep/mep.c
  2. 1 0
      ldap/servers/plugins/mep/mep.h

+ 244 - 4
ldap/servers/plugins/mep/mep.c

@@ -43,6 +43,7 @@
  * Managed Entries Plug-in
  */
 #include "mep.h"
+#include "slapi-private.h"
 
 
 /*
@@ -117,6 +118,9 @@ static int mep_parse_mapped_attr(char *mapping, Slapi_Entry *origin,
 static int mep_is_managed_entry(Slapi_Entry *e);
 static int mep_is_mapped_attr(Slapi_Entry *template, char *type);
 static int mep_has_tombstone_value(Slapi_Entry * e);
+static int mep_parse_mapped_origin_attr(char *mapping, char **origin_type);
+static int mep_is_mapped_origin_attr(char **vals, char *type);
+static char** mep_extract_origin_attrs(Slapi_Entry *entry);
 
 /*
  * Config cache locking functions
@@ -657,6 +661,7 @@ mep_parse_config_entry(Slapi_Entry * e, int apply, Slapi_PBlock *pb)
             goto bail;
         }
 
+        /* Check the schema */
         if (slapi_entry_schema_check(NULL, test_entry) != 0) {
             slapi_log_error(SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
                             "mep_parse_config_entry: Test managed "
@@ -669,6 +674,11 @@ mep_parse_config_entry(Slapi_Entry * e, int apply, Slapi_PBlock *pb)
             goto bail;
         }
 
+        /*
+         * Extract the origin attrs from the template entry
+         */
+        entry->origin_attrs = mep_extract_origin_attrs(entry->template_entry);
+
         /* Dispose of the test entry */
         slapi_entry_free(test_entry);
 
@@ -780,6 +790,10 @@ mep_free_config_entry(struct configEntry ** entry)
         slapi_entry_free(e->template_entry);
     }
 
+    if(e->origin_attrs){
+        slapi_ch_array_free(e->origin_attrs);
+    }
+
     slapi_ch_free((void **) entry);
 }
 
@@ -808,6 +822,210 @@ mep_delete_config()
 /*
  * Helper functions
  */
+
+/*
+ * mep_parse_mapped_origin_attr()
+ *
+ * Parses a mapped attribute setting from a template and
+ * grabs the attribute name and places it in origin_type.
+ *
+ * This is used to determine if a modify operation needs
+ * to update the managed entry.
+ */
+static int
+mep_parse_mapped_origin_attr(char *mapping, char **origin_type)
+{
+    int ret = 0;
+    char *p = NULL;
+    char *end = NULL;
+    char *var_start = NULL;
+
+    /* reset the pointer for origin_type as this func is usually in a loop */
+    *origin_type = NULL;
+
+    /* split out the type from the value (use the first ':') */
+    if ((p = strchr(mapping, ':')) == NULL) {
+        slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+                        "mep_parse_mapped_origin_attr: Value for mapped attribute "
+                        "is not in the correct format. (value: \"%s\").\n",
+                        mapping);
+        ret = 1;
+        goto bail;
+    }
+
+    /* Ensure the type is not empty. */
+    if (p == mapping) {
+        slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+                        "mep_parse_mapped_origin_attr: Value for mapped attribute "
+                        "is not in the correct format. The type is missing. "
+                        "(value: \"%s\").\n",
+                        mapping);
+        ret = 1;
+        goto bail;
+    }
+
+    /* Terminate the type so we can use it as a string. */
+    *p = '\0';
+
+    /* Advance p to point to the beginning of the value. */
+    p++;
+    while (*p == ' ') {
+        p++;
+    }
+
+    /* Make end point to the last character that we want in the value. */
+    end = p + strlen(p) - 1;
+
+    /* Find the variable that we need to substitute. */
+    for (; p <= end; p++) {
+        if (*p == '$') {
+            if (p == end) {
+                slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+                                "mep_parse_mapped_origin_attr: Invalid mapped "
+                                "attribute value for type \"%s\".\n", mapping);
+                ret = 1;
+                goto bail;
+            }
+
+            if (*(p + 1) == '$') {
+                /* This is an escaped $.  Eliminate the escape character
+                 * to prevent if from being a part of the value. */
+                p++;
+                memmove(p, p+1, end-(p+1)+1);
+                *end = '\0';
+                end--;
+            } else {
+                int quoted = 0;
+
+                /* We found a variable.  Terminate the pre
+                 * string and process the variable. */
+                *p = '\0';
+                p++;
+
+                /* Check if the variable name is quoted.  If it is, we skip past
+                 * the quoting brace to avoid putting it in the mapped value. */
+                if (*p == '{') {
+                    quoted = 1;
+                    if (p < end) {
+                        p++;
+                    } else {
+                        slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+                                        "mep_parse_mapped_origin_attr: Invalid mapped "
+                                        "attribute value for type \"%s\".\n", mapping);
+                        ret = 1;
+                        goto bail;
+                    }
+                }
+
+                /* We should be pointing at the variable name now. */
+                var_start = p;
+
+                /* Move the pointer to the end of the variable name.  We
+                 * stop at the first character that is not legal for use
+                 * in an attribute description. */
+                while ((p < end) && IS_ATTRDESC_CHAR(*p)) {
+                    p++;
+                }
+
+                /* If the variable is quoted and this is not a closing
+                 * brace, there is a syntax error in the mapping rule. */
+                if (quoted && (*p != '}')) {
+                        slapi_log_error( SLAPI_LOG_FATAL, MEP_PLUGIN_SUBSYSTEM,
+                                        "mep_parse_mapped_origin_attr: Invalid mapped "
+                                        "attribute value for type \"%s\".\n", mapping);
+                        ret = 1;
+                        goto bail;
+                }
+
+                /* Check for a missing variable name. */
+                if (p == var_start) {
+                    break;
+                }
+
+                if (p == end) {
+                    /* Set the map type.  In this case, p could be
+                     * pointing at either the last character of the
+                     * map type, or at the first character after the
+                     * map type.  If the character is valid for use
+                     * in an attribute description, we consider it
+                     * to be a part of the map type. */
+                    if (IS_ATTRDESC_CHAR(*p)) {
+                        *origin_type = strndup(var_start, p - var_start + 1);
+                        /* There is no post string. */
+                    } else {
+                        *origin_type = strndup(var_start, p - var_start);
+                    }
+                } else {
+                    /* Set the map type.  In this case, p is pointing
+                     * at the first character after the map type. */
+                    *origin_type = strndup(var_start, p - var_start);
+                }
+
+                /* We only support a single variable, so we're done. */
+                break;
+            }
+        }
+    }
+
+  bail:
+    if (ret != 0) {
+        slapi_ch_free_string(origin_type);
+    }
+
+    return ret;
+}
+
+/*
+ *  mep_extract_origin_attrs
+ *
+ *  Extract the attributes from the template that reside on
+ *  the origin entry that trigger updates to the managed entry.
+ */
+static char **
+mep_extract_origin_attrs(Slapi_Entry *template)
+{
+    char **vals = NULL;
+    char *origin_type = NULL;
+    char **origin_attrs = NULL;
+    int i;
+
+    if (template) {
+        vals = slapi_entry_attr_get_charray(template, MEP_MAPPED_ATTR_TYPE);
+        for (i = 0; vals && vals[i]; ++i) {
+            if (mep_parse_mapped_origin_attr(vals[i], &origin_type) == 0) {
+                slapi_ch_array_add(&origin_attrs,origin_type);
+            }
+        }
+        slapi_ch_array_free(vals);
+    }
+
+    return origin_attrs;
+}
+
+/*
+ * mep_is_mapped_origin_attr()
+ *
+ * Checks if type is a mapped origin attribute.
+ */
+static int
+mep_is_mapped_origin_attr(char **vals, char *type)
+{
+    int ret = 0;
+    int i;
+
+    if (type) {
+        for (i = 0; vals && vals[i]; ++i) {
+            if (slapi_attr_type_cmp(vals[i], type, SLAPI_TYPE_CMP_EXACT) == 0) {
+                /* Ok, we are modifying a attribute that affects the managed entry */
+                ret = 1;
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
 static Slapi_DN *
 mep_get_sdn(Slapi_PBlock * pb)
 {
@@ -2098,6 +2316,8 @@ mep_mod_post_op(Slapi_PBlock *pb)
     struct configEntry *config = NULL;
     int result = 0;
     void *txn = NULL;
+    LDAPMod	**mods = NULL;
+    int i, abort_mod = 1;
 
     slapi_log_error(SLAPI_LOG_TRACE, MEP_PLUGIN_SUBSYSTEM,
                     "--> mep_mod_post_op\n");
@@ -2146,6 +2366,29 @@ mep_mod_post_op(Slapi_PBlock *pb)
 
             mep_find_config(e, &config);
             if (config) {
+                /*
+                 *  Check to see if the applied mods are mapped origin attributes.
+                 *  If they are not, then we don't need to modify the mapped entry
+                 *  as it has not changed.
+                 */
+                slapi_pblock_get (pb, SLAPI_MODIFY_MODS, &mods);
+                for(i = 0; mods && mods[i]; i++){
+                    if(mep_is_mapped_origin_attr(config->origin_attrs,mods[i]->mod_type)){
+                        /*
+                         * We are modifying a managed origin attr, so we can proceed with
+                         * modifying the managed entry.  Otherwise we would modify the
+                         * managed entry for no reason.
+                         */    
+                        abort_mod = 0;
+                        break;
+                    }
+                }
+
+                if(abort_mod){
+                    mep_config_unlock();
+                    goto bail;
+                }
+
                 smods = mep_get_mapped_mods(config, e, &mapped_dn);
                 if (smods) {
                     /* Clear out the pblock for reuse. */
@@ -2191,15 +2434,12 @@ mep_mod_post_op(Slapi_PBlock *pb)
                         "mep_mod_post_op: Unable to find config for origin "
                         "entry \"%s\".\n", slapi_sdn_get_dn(sdn));
             }
-
-            slapi_ch_free_string(&managed_dn);
-
             mep_config_unlock();
         }
-
     }
 
   bail:
+    slapi_ch_free_string(&managed_dn);
     slapi_log_error(SLAPI_LOG_TRACE, MEP_PLUGIN_SUBSYSTEM,
                     "<-- mep_mod_post_op\n");
 

+ 1 - 0
ldap/servers/plugins/mep/mep.h

@@ -105,6 +105,7 @@ struct configEntry {
     char *managed_base;
     Slapi_DN *template_sdn;
     Slapi_Entry *template_entry;
+    char **origin_attrs;
 };
 
 /*