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_includes.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;
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 /* FIXME: we should probably leave this to the schema module to check */
128 if (! ldb_valid_attr_name(attr_name)) {
129 return LDB_ERR_OPERATIONS_ERROR;
132 els = talloc_realloc(msg, msg->elements,
133 struct ldb_message_element, msg->num_elements+1);
136 return LDB_ERR_OPERATIONS_ERROR;
139 els[msg->num_elements].values = NULL;
140 els[msg->num_elements].num_values = 0;
141 els[msg->num_elements].flags = flags;
142 els[msg->num_elements].name = talloc_strdup(els, attr_name);
143 if (!els[msg->num_elements].name) {
145 return LDB_ERR_OPERATIONS_ERROR;
152 *return_el = &els[msg->num_elements-1];
159 add an empty element to a message
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) != 0) {
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-existant 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 return ldb_msg_add_steal_value(msg, attr_name, &val);
267 add a printf formatted element to a message
269 int ldb_msg_add_fmt(struct ldb_message *msg,
270 const char *attr_name, const char *fmt, ...)
277 str = talloc_vasprintf(msg, fmt, ap);
280 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
282 val.data = (uint8_t *)str;
283 val.length = strlen(str);
285 return ldb_msg_add_steal_value(msg, attr_name, &val);
289 compare two ldb_message_element structures
290 assumes case senistive comparison
292 int ldb_msg_element_compare(struct ldb_message_element *el1,
293 struct ldb_message_element *el2)
297 if (el1->num_values != el2->num_values) {
298 return el1->num_values - el2->num_values;
301 for (i=0;i<el1->num_values;i++) {
302 if (!ldb_msg_find_val(el2, &el1->values[i])) {
311 compare two ldb_message_element structures
312 comparing by element name
314 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
315 struct ldb_message_element *el2)
317 return ldb_attr_cmp(el1->name, el2->name);
321 convenience functions to return common types from a message
322 these return the first value if the attribute is multi-valued
324 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
326 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
327 if (!el || el->num_values == 0) {
330 return &el->values[0];
333 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
334 const char *attr_name,
337 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
338 if (!v || !v->data) {
339 return default_value;
341 return strtol((const char *)v->data, NULL, 0);
344 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
345 const char *attr_name,
346 unsigned int default_value)
348 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
349 if (!v || !v->data) {
350 return default_value;
352 return strtoul((const char *)v->data, NULL, 0);
355 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
356 const char *attr_name,
357 int64_t default_value)
359 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
360 if (!v || !v->data) {
361 return default_value;
363 return strtoll((const char *)v->data, NULL, 0);
366 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
367 const char *attr_name,
368 uint64_t default_value)
370 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
371 if (!v || !v->data) {
372 return default_value;
374 return strtoull((const char *)v->data, NULL, 0);
377 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
378 const char *attr_name,
379 double 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 strtod((const char *)v->data, NULL);
388 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
389 const char *attr_name,
392 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
393 if (!v || !v->data) {
394 return default_value;
396 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
399 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
402 return default_value;
405 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
406 const char *attr_name,
407 const char *default_value)
409 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
410 if (!v || !v->data) {
411 return default_value;
413 return (const char *)v->data;
416 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
418 const struct ldb_message *msg,
419 const char *attr_name)
421 struct ldb_dn *res_dn;
422 const struct ldb_val *v;
424 v = ldb_msg_find_ldb_val(msg, attr_name);
425 if (!v || !v->data) {
428 res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
429 if ( ! ldb_dn_validate(res_dn)) {
437 sort the elements of a message by name
439 void ldb_msg_sort_elements(struct ldb_message *msg)
441 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
442 (comparison_fn_t)ldb_msg_element_compare_name);
446 shallow copy a message - copying only the elements array so that the caller
447 can safely add new elements without changing the message
449 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
450 const struct ldb_message *msg)
452 struct ldb_message *msg2;
455 msg2 = talloc(mem_ctx, struct ldb_message);
456 if (msg2 == NULL) return NULL;
460 msg2->elements = talloc_array(msg2, struct ldb_message_element,
462 if (msg2->elements == NULL) goto failed;
464 for (i=0;i<msg2->num_elements;i++) {
465 msg2->elements[i] = msg->elements[i];
477 copy a message, allocating new memory for all parts
479 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
480 const struct ldb_message *msg)
482 struct ldb_message *msg2;
485 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
486 if (msg2 == NULL) return NULL;
488 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
489 if (msg2->dn == NULL) goto failed;
491 for (i=0;i<msg2->num_elements;i++) {
492 struct ldb_message_element *el = &msg2->elements[i];
493 struct ldb_val *values = el->values;
494 el->name = talloc_strdup(msg2->elements, el->name);
495 if (el->name == NULL) goto failed;
496 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
497 for (j=0;j<el->num_values;j++) {
498 el->values[j] = ldb_val_dup(el->values, &values[j]);
499 if (el->values[j].data == NULL && values[j].length != 0) {
514 canonicalise a message, merging elements of the same name
516 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
517 const struct ldb_message *msg)
520 struct ldb_message *msg2;
522 msg2 = ldb_msg_copy(ldb, msg);
523 if (msg2 == NULL) return NULL;
525 ldb_msg_sort_elements(msg2);
527 for (i=1;i<msg2->num_elements;i++) {
528 struct ldb_message_element *el1 = &msg2->elements[i-1];
529 struct ldb_message_element *el2 = &msg2->elements[i];
530 if (ldb_msg_element_compare_name(el1, el2) == 0) {
531 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
532 el1->num_values + el2->num_values);
533 if (el1->values == NULL) {
536 memcpy(el1->values + el1->num_values,
538 sizeof(struct ldb_val) * el2->num_values);
539 el1->num_values += el2->num_values;
540 talloc_free(discard_const_p(char, el2->name));
541 if (i+1<msg2->num_elements) {
542 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
543 (msg2->num_elements - (i+1)));
545 msg2->num_elements--;
555 return a ldb_message representing the differences between msg1 and msg2. If you
556 then use this in a ldb_modify() call it can be used to save edits to a message
558 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
559 struct ldb_message *msg1,
560 struct ldb_message *msg2)
562 struct ldb_message *mod;
563 struct ldb_message_element *el;
566 mod = ldb_msg_new(ldb);
569 mod->num_elements = 0;
570 mod->elements = NULL;
572 msg2 = ldb_msg_canonicalize(ldb, msg2);
577 /* look in msg2 to find elements that need to be added
579 for (i=0;i<msg2->num_elements;i++) {
580 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
582 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
588 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
593 /* look in msg1 to find elements that need to be deleted */
594 for (i=0;i<msg1->num_elements;i++) {
595 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
597 if (ldb_msg_add_empty(mod,
598 msg1->elements[i].name,
599 LDB_FLAG_MOD_DELETE, NULL) != 0) {
608 int ldb_msg_sanity_check(struct ldb_context *ldb,
609 const struct ldb_message *msg)
613 /* basic check on DN */
614 if (msg->dn == NULL) {
615 /* TODO: return also an error string */
616 ldb_set_errstring(ldb, "ldb message lacks a DN!");
617 return LDB_ERR_INVALID_DN_SYNTAX;
620 /* basic syntax checks */
621 for (i = 0; i < msg->num_elements; i++) {
622 for (j = 0; j < msg->elements[i].num_values; j++) {
623 if (msg->elements[i].values[j].length == 0) {
624 TALLOC_CTX *mem_ctx = talloc_new(ldb);
625 /* an attribute cannot be empty */
626 /* TODO: return also an error string */
627 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
628 msg->elements[i].name,
629 ldb_dn_get_linearized(msg->dn));
630 talloc_free(mem_ctx);
631 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
643 copy an attribute list. This only copies the array, not the elements
644 (ie. the elements are left as the same pointers)
646 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
650 for (i=0;attrs[i];i++) /* noop */ ;
651 ret = talloc_array(mem_ctx, const char *, i+1);
655 for (i=0;attrs[i];i++) {
664 copy an attribute list. This only copies the array, not the elements
665 (ie. the elements are left as the same pointers). The new attribute is added to the list.
667 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
672 for (i=0;attrs[i];i++) {
673 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
678 return ldb_attr_list_copy(mem_ctx, attrs);
680 ret = talloc_array(mem_ctx, const char *, i+2);
684 for (i=0;attrs[i];i++) {
694 return 1 if an attribute is in a list of attributes, or 0 otherwise
696 int ldb_attr_in_list(const char * const *attrs, const char *attr)
699 for (i=0;attrs && attrs[i];i++) {
700 if (ldb_attr_cmp(attrs[i], attr) == 0) {
709 rename the specified attribute in a search result
711 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
713 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
717 el->name = talloc_strdup(msg->elements, replace);
718 if (el->name == NULL) {
719 return LDB_ERR_OPERATIONS_ERROR;
726 copy the specified attribute in a search result to a new attribute
728 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
730 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
734 if (ldb_msg_add(msg, el, 0) != 0) {
735 return LDB_ERR_OPERATIONS_ERROR;
737 return ldb_msg_rename_attr(msg, attr, replace);
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));
754 remove the specified attribute in a search result
756 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
758 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
760 ldb_msg_remove_element(msg, el);
765 return a LDAP formatted GeneralizedTime string
767 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
769 struct tm *tm = gmtime(&t);
777 /* we now excatly how long this string will be */
778 ts = talloc_array(mem_ctx, char, 18);
780 /* formatted like: 20040408072012.0Z */
782 "%04u%02u%02u%02u%02u%02u.0Z",
783 tm->tm_year+1900, tm->tm_mon+1,
784 tm->tm_mday, tm->tm_hour, tm->tm_min,
796 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
798 time_t ldb_string_to_time(const char *s)
802 if (s == NULL) return 0;
804 memset(&tm, 0, sizeof(tm));
805 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
806 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
807 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
817 return a LDAP formatted UTCTime string
819 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
821 struct tm *tm = gmtime(&t);
829 /* we now excatly how long this string will be */
830 ts = talloc_array(mem_ctx, char, 14);
832 /* formatted like: 20040408072012.0Z => 040408072012Z */
834 "%02u%02u%02u%02u%02u%02uZ",
835 (tm->tm_year+1900)%100, tm->tm_mon+1,
836 tm->tm_mday, tm->tm_hour, tm->tm_min,
848 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
850 time_t ldb_string_utc_to_time(const char *s)
854 if (s == NULL) return 0;
856 memset(&tm, 0, sizeof(tm));
857 if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
858 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
859 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
862 if (tm.tm_year < 50) {
872 dump a set of results to a file. Useful from within gdb
874 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
878 for (i = 0; i < result->count; i++) {
879 struct ldb_ldif ldif;
880 fprintf(f, "# record %d\n", i+1);
881 ldif.changetype = LDB_CHANGETYPE_NONE;
882 ldif.msg = result->msgs[i];
883 ldb_ldif_write_file(ldb, f, &ldif);
887 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
889 struct ldb_message_element *el;
892 el = ldb_msg_find_element(msg, name);
896 val.data = discard_const_p(uint8_t, value);
897 val.length = strlen(value);
899 if (ldb_msg_find_val(el, &val))