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 * Adds an element to a message.
156 * NOTE: Ownership of ldb_message_element fields
157 * is NOT transferred. Thus, if el pointer
158 * is invalidated for some reason, this will
159 * corrupt msg contents also
161 int ldb_msg_add(struct ldb_message *msg,
162 const struct ldb_message_element *el,
165 /* We have to copy this, just in case *el is a pointer into
166 * what ldb_msg_add_empty() is about to realloc() */
167 struct ldb_message_element el_copy = *el;
168 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != LDB_SUCCESS) {
169 return LDB_ERR_OPERATIONS_ERROR;
172 msg->elements[msg->num_elements-1] = el_copy;
173 msg->elements[msg->num_elements-1].flags = flags;
179 add a value to a message
181 int ldb_msg_add_value(struct ldb_message *msg,
182 const char *attr_name,
183 const struct ldb_val *val,
184 struct ldb_message_element **return_el)
186 struct ldb_message_element *el;
187 struct ldb_val *vals;
190 el = ldb_msg_find_element(msg, attr_name);
192 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
193 if (ret != LDB_SUCCESS) {
198 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
201 return LDB_ERR_OPERATIONS_ERROR;
204 el->values[el->num_values] = *val;
216 add a value to a message, stealing it into the 'right' place
218 int ldb_msg_add_steal_value(struct ldb_message *msg,
219 const char *attr_name,
223 struct ldb_message_element *el;
225 ret = ldb_msg_add_value(msg, attr_name, val, &el);
226 if (ret == LDB_SUCCESS) {
227 talloc_steal(el->values, val->data);
234 add a string element to a message
236 int ldb_msg_add_string(struct ldb_message *msg,
237 const char *attr_name, const char *str)
241 val.data = discard_const_p(uint8_t, str);
242 val.length = strlen(str);
244 if (val.length == 0) {
245 /* allow empty strings as non-existent attributes */
249 return ldb_msg_add_value(msg, attr_name, &val, NULL);
253 add a string element to a message, stealing it into the 'right' place
255 int ldb_msg_add_steal_string(struct ldb_message *msg,
256 const char *attr_name, char *str)
260 val.data = (uint8_t *)str;
261 val.length = strlen(str);
263 if (val.length == 0) {
264 /* allow empty strings as non-existent attributes */
268 return ldb_msg_add_steal_value(msg, attr_name, &val);
272 add a DN element to a message
273 WARNING: this uses the linearized string from the dn, and does not
276 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
279 return ldb_msg_add_steal_string(msg, attr_name,
280 ldb_dn_alloc_linearized(msg, dn));
284 add a printf formatted element to a message
286 int ldb_msg_add_fmt(struct ldb_message *msg,
287 const char *attr_name, const char *fmt, ...)
294 str = talloc_vasprintf(msg, fmt, ap);
297 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
299 val.data = (uint8_t *)str;
300 val.length = strlen(str);
302 return ldb_msg_add_steal_value(msg, attr_name, &val);
306 compare two ldb_message_element structures
307 assumes case sensitive comparison
309 int ldb_msg_element_compare(struct ldb_message_element *el1,
310 struct ldb_message_element *el2)
314 if (el1->num_values != el2->num_values) {
315 return el1->num_values - el2->num_values;
318 for (i=0;i<el1->num_values;i++) {
319 if (!ldb_msg_find_val(el2, &el1->values[i])) {
328 compare two ldb_message_element structures
329 comparing by element name
331 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
332 struct ldb_message_element *el2)
334 return ldb_attr_cmp(el1->name, el2->name);
338 convenience functions to return common types from a message
339 these return the first value if the attribute is multi-valued
341 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
342 const char *attr_name)
344 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
345 if (!el || el->num_values == 0) {
348 return &el->values[0];
351 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
352 const char *attr_name,
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 strtol((const char *)v->data, NULL, 0);
362 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
363 const char *attr_name,
364 unsigned int default_value)
367 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
368 if (!v || !v->data) {
369 return default_value;
372 /* in LDAP there're only int32_t values */
374 ret = strtol((const char *)v->data, NULL, 0);
379 return strtoul((const char *)v->data, NULL, 0);
382 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
383 const char *attr_name,
384 int64_t default_value)
386 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
387 if (!v || !v->data) {
388 return default_value;
390 return strtoll((const char *)v->data, NULL, 0);
393 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
394 const char *attr_name,
395 uint64_t default_value)
398 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
399 if (!v || !v->data) {
400 return default_value;
403 /* in LDAP there're only int64_t values */
405 ret = strtoll((const char *)v->data, NULL, 0);
410 return strtoull((const char *)v->data, NULL, 0);
413 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
414 const char *attr_name,
415 double default_value)
417 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
418 if (!v || !v->data) {
419 return default_value;
421 return strtod((const char *)v->data, NULL);
424 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
425 const char *attr_name,
428 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
429 if (!v || !v->data) {
430 return default_value;
432 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
435 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
438 return default_value;
441 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
442 const char *attr_name,
443 const char *default_value)
445 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
446 if (!v || !v->data) {
447 return default_value;
449 return (const char *)v->data;
452 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
454 const struct ldb_message *msg,
455 const char *attr_name)
457 struct ldb_dn *res_dn;
458 const struct ldb_val *v;
460 v = ldb_msg_find_ldb_val(msg, attr_name);
461 if (!v || !v->data) {
464 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
465 if ( ! ldb_dn_validate(res_dn)) {
473 sort the elements of a message by name
475 void ldb_msg_sort_elements(struct ldb_message *msg)
477 TYPESAFE_QSORT(msg->elements, msg->num_elements,
478 ldb_msg_element_compare_name);
482 shallow copy a message - copying only the elements array so that the caller
483 can safely add new elements without changing the message
485 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
486 const struct ldb_message *msg)
488 struct ldb_message *msg2;
491 msg2 = talloc(mem_ctx, struct ldb_message);
492 if (msg2 == NULL) return NULL;
496 msg2->elements = talloc_array(msg2, struct ldb_message_element,
498 if (msg2->elements == NULL) goto failed;
500 for (i=0;i<msg2->num_elements;i++) {
501 msg2->elements[i] = msg->elements[i];
513 copy a message, allocating new memory for all parts
515 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
516 const struct ldb_message *msg)
518 struct ldb_message *msg2;
521 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
522 if (msg2 == NULL) return NULL;
524 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
525 if (msg2->dn == NULL) goto failed;
527 for (i=0;i<msg2->num_elements;i++) {
528 struct ldb_message_element *el = &msg2->elements[i];
529 struct ldb_val *values = el->values;
530 el->name = talloc_strdup(msg2->elements, el->name);
531 if (el->name == NULL) goto failed;
532 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
533 for (j=0;j<el->num_values;j++) {
534 el->values[j] = ldb_val_dup(el->values, &values[j]);
535 if (el->values[j].data == NULL && values[j].length != 0) {
550 canonicalise a message, merging elements of the same name
552 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
553 const struct ldb_message *msg)
556 struct ldb_message *msg2;
558 msg2 = ldb_msg_copy(ldb, msg);
559 if (msg2 == NULL) return NULL;
561 ldb_msg_sort_elements(msg2);
563 for (i=1;i<msg2->num_elements;i++) {
564 struct ldb_message_element *el1 = &msg2->elements[i-1];
565 struct ldb_message_element *el2 = &msg2->elements[i];
566 if (ldb_msg_element_compare_name(el1, el2) == 0) {
567 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
568 el1->num_values + el2->num_values);
569 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
572 memcpy(el1->values + el1->num_values,
574 sizeof(struct ldb_val) * el2->num_values);
575 el1->num_values += el2->num_values;
576 talloc_free(discard_const_p(char, el2->name));
577 if (i+1<msg2->num_elements) {
578 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
579 (msg2->num_elements - (i+1)));
581 msg2->num_elements--;
591 return a ldb_message representing the differences between msg1 and msg2. If you
592 then use this in a ldb_modify() call it can be used to save edits to a message
594 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
595 struct ldb_message *msg1,
596 struct ldb_message *msg2)
599 struct ldb_message *mod;
601 /* allocate mod message in NULL context
602 * so it should appear as 'leaked' in talloc reports */
603 ldb_ret = ldb_msg_diff_ex(ldb, msg1, msg2,
604 (TALLOC_CTX*)NULL, &mod);
605 if (ldb_ret != LDB_SUCCESS) {
613 * return a ldb_message representing the differences between msg1 and msg2.
614 * If you then use this in a ldb_modify() call it can be used to save edits to a message
616 * Result message is constructed as follows:
617 * - LDB_FLAG_MOD_ADD - elements found only in msg2
618 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
619 * Value for msg2 element is used
620 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
622 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
624 int ldb_msg_diff_ex(struct ldb_context *ldb,
625 struct ldb_message *msg1,
626 struct ldb_message *msg2,
628 struct ldb_message **_msg_out)
632 struct ldb_message *mod;
633 struct ldb_message_element *el;
634 TALLOC_CTX *temp_ctx;
636 temp_ctx = talloc_new(mem_ctx);
638 return LDB_ERR_OPERATIONS_ERROR;
641 mod = ldb_msg_new(temp_ctx);
647 mod->num_elements = 0;
648 mod->elements = NULL;
650 /* canonicalize msg2 so we have no
651 * repeated elements */
652 msg2 = ldb_msg_canonicalize(ldb, msg2);
657 /* steal msg2 into mod context as it is
658 * allocated in ldb's context */
659 talloc_steal(mod, msg2);
661 /* look in msg2 to find elements that need to be added
663 for (i=0;i<msg2->num_elements;i++) {
664 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
666 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
670 ldb_res = ldb_msg_add(mod,
672 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
673 if (ldb_res != LDB_SUCCESS) {
678 /* look in msg1 to find elements that need to be deleted */
679 for (i=0;i<msg1->num_elements;i++) {
680 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
682 ldb_res = ldb_msg_add_empty(mod,
683 msg1->elements[i].name,
684 LDB_FLAG_MOD_DELETE, NULL);
685 if (ldb_res != LDB_SUCCESS) {
691 /* steal resulting message into supplied context */
692 talloc_steal(mem_ctx, mod);
695 talloc_free(temp_ctx);
699 talloc_free(temp_ctx);
700 return LDB_ERR_OPERATIONS_ERROR;
704 int ldb_msg_sanity_check(struct ldb_context *ldb,
705 const struct ldb_message *msg)
709 /* basic check on DN */
710 if (msg->dn == NULL) {
711 /* TODO: return also an error string */
712 ldb_set_errstring(ldb, "ldb message lacks a DN!");
713 return LDB_ERR_INVALID_DN_SYNTAX;
716 /* basic syntax checks */
717 for (i = 0; i < msg->num_elements; i++) {
718 for (j = 0; j < msg->elements[i].num_values; j++) {
719 if (msg->elements[i].values[j].length == 0) {
720 TALLOC_CTX *mem_ctx = talloc_new(ldb);
721 /* an attribute cannot be empty */
722 /* TODO: return also an error string */
723 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
724 msg->elements[i].name,
725 ldb_dn_get_linearized(msg->dn));
726 talloc_free(mem_ctx);
727 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
739 copy an attribute list. This only copies the array, not the elements
740 (ie. the elements are left as the same pointers)
742 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
747 for (i=0;attrs && attrs[i];i++) /* noop */ ;
748 ret = talloc_array(mem_ctx, const char *, i+1);
752 for (i=0;attrs && attrs[i];i++) {
761 copy an attribute list. This only copies the array, not the elements
762 (ie. the elements are left as the same pointers). The new attribute is added to the list.
764 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
770 for (i=0;attrs && attrs[i];i++) {
771 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
776 return ldb_attr_list_copy(mem_ctx, attrs);
778 ret = talloc_array(mem_ctx, const char *, i+2);
782 for (i=0;attrs && attrs[i];i++) {
792 return 1 if an attribute is in a list of attributes, or 0 otherwise
794 int ldb_attr_in_list(const char * const *attrs, const char *attr)
797 for (i=0;attrs && attrs[i];i++) {
798 if (ldb_attr_cmp(attrs[i], attr) == 0) {
807 rename the specified attribute in a search result
809 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
811 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
815 el->name = talloc_strdup(msg->elements, replace);
816 if (el->name == NULL) {
817 return LDB_ERR_OPERATIONS_ERROR;
824 copy the specified attribute in a search result to a new attribute
826 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
828 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
832 if (ldb_msg_add(msg, el, 0) != 0) {
833 return LDB_ERR_OPERATIONS_ERROR;
835 return ldb_msg_rename_attr(msg, attr, replace);
839 remove the specified element in a search result
841 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
843 ptrdiff_t n = (el - msg->elements);
844 if (n >= msg->num_elements) {
845 /* should we abort() here? */
848 if (n != msg->num_elements-1) {
849 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
856 remove the specified attribute in a search result
858 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
860 struct ldb_message_element *el;
862 while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
863 ldb_msg_remove_element(msg, el);
868 return a LDAP formatted GeneralizedTime string
870 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
872 struct tm *tm = gmtime(&t);
880 /* we now excatly how long this string will be */
881 ts = talloc_array(mem_ctx, char, 18);
883 /* formatted like: 20040408072012.0Z */
885 "%04u%02u%02u%02u%02u%02u.0Z",
886 tm->tm_year+1900, tm->tm_mon+1,
887 tm->tm_mday, tm->tm_hour, tm->tm_min,
899 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
901 time_t ldb_string_to_time(const char *s)
905 if (s == NULL) return 0;
907 memset(&tm, 0, sizeof(tm));
908 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
909 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
910 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
920 convert a LDAP GeneralizedTime string in ldb_val format to a
923 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
927 if (v == NULL || !v->data || v->length < 17) {
928 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
931 memset(&tm, 0, sizeof(tm));
933 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
934 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
935 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
936 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
947 return a LDAP formatted UTCTime string
949 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
951 struct tm *tm = gmtime(&t);
959 /* we now excatly how long this string will be */
960 ts = talloc_array(mem_ctx, char, 14);
962 /* formatted like: 20040408072012.0Z => 040408072012Z */
964 "%02u%02u%02u%02u%02u%02uZ",
965 (tm->tm_year+1900)%100, tm->tm_mon+1,
966 tm->tm_mday, tm->tm_hour, tm->tm_min,
978 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
980 time_t ldb_string_utc_to_time(const char *s)
984 if (s == NULL) return 0;
986 memset(&tm, 0, sizeof(tm));
987 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
988 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
989 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
992 if (tm.tm_year < 50) {
1002 dump a set of results to a file. Useful from within gdb
1004 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1008 for (i = 0; i < result->count; i++) {
1009 struct ldb_ldif ldif;
1010 fprintf(f, "# record %d\n", i+1);
1011 ldif.changetype = LDB_CHANGETYPE_NONE;
1012 ldif.msg = result->msgs[i];
1013 ldb_ldif_write_file(ldb, f, &ldif);
1018 checks for a string attribute. Returns "1" on match and otherwise "0".
1020 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1021 const char *name, const char *value)
1023 struct ldb_message_element *el;
1026 el = ldb_msg_find_element(msg, name);
1031 val.data = discard_const_p(uint8_t, value);
1032 val.length = strlen(value);
1034 if (ldb_msg_find_val(el, &val)) {