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 3 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, see <http://www.gnu.org/licenses/>.
27 * Component: ldb message component utility functions
29 * Description: functions for manipulating ldb_message structures
31 * Author: Andrew Tridgell
34 #include "ldb_private.h"
37 create a new ldb_message in a given memory context (NULL for top level)
39 struct ldb_message *ldb_msg_new(void *mem_ctx)
41 return talloc_zero(mem_ctx, struct ldb_message);
45 find an element in a message by attribute name
47 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48 const char *attr_name)
51 for (i=0;i<msg->num_elements;i++) {
52 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53 return &msg->elements[i];
60 see if two ldb_val structures contain exactly the same data
61 return 1 for a match, 0 for a mis-match
63 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
65 if (v1->length != v2->length) return 0;
66 if (v1->data == v2->data) return 1;
67 if (v1->length == 0) return 1;
69 if (memcmp(v1->data, v2->data, v1->length) == 0) {
77 find a value in an element
78 assumes case sensitive comparison
80 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
84 for (i=0;i<el->num_values;i++) {
85 if (ldb_val_equal_exact(val, &el->values[i])) {
86 return &el->values[i];
93 duplicate a ldb_val structure
95 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
98 v2.length = v->length;
99 if (v->data == NULL) {
104 /* the +1 is to cope with buggy C library routines like strndup
105 that look one byte beyond */
106 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
112 memcpy(v2.data, v->data, v->length);
113 ((char *)v2.data)[v->length] = 0;
118 add an empty element to a message
120 int ldb_msg_add_empty( struct ldb_message *msg,
121 const char *attr_name,
123 struct ldb_message_element **return_el)
125 struct ldb_message_element *els;
127 els = talloc_realloc(msg, msg->elements,
128 struct ldb_message_element, msg->num_elements+1);
131 return LDB_ERR_OPERATIONS_ERROR;
134 els[msg->num_elements].values = NULL;
135 els[msg->num_elements].num_values = 0;
136 els[msg->num_elements].flags = flags;
137 els[msg->num_elements].name = talloc_strdup(els, attr_name);
138 if (!els[msg->num_elements].name) {
140 return LDB_ERR_OPERATIONS_ERROR;
147 *return_el = &els[msg->num_elements-1];
154 add an empty element to a message
156 int ldb_msg_add(struct ldb_message *msg,
157 const struct ldb_message_element *el,
160 /* We have to copy this, just in case *el is a pointer into
161 * what ldb_msg_add_empty() is about to realloc() */
162 struct ldb_message_element el_copy = *el;
163 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
164 return LDB_ERR_OPERATIONS_ERROR;
167 msg->elements[msg->num_elements-1] = el_copy;
168 msg->elements[msg->num_elements-1].flags = flags;
174 add a value to a message
176 int ldb_msg_add_value(struct ldb_message *msg,
177 const char *attr_name,
178 const struct ldb_val *val,
179 struct ldb_message_element **return_el)
181 struct ldb_message_element *el;
182 struct ldb_val *vals;
185 el = ldb_msg_find_element(msg, attr_name);
187 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
188 if (ret != LDB_SUCCESS) {
193 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
196 return LDB_ERR_OPERATIONS_ERROR;
199 el->values[el->num_values] = *val;
211 add a value to a message, stealing it into the 'right' place
213 int ldb_msg_add_steal_value(struct ldb_message *msg,
214 const char *attr_name,
218 struct ldb_message_element *el;
220 ret = ldb_msg_add_value(msg, attr_name, val, &el);
221 if (ret == LDB_SUCCESS) {
222 talloc_steal(el->values, val->data);
229 add a string element to a message
231 int ldb_msg_add_string(struct ldb_message *msg,
232 const char *attr_name, const char *str)
236 val.data = discard_const_p(uint8_t, str);
237 val.length = strlen(str);
239 if (val.length == 0) {
240 /* allow empty strings as non-existant attributes */
244 return ldb_msg_add_value(msg, attr_name, &val, NULL);
248 add a string element to a message, stealing it into the 'right' place
250 int ldb_msg_add_steal_string(struct ldb_message *msg,
251 const char *attr_name, char *str)
255 val.data = (uint8_t *)str;
256 val.length = strlen(str);
258 return ldb_msg_add_steal_value(msg, attr_name, &val);
262 add a DN element to a message
263 WARNING: this uses the linearized string from the dn, and does not
266 int ldb_msg_add_dn(struct ldb_message *msg, const char *attr_name,
269 return ldb_msg_add_string(msg, attr_name, ldb_dn_get_linearized(dn));
273 add a printf formatted element to a message
275 int ldb_msg_add_fmt(struct ldb_message *msg,
276 const char *attr_name, const char *fmt, ...)
283 str = talloc_vasprintf(msg, fmt, ap);
286 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
288 val.data = (uint8_t *)str;
289 val.length = strlen(str);
291 return ldb_msg_add_steal_value(msg, attr_name, &val);
295 compare two ldb_message_element structures
296 assumes case senistive comparison
298 int ldb_msg_element_compare(struct ldb_message_element *el1,
299 struct ldb_message_element *el2)
303 if (el1->num_values != el2->num_values) {
304 return el1->num_values - el2->num_values;
307 for (i=0;i<el1->num_values;i++) {
308 if (!ldb_msg_find_val(el2, &el1->values[i])) {
317 compare two ldb_message_element structures
318 comparing by element name
320 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
321 struct ldb_message_element *el2)
323 return ldb_attr_cmp(el1->name, el2->name);
327 convenience functions to return common types from a message
328 these return the first value if the attribute is multi-valued
330 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
331 const char *attr_name)
333 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
334 if (!el || el->num_values == 0) {
337 return &el->values[0];
340 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
341 const char *attr_name,
344 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
345 if (!v || !v->data) {
346 return default_value;
348 return strtol((const char *)v->data, NULL, 0);
351 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
352 const char *attr_name,
353 unsigned int default_value)
355 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
356 if (!v || !v->data) {
357 return default_value;
359 return strtoul((const char *)v->data, NULL, 0);
362 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
363 const char *attr_name,
364 int64_t default_value)
366 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
367 if (!v || !v->data) {
368 return default_value;
370 return strtoll((const char *)v->data, NULL, 0);
373 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
374 const char *attr_name,
375 uint64_t default_value)
377 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
378 if (!v || !v->data) {
379 return default_value;
381 return strtoull((const char *)v->data, NULL, 0);
384 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
385 const char *attr_name,
386 double default_value)
388 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
389 if (!v || !v->data) {
390 return default_value;
392 return strtod((const char *)v->data, NULL);
395 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
396 const char *attr_name,
399 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
400 if (!v || !v->data) {
401 return default_value;
403 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
406 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
409 return default_value;
412 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
413 const char *attr_name,
414 const char *default_value)
416 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
417 if (!v || !v->data) {
418 return default_value;
420 return (const char *)v->data;
423 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
425 const struct ldb_message *msg,
426 const char *attr_name)
428 struct ldb_dn *res_dn;
429 const struct ldb_val *v;
431 v = ldb_msg_find_ldb_val(msg, attr_name);
432 if (!v || !v->data) {
435 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
436 if ( ! ldb_dn_validate(res_dn)) {
444 sort the elements of a message by name
446 void ldb_msg_sort_elements(struct ldb_message *msg)
448 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
449 (comparison_fn_t)ldb_msg_element_compare_name);
453 shallow copy a message - copying only the elements array so that the caller
454 can safely add new elements without changing the message
456 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
457 const struct ldb_message *msg)
459 struct ldb_message *msg2;
462 msg2 = talloc(mem_ctx, struct ldb_message);
463 if (msg2 == NULL) return NULL;
467 msg2->elements = talloc_array(msg2, struct ldb_message_element,
469 if (msg2->elements == NULL) goto failed;
471 for (i=0;i<msg2->num_elements;i++) {
472 msg2->elements[i] = msg->elements[i];
484 copy a message, allocating new memory for all parts
486 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
487 const struct ldb_message *msg)
489 struct ldb_message *msg2;
492 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
493 if (msg2 == NULL) return NULL;
495 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
496 if (msg2->dn == NULL) goto failed;
498 for (i=0;i<msg2->num_elements;i++) {
499 struct ldb_message_element *el = &msg2->elements[i];
500 struct ldb_val *values = el->values;
501 el->name = talloc_strdup(msg2->elements, el->name);
502 if (el->name == NULL) goto failed;
503 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
504 for (j=0;j<el->num_values;j++) {
505 el->values[j] = ldb_val_dup(el->values, &values[j]);
506 if (el->values[j].data == NULL && values[j].length != 0) {
521 canonicalise a message, merging elements of the same name
523 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
524 const struct ldb_message *msg)
527 struct ldb_message *msg2;
529 msg2 = ldb_msg_copy(ldb, msg);
530 if (msg2 == NULL) return NULL;
532 ldb_msg_sort_elements(msg2);
534 for (i=1;i<msg2->num_elements;i++) {
535 struct ldb_message_element *el1 = &msg2->elements[i-1];
536 struct ldb_message_element *el2 = &msg2->elements[i];
537 if (ldb_msg_element_compare_name(el1, el2) == 0) {
538 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
539 el1->num_values + el2->num_values);
540 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
543 memcpy(el1->values + el1->num_values,
545 sizeof(struct ldb_val) * el2->num_values);
546 el1->num_values += el2->num_values;
547 talloc_free(discard_const_p(char, el2->name));
548 if (i+1<msg2->num_elements) {
549 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
550 (msg2->num_elements - (i+1)));
552 msg2->num_elements--;
562 return a ldb_message representing the differences between msg1 and msg2. If you
563 then use this in a ldb_modify() call it can be used to save edits to a message
565 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
566 struct ldb_message *msg1,
567 struct ldb_message *msg2)
569 struct ldb_message *mod;
570 struct ldb_message_element *el;
573 mod = ldb_msg_new(ldb);
579 mod->num_elements = 0;
580 mod->elements = NULL;
582 msg2 = ldb_msg_canonicalize(ldb, msg2);
588 /* look in msg2 to find elements that need to be added
590 for (i=0;i<msg2->num_elements;i++) {
591 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
593 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
599 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != LDB_SUCCESS) {
605 /* look in msg1 to find elements that need to be deleted */
606 for (i=0;i<msg1->num_elements;i++) {
607 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
609 if (ldb_msg_add_empty(mod,
610 msg1->elements[i].name,
611 LDB_FLAG_MOD_DELETE, NULL) != LDB_SUCCESS) {
621 int ldb_msg_sanity_check(struct ldb_context *ldb,
622 const struct ldb_message *msg)
626 /* basic check on DN */
627 if (msg->dn == NULL) {
628 /* TODO: return also an error string */
629 ldb_set_errstring(ldb, "ldb message lacks a DN!");
630 return LDB_ERR_INVALID_DN_SYNTAX;
633 /* basic syntax checks */
634 for (i = 0; i < msg->num_elements; i++) {
635 for (j = 0; j < msg->elements[i].num_values; j++) {
636 if (msg->elements[i].values[j].length == 0) {
637 TALLOC_CTX *mem_ctx = talloc_new(ldb);
638 /* an attribute cannot be empty */
639 /* TODO: return also an error string */
640 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
641 msg->elements[i].name,
642 ldb_dn_get_linearized(msg->dn));
643 talloc_free(mem_ctx);
644 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
656 copy an attribute list. This only copies the array, not the elements
657 (ie. the elements are left as the same pointers)
659 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
663 for (i=0;attrs && attrs[i];i++) /* noop */ ;
664 ret = talloc_array(mem_ctx, const char *, i+1);
668 for (i=0;attrs && attrs[i];i++) {
677 copy an attribute list. This only copies the array, not the elements
678 (ie. the elements are left as the same pointers). The new attribute is added to the list.
680 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
685 for (i=0;attrs && attrs[i];i++) {
686 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
691 return ldb_attr_list_copy(mem_ctx, attrs);
693 ret = talloc_array(mem_ctx, const char *, i+2);
697 for (i=0;attrs && attrs[i];i++) {
707 return 1 if an attribute is in a list of attributes, or 0 otherwise
709 int ldb_attr_in_list(const char * const *attrs, const char *attr)
712 for (i=0;attrs && attrs[i];i++) {
713 if (ldb_attr_cmp(attrs[i], attr) == 0) {
722 rename the specified attribute in a search result
724 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
726 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
730 el->name = talloc_strdup(msg->elements, replace);
731 if (el->name == NULL) {
732 return LDB_ERR_OPERATIONS_ERROR;
739 copy the specified attribute in a search result to a new attribute
741 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
743 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
747 if (ldb_msg_add(msg, el, 0) != 0) {
748 return LDB_ERR_OPERATIONS_ERROR;
750 return ldb_msg_rename_attr(msg, attr, replace);
754 remove the specified element in a search result
756 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
758 int n = (el - msg->elements);
759 if (n >= msg->num_elements) {
760 /* should we abort() here? */
763 if (n != msg->num_elements-1) {
764 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
771 remove the specified attribute in a search result
773 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
775 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
777 ldb_msg_remove_element(msg, el);
782 return a LDAP formatted GeneralizedTime string
784 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
786 struct tm *tm = gmtime(&t);
794 /* we now excatly how long this string will be */
795 ts = talloc_array(mem_ctx, char, 18);
797 /* formatted like: 20040408072012.0Z */
799 "%04u%02u%02u%02u%02u%02u.0Z",
800 tm->tm_year+1900, tm->tm_mon+1,
801 tm->tm_mday, tm->tm_hour, tm->tm_min,
813 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
815 time_t ldb_string_to_time(const char *s)
819 if (s == NULL) return 0;
821 memset(&tm, 0, sizeof(tm));
822 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
823 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
824 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
834 return a LDAP formatted UTCTime string
836 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
838 struct tm *tm = gmtime(&t);
846 /* we now excatly how long this string will be */
847 ts = talloc_array(mem_ctx, char, 14);
849 /* formatted like: 20040408072012.0Z => 040408072012Z */
851 "%02u%02u%02u%02u%02u%02uZ",
852 (tm->tm_year+1900)%100, tm->tm_mon+1,
853 tm->tm_mday, tm->tm_hour, tm->tm_min,
865 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
867 time_t ldb_string_utc_to_time(const char *s)
871 if (s == NULL) return 0;
873 memset(&tm, 0, sizeof(tm));
874 if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
875 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
876 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
879 if (tm.tm_year < 50) {
889 dump a set of results to a file. Useful from within gdb
891 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
895 for (i = 0; i < result->count; i++) {
896 struct ldb_ldif ldif;
897 fprintf(f, "# record %d\n", i+1);
898 ldif.changetype = LDB_CHANGETYPE_NONE;
899 ldif.msg = result->msgs[i];
900 ldb_ldif_write_file(ldb, f, &ldif);
905 checks for a string attribute. Returns "1" on match and otherwise "0".
907 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
908 const char *name, const char *value)
910 struct ldb_message_element *el;
913 el = ldb_msg_find_element(msg, name);
918 val.data = discard_const_p(uint8_t, value);
919 val.length = strlen(value);
921 if (ldb_msg_find_val(el, &val)) {