4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb message component utility functions
30 * Description: functions for manipulating ldb_message structures
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
39 create a new ldb_message in a given memory context (NULL for top level)
41 struct ldb_message *ldb_msg_new(void *mem_ctx)
43 return talloc_zero(mem_ctx, struct ldb_message);
47 find an element in a message by attribute name
49 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
50 const char *attr_name)
53 for (i=0;i<msg->num_elements;i++) {
54 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
55 return &msg->elements[i];
62 see if two ldb_val structures contain exactly the same data
63 return 1 for a match, 0 for a mis-match
65 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
67 if (v1->length != v2->length) return 0;
69 if (v1->length == 0) return 1;
71 if (memcmp(v1->data, v2->data, v1->length) == 0) {
79 find a value in an element
80 assumes case sensitive comparison
82 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
86 for (i=0;i<el->num_values;i++) {
87 if (ldb_val_equal_exact(val, &el->values[i])) {
88 return &el->values[i];
95 duplicate a ldb_val structure
97 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
100 v2.length = v->length;
101 if (v->data == NULL) {
106 /* the +1 is to cope with buggy C library routines like strndup
107 that look one byte beyond */
108 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
114 memcpy(v2.data, v->data, v->length);
115 ((char *)v2.data)[v->length] = 0;
120 add an empty element to a message
122 int ldb_msg_add_empty( struct ldb_message *msg,
123 const char *attr_name,
125 struct ldb_message_element **return_el)
127 struct ldb_message_element *els;
129 if (! ldb_valid_attr_name(attr_name)) {
130 return LDB_ERR_OPERATIONS_ERROR;
133 els = talloc_realloc(msg, msg->elements,
134 struct ldb_message_element, msg->num_elements+1);
137 return LDB_ERR_OPERATIONS_ERROR;
140 els[msg->num_elements].values = NULL;
141 els[msg->num_elements].num_values = 0;
142 els[msg->num_elements].flags = flags;
143 els[msg->num_elements].name = talloc_strdup(els, attr_name);
144 if (!els[msg->num_elements].name) {
146 return LDB_ERR_OPERATIONS_ERROR;
153 *return_el = &els[msg->num_elements-1];
160 add an empty element to a message
162 int ldb_msg_add(struct ldb_message *msg,
163 const struct ldb_message_element *el,
166 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
167 return LDB_ERR_OPERATIONS_ERROR;
170 msg->elements[msg->num_elements-1] = *el;
171 msg->elements[msg->num_elements-1].flags = flags;
177 add a value to a message
179 int ldb_msg_add_value(struct ldb_message *msg,
180 const char *attr_name,
181 const struct ldb_val *val,
182 struct ldb_message_element **return_el)
184 struct ldb_message_element *el;
185 struct ldb_val *vals;
188 el = ldb_msg_find_element(msg, attr_name);
190 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
191 if (ret != LDB_SUCCESS) {
196 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
199 return LDB_ERR_OPERATIONS_ERROR;
202 el->values[el->num_values] = *val;
214 add a value to a message, stealing it into the 'right' place
216 int ldb_msg_add_steal_value(struct ldb_message *msg,
217 const char *attr_name,
221 struct ldb_message_element *el;
223 ret = ldb_msg_add_value(msg, attr_name, val, &el);
224 if (ret == LDB_SUCCESS) {
225 talloc_steal(el->values, val->data);
232 add a string element to a message
234 int ldb_msg_add_string(struct ldb_message *msg,
235 const char *attr_name, const char *str)
239 val.data = discard_const_p(uint8_t, str);
240 val.length = strlen(str);
242 if (val.length == 0) {
243 /* allow empty strings as non-existant attributes */
247 return ldb_msg_add_value(msg, attr_name, &val, NULL);
251 add a string element to a message, stealing it into the 'right' place
253 int ldb_msg_add_steal_string(struct ldb_message *msg,
254 const char *attr_name, char *str)
258 val.data = (uint8_t *)str;
259 val.length = strlen(str);
261 return ldb_msg_add_steal_value(msg, attr_name, &val);
265 add a printf formatted element to a message
267 int ldb_msg_add_fmt(struct ldb_message *msg,
268 const char *attr_name, const char *fmt, ...)
275 str = talloc_vasprintf(msg, fmt, ap);
278 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
280 val.data = (uint8_t *)str;
281 val.length = strlen(str);
283 return ldb_msg_add_steal_value(msg, attr_name, &val);
287 compare two ldb_message_element structures
288 assumes case senistive comparison
290 int ldb_msg_element_compare(struct ldb_message_element *el1,
291 struct ldb_message_element *el2)
295 if (el1->num_values != el2->num_values) {
296 return el1->num_values - el2->num_values;
299 for (i=0;i<el1->num_values;i++) {
300 if (!ldb_msg_find_val(el2, &el1->values[i])) {
309 compare two ldb_message_element structures
310 comparing by element name
312 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
313 struct ldb_message_element *el2)
315 return ldb_attr_cmp(el1->name, el2->name);
319 convenience functions to return common types from a message
320 these return the first value if the attribute is multi-valued
322 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
324 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
325 if (!el || el->num_values == 0) {
328 return &el->values[0];
331 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
332 const char *attr_name,
335 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
336 if (!v || !v->data) {
337 return default_value;
339 return strtol((const char *)v->data, NULL, 0);
342 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
343 const char *attr_name,
344 unsigned int default_value)
346 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
347 if (!v || !v->data) {
348 return default_value;
350 return strtoul((const char *)v->data, NULL, 0);
353 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
354 const char *attr_name,
355 int64_t default_value)
357 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
358 if (!v || !v->data) {
359 return default_value;
361 return strtoll((const char *)v->data, NULL, 0);
364 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
365 const char *attr_name,
366 uint64_t default_value)
368 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
369 if (!v || !v->data) {
370 return default_value;
372 return strtoull((const char *)v->data, NULL, 0);
375 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
376 const char *attr_name,
377 double default_value)
379 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
380 if (!v || !v->data) {
381 return default_value;
383 return strtod((const char *)v->data, NULL);
386 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
387 const char *attr_name,
390 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
391 if (!v || !v->data) {
392 return default_value;
394 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
397 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
400 return default_value;
403 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
404 const char *attr_name,
405 const char *default_value)
407 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
408 if (!v || !v->data) {
409 return default_value;
411 return (const char *)v->data;
414 struct ldb_dn *ldb_msg_find_attr_as_dn(void *mem_ctx,
415 const struct ldb_message *msg,
416 const char *attr_name)
418 const struct ldb_val *v;
420 v = ldb_msg_find_ldb_val(msg, attr_name);
421 if (!v || !v->data) {
424 return ldb_dn_explode(mem_ctx, (const char *)v->data);
428 sort the elements of a message by name
430 void ldb_msg_sort_elements(struct ldb_message *msg)
432 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
433 (comparison_fn_t)ldb_msg_element_compare_name);
437 shallow copy a message - copying only the elements array so that the caller
438 can safely add new elements without changing the message
440 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
441 const struct ldb_message *msg)
443 struct ldb_message *msg2;
446 msg2 = talloc(mem_ctx, struct ldb_message);
447 if (msg2 == NULL) return NULL;
450 msg2->private_data = NULL;
452 msg2->elements = talloc_array(msg2, struct ldb_message_element,
454 if (msg2->elements == NULL) goto failed;
456 for (i=0;i<msg2->num_elements;i++) {
457 msg2->elements[i] = msg->elements[i];
469 copy a message, allocating new memory for all parts
471 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
472 const struct ldb_message *msg)
474 struct ldb_message *msg2;
477 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
478 if (msg2 == NULL) return NULL;
480 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
481 if (msg2->dn == NULL) goto failed;
483 for (i=0;i<msg2->num_elements;i++) {
484 struct ldb_message_element *el = &msg2->elements[i];
485 struct ldb_val *values = el->values;
486 el->name = talloc_strdup(msg2->elements, el->name);
487 if (el->name == NULL) goto failed;
488 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
489 for (j=0;j<el->num_values;j++) {
490 el->values[j] = ldb_val_dup(el->values, &values[j]);
491 if (el->values[j].data == NULL && values[j].length != 0) {
506 canonicalise a message, merging elements of the same name
508 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
509 const struct ldb_message *msg)
512 struct ldb_message *msg2;
514 msg2 = ldb_msg_copy(ldb, msg);
515 if (msg2 == NULL) return NULL;
517 ldb_msg_sort_elements(msg2);
519 for (i=1;i<msg2->num_elements;i++) {
520 struct ldb_message_element *el1 = &msg2->elements[i-1];
521 struct ldb_message_element *el2 = &msg2->elements[i];
522 if (ldb_msg_element_compare_name(el1, el2) == 0) {
523 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
524 el1->num_values + el2->num_values);
525 if (el1->values == NULL) {
528 memcpy(el1->values + el1->num_values,
530 sizeof(struct ldb_val) * el2->num_values);
531 el1->num_values += el2->num_values;
532 talloc_free(discard_const_p(char, el2->name));
533 if (i+1<msg2->num_elements) {
534 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
535 (msg2->num_elements - (i+1)));
537 msg2->num_elements--;
547 return a ldb_message representing the differences between msg1 and msg2. If you
548 then use this in a ldb_modify() call it can be used to save edits to a message
550 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
551 struct ldb_message *msg1,
552 struct ldb_message *msg2)
554 struct ldb_message *mod;
555 struct ldb_message_element *el;
558 mod = ldb_msg_new(ldb);
561 mod->num_elements = 0;
562 mod->elements = NULL;
564 msg2 = ldb_msg_canonicalize(ldb, msg2);
569 /* look in msg2 to find elements that need to be added
571 for (i=0;i<msg2->num_elements;i++) {
572 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
574 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
580 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
585 /* look in msg1 to find elements that need to be deleted */
586 for (i=0;i<msg1->num_elements;i++) {
587 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
589 if (ldb_msg_add_empty(mod,
590 msg1->elements[i].name,
591 LDB_FLAG_MOD_DELETE, NULL) != 0) {
600 int ldb_msg_sanity_check(struct ldb_context *ldb,
601 const struct ldb_message *msg)
605 /* basic check on DN */
606 if (msg->dn == NULL) {
607 /* TODO: return also an error string */
608 ldb_set_errstring(ldb, "ldb message lacks a DN!");
609 return LDB_ERR_INVALID_DN_SYNTAX;
612 /* basic syntax checks */
613 for (i = 0; i < msg->num_elements; i++) {
614 for (j = 0; j < msg->elements[i].num_values; j++) {
615 if (msg->elements[i].values[j].length == 0) {
616 TALLOC_CTX *mem_ctx = talloc_new(ldb);
617 /* an attribute cannot be empty */
618 /* TODO: return also an error string */
619 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
620 msg->elements[i].name,
621 ldb_dn_linearize(mem_ctx, msg->dn));
622 talloc_free(mem_ctx);
623 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
635 copy an attribute list. This only copies the array, not the elements
636 (ie. the elements are left as the same pointers)
638 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
642 for (i=0;attrs[i];i++) /* noop */ ;
643 ret = talloc_array(mem_ctx, const char *, i+1);
647 for (i=0;attrs[i];i++) {
656 copy an attribute list. This only copies the array, not the elements
657 (ie. the elements are left as the same pointers). The new attribute is added to the list.
659 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
663 for (i=0;attrs[i];i++) /* noop */ ;
664 ret = talloc_array(mem_ctx, const char *, i+2);
668 for (i=0;attrs[i];i++) {
678 return 1 if an attribute is in a list of attributes, or 0 otherwise
680 int ldb_attr_in_list(const char * const *attrs, const char *attr)
683 for (i=0;attrs[i];i++) {
684 if (ldb_attr_cmp(attrs[i], attr) == 0) {
693 rename the specified attribute in a search result
695 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
697 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
701 el->name = talloc_strdup(msg->elements, replace);
702 if (el->name == NULL) {
703 return LDB_ERR_OPERATIONS_ERROR;
710 copy the specified attribute in a search result to a new attribute
712 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
714 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
718 if (ldb_msg_add(msg, el, 0) != 0) {
719 return LDB_ERR_OPERATIONS_ERROR;
721 return ldb_msg_rename_attr(msg, attr, replace);
726 remove the specified attribute in a search result
728 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
730 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
732 int n = (el - msg->elements);
733 if (n != msg->num_elements-1) {
734 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
741 remove the specified element in a search result
743 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
745 int n = (el - msg->elements);
746 if (n != msg->num_elements-1) {
747 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
753 return a LDAP formatted time string
755 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
757 struct tm *tm = gmtime(&t);
763 /* formatted like: 20040408072012.0Z */
764 return talloc_asprintf(mem_ctx,
765 "%04u%02u%02u%02u%02u%02u.0Z",
766 tm->tm_year+1900, tm->tm_mon+1,
767 tm->tm_mday, tm->tm_hour, tm->tm_min,
773 convert a LDAP time string to a time_t. Return 0 if unable to convert
775 time_t ldb_string_to_time(const char *s)
779 if (s == NULL) return 0;
781 memset(&tm, 0, sizeof(tm));
782 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
783 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
784 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
795 dump a set of results to a file. Useful from within gdb
797 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
801 for (i = 0; i < result->count; i++) {
802 struct ldb_ldif ldif;
803 fprintf(f, "# record %d\n", i+1);
804 ldif.changetype = LDB_CHANGETYPE_NONE;
805 ldif.msg = result->msgs[i];
806 ldb_ldif_write_file(ldb, f, &ldif);
810 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
812 struct ldb_message_element *el;
815 el = ldb_msg_find_element(msg, name);
819 val.data = discard_const_p(uint8_t, value);
820 val.length = strlen(value);
822 if (ldb_msg_find_val(el, &val))