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 2 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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb message component utility functions
30 * Description: functions for manipulating ldb_message structures
32 * Author: Andrew Tridgell
35 #include "ldb_includes.h"
38 create a new ldb_message in a given memory context (NULL for top level)
40 struct ldb_message *ldb_msg_new(void *mem_ctx)
42 return talloc_zero(mem_ctx, struct ldb_message);
46 find an element in a message by attribute name
48 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
49 const char *attr_name)
52 for (i=0;i<msg->num_elements;i++) {
53 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
54 return &msg->elements[i];
61 see if two ldb_val structures contain exactly the same data
62 return 1 for a match, 0 for a mis-match
64 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
66 if (v1->length != v2->length) return 0;
68 if (v1->length == 0) return 1;
70 if (memcmp(v1->data, v2->data, v1->length) == 0) {
78 find a value in an element
79 assumes case sensitive comparison
81 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
85 for (i=0;i<el->num_values;i++) {
86 if (ldb_val_equal_exact(val, &el->values[i])) {
87 return &el->values[i];
94 duplicate a ldb_val structure
96 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
99 v2.length = v->length;
100 if (v->data == NULL) {
105 /* the +1 is to cope with buggy C library routines like strndup
106 that look one byte beyond */
107 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
113 memcpy(v2.data, v->data, v->length);
114 ((char *)v2.data)[v->length] = 0;
119 add an empty element to a message
121 int ldb_msg_add_empty( struct ldb_message *msg,
122 const char *attr_name,
124 struct ldb_message_element **return_el)
126 struct ldb_message_element *els;
128 /* FIXME: we should probably leave this to the schema module to check */
129 if (! ldb_valid_attr_name(attr_name)) {
130 return LDB_ERR_OPERATIONS_ERROR;
133 els = talloc_realloc(msg, msg->elements,
134 struct ldb_message_element, msg->num_elements+1);
137 return LDB_ERR_OPERATIONS_ERROR;
140 els[msg->num_elements].values = NULL;
141 els[msg->num_elements].num_values = 0;
142 els[msg->num_elements].flags = flags;
143 els[msg->num_elements].name = talloc_strdup(els, attr_name);
144 if (!els[msg->num_elements].name) {
146 return LDB_ERR_OPERATIONS_ERROR;
153 *return_el = &els[msg->num_elements-1];
160 add an empty element to a message
162 int ldb_msg_add(struct ldb_message *msg,
163 const struct ldb_message_element *el,
166 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
167 return LDB_ERR_OPERATIONS_ERROR;
170 msg->elements[msg->num_elements-1] = *el;
171 msg->elements[msg->num_elements-1].flags = flags;
177 add a value to a message
179 int ldb_msg_add_value(struct ldb_message *msg,
180 const char *attr_name,
181 const struct ldb_val *val,
182 struct ldb_message_element **return_el)
184 struct ldb_message_element *el;
185 struct ldb_val *vals;
188 el = ldb_msg_find_element(msg, attr_name);
190 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
191 if (ret != LDB_SUCCESS) {
196 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
199 return LDB_ERR_OPERATIONS_ERROR;
202 el->values[el->num_values] = *val;
214 add a value to a message, stealing it into the 'right' place
216 int ldb_msg_add_steal_value(struct ldb_message *msg,
217 const char *attr_name,
221 struct ldb_message_element *el;
223 ret = ldb_msg_add_value(msg, attr_name, val, &el);
224 if (ret == LDB_SUCCESS) {
225 talloc_steal(el->values, val->data);
232 add a string element to a message
234 int ldb_msg_add_string(struct ldb_message *msg,
235 const char *attr_name, const char *str)
239 val.data = discard_const_p(uint8_t, str);
240 val.length = strlen(str);
242 if (val.length == 0) {
243 /* allow empty strings as non-existant attributes */
247 return ldb_msg_add_value(msg, attr_name, &val, NULL);
251 add a string element to a message, stealing it into the 'right' place
253 int ldb_msg_add_steal_string(struct ldb_message *msg,
254 const char *attr_name, char *str)
258 val.data = (uint8_t *)str;
259 val.length = strlen(str);
261 return ldb_msg_add_steal_value(msg, attr_name, &val);
265 add a printf formatted element to a message
267 int ldb_msg_add_fmt(struct ldb_message *msg,
268 const char *attr_name, const char *fmt, ...)
275 str = talloc_vasprintf(msg, fmt, ap);
278 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
280 val.data = (uint8_t *)str;
281 val.length = strlen(str);
283 return ldb_msg_add_steal_value(msg, attr_name, &val);
287 compare two ldb_message_element structures
288 assumes case senistive comparison
290 int ldb_msg_element_compare(struct ldb_message_element *el1,
291 struct ldb_message_element *el2)
295 if (el1->num_values != el2->num_values) {
296 return el1->num_values - el2->num_values;
299 for (i=0;i<el1->num_values;i++) {
300 if (!ldb_msg_find_val(el2, &el1->values[i])) {
309 compare two ldb_message_element structures
310 comparing by element name
312 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
313 struct ldb_message_element *el2)
315 return ldb_attr_cmp(el1->name, el2->name);
319 convenience functions to return common types from a message
320 these return the first value if the attribute is multi-valued
322 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
324 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
325 if (!el || el->num_values == 0) {
328 return &el->values[0];
331 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
332 const char *attr_name,
335 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
336 if (!v || !v->data) {
337 return default_value;
339 return strtol((const char *)v->data, NULL, 0);
342 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
343 const char *attr_name,
344 unsigned int default_value)
346 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
347 if (!v || !v->data) {
348 return default_value;
350 return strtoul((const char *)v->data, NULL, 0);
353 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
354 const char *attr_name,
355 int64_t default_value)
357 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
358 if (!v || !v->data) {
359 return default_value;
361 return strtoll((const char *)v->data, NULL, 0);
364 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
365 const char *attr_name,
366 uint64_t default_value)
368 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
369 if (!v || !v->data) {
370 return default_value;
372 return strtoull((const char *)v->data, NULL, 0);
375 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
376 const char *attr_name,
377 double default_value)
379 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
380 if (!v || !v->data) {
381 return default_value;
383 return strtod((const char *)v->data, NULL);
386 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
387 const char *attr_name,
390 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
391 if (!v || !v->data) {
392 return default_value;
394 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
397 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
400 return default_value;
403 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
404 const char *attr_name,
405 const char *default_value)
407 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
408 if (!v || !v->data) {
409 return default_value;
411 return (const char *)v->data;
414 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
416 const struct ldb_message *msg,
417 const char *attr_name)
419 struct ldb_dn *res_dn;
420 const struct ldb_val *v;
422 v = ldb_msg_find_ldb_val(msg, attr_name);
423 if (!v || !v->data) {
426 res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
427 if ( ! ldb_dn_validate(res_dn)) {
435 sort the elements of a message by name
437 void ldb_msg_sort_elements(struct ldb_message *msg)
439 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
440 (comparison_fn_t)ldb_msg_element_compare_name);
444 shallow copy a message - copying only the elements array so that the caller
445 can safely add new elements without changing the message
447 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
448 const struct ldb_message *msg)
450 struct ldb_message *msg2;
453 msg2 = talloc(mem_ctx, struct ldb_message);
454 if (msg2 == NULL) return NULL;
458 msg2->elements = talloc_array(msg2, struct ldb_message_element,
460 if (msg2->elements == NULL) goto failed;
462 for (i=0;i<msg2->num_elements;i++) {
463 msg2->elements[i] = msg->elements[i];
475 copy a message, allocating new memory for all parts
477 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
478 const struct ldb_message *msg)
480 struct ldb_message *msg2;
483 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
484 if (msg2 == NULL) return NULL;
486 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
487 if (msg2->dn == NULL) goto failed;
489 for (i=0;i<msg2->num_elements;i++) {
490 struct ldb_message_element *el = &msg2->elements[i];
491 struct ldb_val *values = el->values;
492 el->name = talloc_strdup(msg2->elements, el->name);
493 if (el->name == NULL) goto failed;
494 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
495 for (j=0;j<el->num_values;j++) {
496 el->values[j] = ldb_val_dup(el->values, &values[j]);
497 if (el->values[j].data == NULL && values[j].length != 0) {
512 canonicalise a message, merging elements of the same name
514 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
515 const struct ldb_message *msg)
518 struct ldb_message *msg2;
520 msg2 = ldb_msg_copy(ldb, msg);
521 if (msg2 == NULL) return NULL;
523 ldb_msg_sort_elements(msg2);
525 for (i=1;i<msg2->num_elements;i++) {
526 struct ldb_message_element *el1 = &msg2->elements[i-1];
527 struct ldb_message_element *el2 = &msg2->elements[i];
528 if (ldb_msg_element_compare_name(el1, el2) == 0) {
529 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
530 el1->num_values + el2->num_values);
531 if (el1->values == NULL) {
534 memcpy(el1->values + el1->num_values,
536 sizeof(struct ldb_val) * el2->num_values);
537 el1->num_values += el2->num_values;
538 talloc_free(discard_const_p(char, el2->name));
539 if (i+1<msg2->num_elements) {
540 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
541 (msg2->num_elements - (i+1)));
543 msg2->num_elements--;
553 return a ldb_message representing the differences between msg1 and msg2. If you
554 then use this in a ldb_modify() call it can be used to save edits to a message
556 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
557 struct ldb_message *msg1,
558 struct ldb_message *msg2)
560 struct ldb_message *mod;
561 struct ldb_message_element *el;
564 mod = ldb_msg_new(ldb);
567 mod->num_elements = 0;
568 mod->elements = NULL;
570 msg2 = ldb_msg_canonicalize(ldb, msg2);
575 /* look in msg2 to find elements that need to be added
577 for (i=0;i<msg2->num_elements;i++) {
578 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
580 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
586 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
591 /* look in msg1 to find elements that need to be deleted */
592 for (i=0;i<msg1->num_elements;i++) {
593 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
595 if (ldb_msg_add_empty(mod,
596 msg1->elements[i].name,
597 LDB_FLAG_MOD_DELETE, NULL) != 0) {
606 int ldb_msg_sanity_check(struct ldb_context *ldb,
607 const struct ldb_message *msg)
611 /* basic check on DN */
612 if (msg->dn == NULL) {
613 /* TODO: return also an error string */
614 ldb_set_errstring(ldb, "ldb message lacks a DN!");
615 return LDB_ERR_INVALID_DN_SYNTAX;
618 /* basic syntax checks */
619 for (i = 0; i < msg->num_elements; i++) {
620 for (j = 0; j < msg->elements[i].num_values; j++) {
621 if (msg->elements[i].values[j].length == 0) {
622 TALLOC_CTX *mem_ctx = talloc_new(ldb);
623 /* an attribute cannot be empty */
624 /* TODO: return also an error string */
625 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
626 msg->elements[i].name,
627 ldb_dn_get_linearized(msg->dn));
628 talloc_free(mem_ctx);
629 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
641 copy an attribute list. This only copies the array, not the elements
642 (ie. the elements are left as the same pointers)
644 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
648 for (i=0;attrs[i];i++) /* noop */ ;
649 ret = talloc_array(mem_ctx, const char *, i+1);
653 for (i=0;attrs[i];i++) {
662 copy an attribute list. This only copies the array, not the elements
663 (ie. the elements are left as the same pointers). The new attribute is added to the list.
665 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
670 for (i=0;attrs[i];i++) {
671 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
676 return ldb_attr_list_copy(mem_ctx, attrs);
678 ret = talloc_array(mem_ctx, const char *, i+2);
682 for (i=0;attrs[i];i++) {
692 return 1 if an attribute is in a list of attributes, or 0 otherwise
694 int ldb_attr_in_list(const char * const *attrs, const char *attr)
697 for (i=0;attrs && attrs[i];i++) {
698 if (ldb_attr_cmp(attrs[i], attr) == 0) {
707 rename the specified attribute in a search result
709 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
711 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
715 el->name = talloc_strdup(msg->elements, replace);
716 if (el->name == NULL) {
717 return LDB_ERR_OPERATIONS_ERROR;
724 copy the specified attribute in a search result to a new attribute
726 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
728 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
732 if (ldb_msg_add(msg, el, 0) != 0) {
733 return LDB_ERR_OPERATIONS_ERROR;
735 return ldb_msg_rename_attr(msg, attr, replace);
739 remove the specified element in a search result
741 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
743 int n = (el - msg->elements);
744 if (n != msg->num_elements-1) {
745 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
752 remove the specified attribute in a search result
754 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
756 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
758 ldb_msg_remove_element(msg, el);
763 return a LDAP formatted GeneralizedTime string
765 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
767 struct tm *tm = gmtime(&t);
775 /* we now excatly how long this string will be */
776 ts = talloc_array(mem_ctx, char, 18);
778 /* formatted like: 20040408072012.0Z */
780 "%04u%02u%02u%02u%02u%02u.0Z",
781 tm->tm_year+1900, tm->tm_mon+1,
782 tm->tm_mday, tm->tm_hour, tm->tm_min,
794 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
796 time_t ldb_string_to_time(const char *s)
800 if (s == NULL) return 0;
802 memset(&tm, 0, sizeof(tm));
803 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
804 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
805 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
815 return a LDAP formatted UTCTime string
817 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
819 struct tm *tm = gmtime(&t);
827 /* we now excatly how long this string will be */
828 ts = talloc_array(mem_ctx, char, 14);
830 /* formatted like: 20040408072012.0Z => 040408072012Z */
832 "%02u%02u%02u%02u%02u%02uZ",
833 (tm->tm_year+1900)%100, tm->tm_mon+1,
834 tm->tm_mday, tm->tm_hour, tm->tm_min,
846 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
848 time_t ldb_string_utc_to_time(const char *s)
852 if (s == NULL) return 0;
854 memset(&tm, 0, sizeof(tm));
855 if (sscanf(s, "%02u%02u%02u%02u%02u%02u",
856 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
857 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
860 if (tm.tm_year < 50) {
870 dump a set of results to a file. Useful from within gdb
872 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
876 for (i = 0; i < result->count; i++) {
877 struct ldb_ldif ldif;
878 fprintf(f, "# record %d\n", i+1);
879 ldif.changetype = LDB_CHANGETYPE_NONE;
880 ldif.msg = result->msgs[i];
881 ldb_ldif_write_file(ldb, f, &ldif);
885 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
887 struct ldb_message_element *el;
890 el = ldb_msg_find_element(msg, name);
894 val.data = discard_const_p(uint8_t, value);
895 val.length = strlen(value);
897 if (ldb_msg_find_val(el, &val))