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,
325 const char *attr_name)
327 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
328 if (!el || el->num_values == 0) {
331 return &el->values[0];
334 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
335 const char *attr_name,
338 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
339 if (!v || !v->data) {
340 return default_value;
342 return strtol((const char *)v->data, NULL, 0);
345 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
346 const char *attr_name,
347 unsigned int default_value)
349 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
350 if (!v || !v->data) {
351 return default_value;
353 return strtoul((const char *)v->data, NULL, 0);
356 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
357 const char *attr_name,
358 int64_t default_value)
360 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
361 if (!v || !v->data) {
362 return default_value;
364 return strtoll((const char *)v->data, NULL, 0);
367 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
368 const char *attr_name,
369 uint64_t default_value)
371 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
372 if (!v || !v->data) {
373 return default_value;
375 return strtoull((const char *)v->data, NULL, 0);
378 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
379 const char *attr_name,
380 double default_value)
382 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
383 if (!v || !v->data) {
384 return default_value;
386 return strtod((const char *)v->data, NULL);
389 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
390 const char *attr_name,
393 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
394 if (!v || !v->data) {
395 return default_value;
397 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
400 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
403 return default_value;
406 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
407 const char *attr_name,
408 const char *default_value)
410 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
411 if (!v || !v->data) {
412 return default_value;
414 return (const char *)v->data;
417 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
419 const struct ldb_message *msg,
420 const char *attr_name)
422 struct ldb_dn *res_dn;
423 const struct ldb_val *v;
425 v = ldb_msg_find_ldb_val(msg, attr_name);
426 if (!v || !v->data) {
429 res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
430 if ( ! ldb_dn_validate(res_dn)) {
438 sort the elements of a message by name
440 void ldb_msg_sort_elements(struct ldb_message *msg)
442 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
443 (comparison_fn_t)ldb_msg_element_compare_name);
447 shallow copy a message - copying only the elements array so that the caller
448 can safely add new elements without changing the message
450 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
451 const struct ldb_message *msg)
453 struct ldb_message *msg2;
456 msg2 = talloc(mem_ctx, struct ldb_message);
457 if (msg2 == NULL) return NULL;
461 msg2->elements = talloc_array(msg2, struct ldb_message_element,
463 if (msg2->elements == NULL) goto failed;
465 for (i=0;i<msg2->num_elements;i++) {
466 msg2->elements[i] = msg->elements[i];
478 copy a message, allocating new memory for all parts
480 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
481 const struct ldb_message *msg)
483 struct ldb_message *msg2;
486 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
487 if (msg2 == NULL) return NULL;
489 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
490 if (msg2->dn == NULL) goto failed;
492 for (i=0;i<msg2->num_elements;i++) {
493 struct ldb_message_element *el = &msg2->elements[i];
494 struct ldb_val *values = el->values;
495 el->name = talloc_strdup(msg2->elements, el->name);
496 if (el->name == NULL) goto failed;
497 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
498 for (j=0;j<el->num_values;j++) {
499 el->values[j] = ldb_val_dup(el->values, &values[j]);
500 if (el->values[j].data == NULL && values[j].length != 0) {
515 canonicalise a message, merging elements of the same name
517 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
518 const struct ldb_message *msg)
521 struct ldb_message *msg2;
523 msg2 = ldb_msg_copy(ldb, msg);
524 if (msg2 == NULL) return NULL;
526 ldb_msg_sort_elements(msg2);
528 for (i=1;i<msg2->num_elements;i++) {
529 struct ldb_message_element *el1 = &msg2->elements[i-1];
530 struct ldb_message_element *el2 = &msg2->elements[i];
531 if (ldb_msg_element_compare_name(el1, el2) == 0) {
532 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
533 el1->num_values + el2->num_values);
534 if (el1->values == NULL) {
537 memcpy(el1->values + el1->num_values,
539 sizeof(struct ldb_val) * el2->num_values);
540 el1->num_values += el2->num_values;
541 talloc_free(discard_const_p(char, el2->name));
542 if (i+1<msg2->num_elements) {
543 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
544 (msg2->num_elements - (i+1)));
546 msg2->num_elements--;
556 return a ldb_message representing the differences between msg1 and msg2. If you
557 then use this in a ldb_modify() call it can be used to save edits to a message
559 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
560 struct ldb_message *msg1,
561 struct ldb_message *msg2)
563 struct ldb_message *mod;
564 struct ldb_message_element *el;
567 mod = ldb_msg_new(ldb);
570 mod->num_elements = 0;
571 mod->elements = NULL;
573 msg2 = ldb_msg_canonicalize(ldb, msg2);
578 /* look in msg2 to find elements that need to be added
580 for (i=0;i<msg2->num_elements;i++) {
581 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
583 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
589 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
594 /* look in msg1 to find elements that need to be deleted */
595 for (i=0;i<msg1->num_elements;i++) {
596 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
598 if (ldb_msg_add_empty(mod,
599 msg1->elements[i].name,
600 LDB_FLAG_MOD_DELETE, NULL) != 0) {
609 int ldb_msg_sanity_check(struct ldb_context *ldb,
610 const struct ldb_message *msg)
614 /* basic check on DN */
615 if (msg->dn == NULL) {
616 /* TODO: return also an error string */
617 ldb_set_errstring(ldb, "ldb message lacks a DN!");
618 return LDB_ERR_INVALID_DN_SYNTAX;
621 /* basic syntax checks */
622 for (i = 0; i < msg->num_elements; i++) {
623 for (j = 0; j < msg->elements[i].num_values; j++) {
624 if (msg->elements[i].values[j].length == 0) {
625 TALLOC_CTX *mem_ctx = talloc_new(ldb);
626 /* an attribute cannot be empty */
627 /* TODO: return also an error string */
628 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
629 msg->elements[i].name,
630 ldb_dn_get_linearized(msg->dn));
631 talloc_free(mem_ctx);
632 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
644 copy an attribute list. This only copies the array, not the elements
645 (ie. the elements are left as the same pointers)
647 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
651 for (i=0;attrs[i];i++) /* noop */ ;
652 ret = talloc_array(mem_ctx, const char *, i+1);
656 for (i=0;attrs[i];i++) {
665 copy an attribute list. This only copies the array, not the elements
666 (ie. the elements are left as the same pointers). The new attribute is added to the list.
668 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
673 for (i=0;attrs[i];i++) {
674 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
679 return ldb_attr_list_copy(mem_ctx, attrs);
681 ret = talloc_array(mem_ctx, const char *, i+2);
685 for (i=0;attrs[i];i++) {
695 return 1 if an attribute is in a list of attributes, or 0 otherwise
697 int ldb_attr_in_list(const char * const *attrs, const char *attr)
700 for (i=0;attrs && attrs[i];i++) {
701 if (ldb_attr_cmp(attrs[i], attr) == 0) {
710 rename the specified attribute in a search result
712 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
714 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
718 el->name = talloc_strdup(msg->elements, replace);
719 if (el->name == NULL) {
720 return LDB_ERR_OPERATIONS_ERROR;
727 copy the specified attribute in a search result to a new attribute
729 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
731 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
735 if (ldb_msg_add(msg, el, 0) != 0) {
736 return LDB_ERR_OPERATIONS_ERROR;
738 return ldb_msg_rename_attr(msg, attr, replace);
742 remove the specified element in a search result
744 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
746 int n = (el - msg->elements);
747 if (n != msg->num_elements-1) {
748 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
755 remove the specified attribute in a search result
757 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
759 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
761 ldb_msg_remove_element(msg, el);
766 return a LDAP formatted GeneralizedTime string
768 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
770 struct tm *tm = gmtime(&t);
778 /* we now excatly how long this string will be */
779 ts = talloc_array(mem_ctx, char, 18);
781 /* formatted like: 20040408072012.0Z */
783 "%04u%02u%02u%02u%02u%02u.0Z",
784 tm->tm_year+1900, tm->tm_mon+1,
785 tm->tm_mday, tm->tm_hour, tm->tm_min,
797 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
799 time_t ldb_string_to_time(const char *s)
803 if (s == NULL) return 0;
805 memset(&tm, 0, sizeof(tm));
806 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
807 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
808 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
818 return a LDAP formatted UTCTime string
820 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
822 struct tm *tm = gmtime(&t);
830 /* we now excatly how long this string will be */
831 ts = talloc_array(mem_ctx, char, 14);
833 /* formatted like: 20040408072012.0Z => 040408072012Z */
835 "%02u%02u%02u%02u%02u%02uZ",
836 (tm->tm_year+1900)%100, tm->tm_mon+1,
837 tm->tm_mday, tm->tm_hour, tm->tm_min,
849 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
851 time_t ldb_string_utc_to_time(const char *s)
855 if (s == NULL) return 0;
857 memset(&tm, 0, sizeof(tm));
858 if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
859 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
860 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
863 if (tm.tm_year < 50) {
873 dump a set of results to a file. Useful from within gdb
875 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
879 for (i = 0; i < result->count; i++) {
880 struct ldb_ldif ldif;
881 fprintf(f, "# record %d\n", i+1);
882 ldif.changetype = LDB_CHANGETYPE_NONE;
883 ldif.msg = result->msgs[i];
884 ldb_ldif_write_file(ldb, f, &ldif);
888 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
890 struct ldb_message_element *el;
893 el = ldb_msg_find_element(msg, name);
897 val.data = discard_const_p(uint8_t, value);
898 val.length = strlen(value);
900 if (ldb_msg_find_val(el, &val))