s4:dsdb/common/util.c - provide a better implementation of the "samdb_msg_add_(add...
authorMatthias Dieter Wallnöfer <mdw@samba.org>
Mon, 31 May 2010 12:52:46 +0000 (14:52 +0200)
committerMatthias Dieter Wallnöfer <mdw@samba.org>
Sun, 6 Jun 2010 18:47:10 +0000 (20:47 +0200)
This supports now also coexisting add and delete message elements with the
same attribute name.

source4/dsdb/common/util.c

index 408a9592767ecdfadeb3b5465b9483962ae8fda1..811d4745a761e6380edd8dbc4e08e674dc4c9d86 100644 (file)
@@ -837,52 +837,114 @@ int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc
 }
 
 /*
-  add a add attribute value to a message
+  add an add attribute value to a message or enhance an existing attribute
+  which has the same name and the add flag set.
 */
-int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-                        const char *attr_name, const char *value)
+int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
+                        struct ldb_message *msg, const char *attr_name,
+                        const char *value)
 {
        struct ldb_message_element *el;
-       char *a, *v;
+       struct ldb_val val, *vals;
+       char *v;
+       unsigned int i;
+       bool found = false;
        int ret;
-       a = talloc_strdup(mem_ctx, attr_name);
-       if (a == NULL)
-               return LDB_ERR_OPERATIONS_ERROR;
+
        v = talloc_strdup(mem_ctx, value);
-       if (v == NULL)
+       if (v == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
-       ret = ldb_msg_add_string(msg, a, v);
-       if (ret != 0)
-               return ret;
-       el = ldb_msg_find_element(msg, a);
-       if (el == NULL)
+       }
+
+       val.data = (uint8_t *) v;
+       val.length = strlen(v);
+
+       if (val.length == 0) {
+               /* allow empty strings as non-existent attributes */
+               return LDB_SUCCESS;
+       }
+
+       for (i = 0; i < msg->num_elements; i++) {
+               el = &msg->elements[i];
+               if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
+                   (el->flags == LDB_FLAG_MOD_ADD)) {
+                       found = true;
+                       break;
+               }
+       }
+       if (!found) {
+               ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_ADD,
+                                       &el);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       vals = talloc_realloc(msg, el->values, struct ldb_val,
+                             el->num_values + 1);
+       if (vals == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
-       el->flags = LDB_FLAG_MOD_ADD;
+       }
+       el->values = vals;
+       el->values[el->num_values] = val;
+       ++(el->num_values);
+
        return LDB_SUCCESS;
 }
 
 /*
-  add a delete attribute value to a message
+  add a delete attribute value to a message or enhance an existing attribute
+  which has the same name and the delete flag set.
 */
-int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-                        const char *attr_name, const char *value)
+int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
+                        struct ldb_message *msg, const char *attr_name,
+                        const char *value)
 {
        struct ldb_message_element *el;
-       char *a, *v;
+       struct ldb_val val, *vals;
+       char *v;
+       unsigned int i;
+       bool found = false;
        int ret;
-       a = talloc_strdup(mem_ctx, attr_name);
-       if (a == NULL)
-               return LDB_ERR_OPERATIONS_ERROR;
+
        v = talloc_strdup(mem_ctx, value);
-       if (v == NULL)
+       if (v == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
-       ret = ldb_msg_add_string(msg, a, v);
-       if (ret != 0)
-               return ret;
-       el = ldb_msg_find_element(msg, a);
-       if (el == NULL)
+       }
+
+       val.data = (uint8_t *) v;
+       val.length = strlen(v);
+
+       if (val.length == 0) {
+               /* allow empty strings as non-existent attributes */
+               return LDB_SUCCESS;
+       }
+
+       for (i = 0; i < msg->num_elements; i++) {
+               el = &msg->elements[i];
+               if ((ldb_attr_cmp(el->name, attr_name) == 0) &&
+                   (el->flags == LDB_FLAG_MOD_DELETE)) {
+                       found = true;
+                       break;
+               }
+       }
+       if (!found) {
+               ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_DELETE,
+                                       &el);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+       }
+
+       vals = talloc_realloc(msg, el->values, struct ldb_val,
+                             el->num_values + 1);
+       if (vals == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
-       el->flags = LDB_FLAG_MOD_DELETE;
+       }
+       el->values = vals;
+       el->values[el->num_values] = val;
+       ++(el->num_values);
+
        return LDB_SUCCESS;
 }