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) != LDB_SUCCESS) {
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-existent 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 if (val.length == 0) {
259 /* allow empty strings as non-existent attributes */
263 return ldb_msg_add_steal_value(msg, attr_name, &val);
267 add a DN element to a message
268 WARNING: this uses the linearized string from the dn, and does not
271 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
274 return ldb_msg_add_steal_string(msg, attr_name,
275 ldb_dn_alloc_linearized(msg, dn));
279 add a printf formatted element to a message
281 int ldb_msg_add_fmt(struct ldb_message *msg,
282 const char *attr_name, const char *fmt, ...)
289 str = talloc_vasprintf(msg, fmt, ap);
292 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
294 val.data = (uint8_t *)str;
295 val.length = strlen(str);
297 return ldb_msg_add_steal_value(msg, attr_name, &val);
301 compare two ldb_message_element structures
302 assumes case sensitive comparison
304 int ldb_msg_element_compare(struct ldb_message_element *el1,
305 struct ldb_message_element *el2)
309 if (el1->num_values != el2->num_values) {
310 return el1->num_values - el2->num_values;
313 for (i=0;i<el1->num_values;i++) {
314 if (!ldb_msg_find_val(el2, &el1->values[i])) {
323 compare two ldb_message_element structures
324 comparing by element name
326 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
327 struct ldb_message_element *el2)
329 return ldb_attr_cmp(el1->name, el2->name);
333 convenience functions to return common types from a message
334 these return the first value if the attribute is multi-valued
336 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
337 const char *attr_name)
339 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
340 if (!el || el->num_values == 0) {
343 return &el->values[0];
346 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
347 const char *attr_name,
350 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
351 if (!v || !v->data) {
352 return default_value;
354 return strtol((const char *)v->data, NULL, 0);
357 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
358 const char *attr_name,
359 unsigned int default_value)
362 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
363 if (!v || !v->data) {
364 return default_value;
367 /* in LDAP there're only int32_t values */
369 ret = strtol((const char *)v->data, NULL, 0);
374 return strtoul((const char *)v->data, NULL, 0);
377 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
378 const char *attr_name,
379 int64_t default_value)
381 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
382 if (!v || !v->data) {
383 return default_value;
385 return strtoll((const char *)v->data, NULL, 0);
388 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
389 const char *attr_name,
390 uint64_t default_value)
393 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
394 if (!v || !v->data) {
395 return default_value;
398 /* in LDAP there're only int64_t values */
400 ret = strtoll((const char *)v->data, NULL, 0);
405 return strtoull((const char *)v->data, NULL, 0);
408 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
409 const char *attr_name,
410 double default_value)
412 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
413 if (!v || !v->data) {
414 return default_value;
416 return strtod((const char *)v->data, NULL);
419 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
420 const char *attr_name,
423 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
424 if (!v || !v->data) {
425 return default_value;
427 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
430 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
433 return default_value;
436 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
437 const char *attr_name,
438 const char *default_value)
440 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
441 if (!v || !v->data) {
442 return default_value;
444 return (const char *)v->data;
447 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
449 const struct ldb_message *msg,
450 const char *attr_name)
452 struct ldb_dn *res_dn;
453 const struct ldb_val *v;
455 v = ldb_msg_find_ldb_val(msg, attr_name);
456 if (!v || !v->data) {
459 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
460 if ( ! ldb_dn_validate(res_dn)) {
468 sort the elements of a message by name
470 void ldb_msg_sort_elements(struct ldb_message *msg)
472 TYPESAFE_QSORT(msg->elements, msg->num_elements,
473 ldb_msg_element_compare_name);
477 shallow copy a message - copying only the elements array so that the caller
478 can safely add new elements without changing the message
480 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
481 const struct ldb_message *msg)
483 struct ldb_message *msg2;
486 msg2 = talloc(mem_ctx, struct ldb_message);
487 if (msg2 == NULL) return NULL;
491 msg2->elements = talloc_array(msg2, struct ldb_message_element,
493 if (msg2->elements == NULL) goto failed;
495 for (i=0;i<msg2->num_elements;i++) {
496 msg2->elements[i] = msg->elements[i];
508 copy a message, allocating new memory for all parts
510 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
511 const struct ldb_message *msg)
513 struct ldb_message *msg2;
516 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
517 if (msg2 == NULL) return NULL;
519 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
520 if (msg2->dn == NULL) goto failed;
522 for (i=0;i<msg2->num_elements;i++) {
523 struct ldb_message_element *el = &msg2->elements[i];
524 struct ldb_val *values = el->values;
525 el->name = talloc_strdup(msg2->elements, el->name);
526 if (el->name == NULL) goto failed;
527 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
528 for (j=0;j<el->num_values;j++) {
529 el->values[j] = ldb_val_dup(el->values, &values[j]);
530 if (el->values[j].data == NULL && values[j].length != 0) {
545 canonicalise a message, merging elements of the same name
547 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
548 const struct ldb_message *msg)
551 struct ldb_message *msg2;
553 msg2 = ldb_msg_copy(ldb, msg);
554 if (msg2 == NULL) return NULL;
556 ldb_msg_sort_elements(msg2);
558 for (i=1;i<msg2->num_elements;i++) {
559 struct ldb_message_element *el1 = &msg2->elements[i-1];
560 struct ldb_message_element *el2 = &msg2->elements[i];
561 if (ldb_msg_element_compare_name(el1, el2) == 0) {
562 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
563 el1->num_values + el2->num_values);
564 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
567 memcpy(el1->values + el1->num_values,
569 sizeof(struct ldb_val) * el2->num_values);
570 el1->num_values += el2->num_values;
571 talloc_free(discard_const_p(char, el2->name));
572 if (i+1<msg2->num_elements) {
573 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
574 (msg2->num_elements - (i+1)));
576 msg2->num_elements--;
586 return a ldb_message representing the differences between msg1 and msg2. If you
587 then use this in a ldb_modify() call it can be used to save edits to a message
589 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
590 struct ldb_message *msg1,
591 struct ldb_message *msg2)
594 struct ldb_message *mod;
596 /* allocate mod message in NULL context
597 * so it should appear as 'leaked' in talloc reports */
598 ldb_ret = ldb_msg_diff_ex(ldb, msg1, msg2,
599 (TALLOC_CTX*)NULL, &mod);
600 if (ldb_ret != LDB_SUCCESS) {
608 * return a ldb_message representing the differences between msg1 and msg2.
609 * If you then use this in a ldb_modify() call it can be used to save edits to a message
611 * Result message is constructed as follows:
612 * - LDB_FLAG_MOD_ADD - elements found only in msg2
613 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
614 * Value for msg2 element is used
615 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
617 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
619 int ldb_msg_diff_ex(struct ldb_context *ldb,
620 struct ldb_message *msg1,
621 struct ldb_message *msg2,
623 struct ldb_message **_msg_out)
627 struct ldb_message *mod;
628 struct ldb_message_element *el;
629 TALLOC_CTX *temp_ctx;
631 temp_ctx = talloc_new(mem_ctx);
633 return LDB_ERR_OPERATIONS_ERROR;
636 mod = ldb_msg_new(temp_ctx);
642 mod->num_elements = 0;
643 mod->elements = NULL;
645 /* canonicalize msg2 so we have no
646 * repeated elements */
647 msg2 = ldb_msg_canonicalize(ldb, msg2);
652 /* steal msg2 into mod context as it is
653 * allocated in ldb's context */
654 talloc_steal(mod, msg2);
656 /* look in msg2 to find elements that need to be added
658 for (i=0;i<msg2->num_elements;i++) {
659 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
661 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
665 ldb_res = ldb_msg_add(mod,
667 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
668 if (ldb_res != LDB_SUCCESS) {
673 /* look in msg1 to find elements that need to be deleted */
674 for (i=0;i<msg1->num_elements;i++) {
675 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
677 ldb_res = ldb_msg_add_empty(mod,
678 msg1->elements[i].name,
679 LDB_FLAG_MOD_DELETE, NULL);
680 if (ldb_res != LDB_SUCCESS) {
686 /* steal resulting message into supplied context */
687 talloc_steal(mem_ctx, mod);
690 talloc_free(temp_ctx);
694 talloc_free(temp_ctx);
695 return LDB_ERR_OPERATIONS_ERROR;
699 int ldb_msg_sanity_check(struct ldb_context *ldb,
700 const struct ldb_message *msg)
704 /* basic check on DN */
705 if (msg->dn == NULL) {
706 /* TODO: return also an error string */
707 ldb_set_errstring(ldb, "ldb message lacks a DN!");
708 return LDB_ERR_INVALID_DN_SYNTAX;
711 /* basic syntax checks */
712 for (i = 0; i < msg->num_elements; i++) {
713 for (j = 0; j < msg->elements[i].num_values; j++) {
714 if (msg->elements[i].values[j].length == 0) {
715 TALLOC_CTX *mem_ctx = talloc_new(ldb);
716 /* an attribute cannot be empty */
717 /* TODO: return also an error string */
718 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
719 msg->elements[i].name,
720 ldb_dn_get_linearized(msg->dn));
721 talloc_free(mem_ctx);
722 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
734 copy an attribute list. This only copies the array, not the elements
735 (ie. the elements are left as the same pointers)
737 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
742 for (i=0;attrs && attrs[i];i++) /* noop */ ;
743 ret = talloc_array(mem_ctx, const char *, i+1);
747 for (i=0;attrs && attrs[i];i++) {
756 copy an attribute list. This only copies the array, not the elements
757 (ie. the elements are left as the same pointers). The new attribute is added to the list.
759 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
765 for (i=0;attrs && attrs[i];i++) {
766 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
771 return ldb_attr_list_copy(mem_ctx, attrs);
773 ret = talloc_array(mem_ctx, const char *, i+2);
777 for (i=0;attrs && attrs[i];i++) {
787 return 1 if an attribute is in a list of attributes, or 0 otherwise
789 int ldb_attr_in_list(const char * const *attrs, const char *attr)
792 for (i=0;attrs && attrs[i];i++) {
793 if (ldb_attr_cmp(attrs[i], attr) == 0) {
802 rename the specified attribute in a search result
804 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
806 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
810 el->name = talloc_strdup(msg->elements, replace);
811 if (el->name == NULL) {
812 return LDB_ERR_OPERATIONS_ERROR;
819 copy the specified attribute in a search result to a new attribute
821 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
823 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
827 if (ldb_msg_add(msg, el, 0) != 0) {
828 return LDB_ERR_OPERATIONS_ERROR;
830 return ldb_msg_rename_attr(msg, attr, replace);
834 remove the specified element in a search result
836 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
838 ptrdiff_t n = (el - msg->elements);
839 if (n >= msg->num_elements) {
840 /* should we abort() here? */
843 if (n != msg->num_elements-1) {
844 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
851 remove the specified attribute in a search result
853 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
855 struct ldb_message_element *el;
857 while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
858 ldb_msg_remove_element(msg, el);
863 return a LDAP formatted GeneralizedTime string
865 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
867 struct tm *tm = gmtime(&t);
875 /* we now excatly how long this string will be */
876 ts = talloc_array(mem_ctx, char, 18);
878 /* formatted like: 20040408072012.0Z */
880 "%04u%02u%02u%02u%02u%02u.0Z",
881 tm->tm_year+1900, tm->tm_mon+1,
882 tm->tm_mday, tm->tm_hour, tm->tm_min,
894 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
896 time_t ldb_string_to_time(const char *s)
900 if (s == NULL) return 0;
902 memset(&tm, 0, sizeof(tm));
903 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
904 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
905 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
915 convert a LDAP GeneralizedTime string in ldb_val format to a
918 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
922 if (v == NULL || !v->data || v->length < 17) {
923 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
926 memset(&tm, 0, sizeof(tm));
928 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
929 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
930 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
931 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
942 return a LDAP formatted UTCTime string
944 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
946 struct tm *tm = gmtime(&t);
954 /* we now excatly how long this string will be */
955 ts = talloc_array(mem_ctx, char, 14);
957 /* formatted like: 20040408072012.0Z => 040408072012Z */
959 "%02u%02u%02u%02u%02u%02uZ",
960 (tm->tm_year+1900)%100, tm->tm_mon+1,
961 tm->tm_mday, tm->tm_hour, tm->tm_min,
973 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
975 time_t ldb_string_utc_to_time(const char *s)
979 if (s == NULL) return 0;
981 memset(&tm, 0, sizeof(tm));
982 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
983 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
984 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
987 if (tm.tm_year < 50) {
997 dump a set of results to a file. Useful from within gdb
999 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1003 for (i = 0; i < result->count; i++) {
1004 struct ldb_ldif ldif;
1005 fprintf(f, "# record %d\n", i+1);
1006 ldif.changetype = LDB_CHANGETYPE_NONE;
1007 ldif.msg = result->msgs[i];
1008 ldb_ldif_write_file(ldb, f, &ldif);
1013 checks for a string attribute. Returns "1" on match and otherwise "0".
1015 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1016 const char *name, const char *value)
1018 struct ldb_message_element *el;
1021 el = ldb_msg_find_element(msg, name);
1026 val.data = discard_const_p(uint8_t, value);
1027 val.length = strlen(value);
1029 if (ldb_msg_find_val(el, &val)) {