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
36 #include "ldb/include/includes.h"
39 create a new ldb_message in a given memory context (NULL for top level)
41 struct ldb_message *ldb_msg_new(void *mem_ctx)
43 return talloc_zero(mem_ctx, struct ldb_message);
47 find an element in a message by attribute name
49 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
50 const char *attr_name)
53 for (i=0;i<msg->num_elements;i++) {
54 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
55 return &msg->elements[i];
62 see if two ldb_val structures contain exactly the same data
63 return 1 for a match, 0 for a mis-match
65 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
67 if (v1->length != v2->length) return 0;
69 if (v1->length == 0) return 1;
71 if (memcmp(v1->data, v2->data, v1->length) == 0) {
79 find a value in an element
80 assumes case sensitive comparison
82 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
86 for (i=0;i<el->num_values;i++) {
87 if (ldb_val_equal_exact(val, &el->values[i])) {
88 return &el->values[i];
95 duplicate a ldb_val structure
97 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
100 v2.length = v->length;
101 if (v->data == NULL) {
106 /* the +1 is to cope with buggy C library routines like strndup
107 that look one byte beyond */
108 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
114 memcpy(v2.data, v->data, v->length);
115 ((char *)v2.data)[v->length] = 0;
120 add an empty element to a message
122 int ldb_msg_add_empty( struct ldb_message *msg,
123 const char *attr_name,
125 struct ldb_message_element **return_el)
127 struct ldb_message_element *els;
129 /* FIXME: we should probably leave this to the schema module to check */
130 if (! ldb_valid_attr_name(attr_name)) {
131 return LDB_ERR_OPERATIONS_ERROR;
134 els = talloc_realloc(msg, msg->elements,
135 struct ldb_message_element, msg->num_elements+1);
138 return LDB_ERR_OPERATIONS_ERROR;
141 els[msg->num_elements].values = NULL;
142 els[msg->num_elements].num_values = 0;
143 els[msg->num_elements].flags = flags;
144 els[msg->num_elements].name = talloc_strdup(els, attr_name);
145 if (!els[msg->num_elements].name) {
147 return LDB_ERR_OPERATIONS_ERROR;
154 *return_el = &els[msg->num_elements-1];
161 add an empty element to a message
163 int ldb_msg_add(struct ldb_message *msg,
164 const struct ldb_message_element *el,
167 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
168 return LDB_ERR_OPERATIONS_ERROR;
171 msg->elements[msg->num_elements-1] = *el;
172 msg->elements[msg->num_elements-1].flags = flags;
178 add a value to a message
180 int ldb_msg_add_value(struct ldb_message *msg,
181 const char *attr_name,
182 const struct ldb_val *val,
183 struct ldb_message_element **return_el)
185 struct ldb_message_element *el;
186 struct ldb_val *vals;
189 el = ldb_msg_find_element(msg, attr_name);
191 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
192 if (ret != LDB_SUCCESS) {
197 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
200 return LDB_ERR_OPERATIONS_ERROR;
203 el->values[el->num_values] = *val;
215 add a value to a message, stealing it into the 'right' place
217 int ldb_msg_add_steal_value(struct ldb_message *msg,
218 const char *attr_name,
222 struct ldb_message_element *el;
224 ret = ldb_msg_add_value(msg, attr_name, val, &el);
225 if (ret == LDB_SUCCESS) {
226 talloc_steal(el->values, val->data);
233 add a string element to a message
235 int ldb_msg_add_string(struct ldb_message *msg,
236 const char *attr_name, const char *str)
240 val.data = discard_const_p(uint8_t, str);
241 val.length = strlen(str);
243 if (val.length == 0) {
244 /* allow empty strings as non-existant attributes */
248 return ldb_msg_add_value(msg, attr_name, &val, NULL);
252 add a string element to a message, stealing it into the 'right' place
254 int ldb_msg_add_steal_string(struct ldb_message *msg,
255 const char *attr_name, char *str)
259 val.data = (uint8_t *)str;
260 val.length = strlen(str);
262 return ldb_msg_add_steal_value(msg, attr_name, &val);
266 add a printf formatted element to a message
268 int ldb_msg_add_fmt(struct ldb_message *msg,
269 const char *attr_name, const char *fmt, ...)
276 str = talloc_vasprintf(msg, fmt, ap);
279 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
281 val.data = (uint8_t *)str;
282 val.length = strlen(str);
284 return ldb_msg_add_steal_value(msg, attr_name, &val);
288 compare two ldb_message_element structures
289 assumes case senistive comparison
291 int ldb_msg_element_compare(struct ldb_message_element *el1,
292 struct ldb_message_element *el2)
296 if (el1->num_values != el2->num_values) {
297 return el1->num_values - el2->num_values;
300 for (i=0;i<el1->num_values;i++) {
301 if (!ldb_msg_find_val(el2, &el1->values[i])) {
310 compare two ldb_message_element structures
311 comparing by element name
313 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
314 struct ldb_message_element *el2)
316 return ldb_attr_cmp(el1->name, el2->name);
320 convenience functions to return common types from a message
321 these return the first value if the attribute is multi-valued
323 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
325 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
326 if (!el || el->num_values == 0) {
329 return &el->values[0];
332 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
333 const char *attr_name,
336 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
337 if (!v || !v->data) {
338 return default_value;
340 return strtol((const char *)v->data, NULL, 0);
343 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
344 const char *attr_name,
345 unsigned int default_value)
347 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
348 if (!v || !v->data) {
349 return default_value;
351 return strtoul((const char *)v->data, NULL, 0);
354 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
355 const char *attr_name,
356 int64_t default_value)
358 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
359 if (!v || !v->data) {
360 return default_value;
362 return strtoll((const char *)v->data, NULL, 0);
365 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
366 const char *attr_name,
367 uint64_t default_value)
369 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
370 if (!v || !v->data) {
371 return default_value;
373 return strtoull((const char *)v->data, NULL, 0);
376 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
377 const char *attr_name,
378 double default_value)
380 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
381 if (!v || !v->data) {
382 return default_value;
384 return strtod((const char *)v->data, NULL);
387 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
388 const char *attr_name,
391 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
392 if (!v || !v->data) {
393 return default_value;
395 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
398 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
401 return default_value;
404 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
405 const char *attr_name,
406 const char *default_value)
408 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
409 if (!v || !v->data) {
410 return default_value;
412 return (const char *)v->data;
415 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
417 const struct ldb_message *msg,
418 const char *attr_name)
420 struct ldb_dn *res_dn;
421 const struct ldb_val *v;
423 v = ldb_msg_find_ldb_val(msg, attr_name);
424 if (!v || !v->data) {
427 res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
428 if ( ! ldb_dn_validate(res_dn)) {
436 sort the elements of a message by name
438 void ldb_msg_sort_elements(struct ldb_message *msg)
440 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
441 (comparison_fn_t)ldb_msg_element_compare_name);
445 shallow copy a message - copying only the elements array so that the caller
446 can safely add new elements without changing the message
448 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
449 const struct ldb_message *msg)
451 struct ldb_message *msg2;
454 msg2 = talloc(mem_ctx, struct ldb_message);
455 if (msg2 == NULL) return NULL;
459 msg2->elements = talloc_array(msg2, struct ldb_message_element,
461 if (msg2->elements == NULL) goto failed;
463 for (i=0;i<msg2->num_elements;i++) {
464 msg2->elements[i] = msg->elements[i];
476 copy a message, allocating new memory for all parts
478 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
479 const struct ldb_message *msg)
481 struct ldb_message *msg2;
484 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
485 if (msg2 == NULL) return NULL;
487 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
488 if (msg2->dn == NULL) goto failed;
490 for (i=0;i<msg2->num_elements;i++) {
491 struct ldb_message_element *el = &msg2->elements[i];
492 struct ldb_val *values = el->values;
493 el->name = talloc_strdup(msg2->elements, el->name);
494 if (el->name == NULL) goto failed;
495 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
496 for (j=0;j<el->num_values;j++) {
497 el->values[j] = ldb_val_dup(el->values, &values[j]);
498 if (el->values[j].data == NULL && values[j].length != 0) {
513 canonicalise a message, merging elements of the same name
515 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
516 const struct ldb_message *msg)
519 struct ldb_message *msg2;
521 msg2 = ldb_msg_copy(ldb, msg);
522 if (msg2 == NULL) return NULL;
524 ldb_msg_sort_elements(msg2);
526 for (i=1;i<msg2->num_elements;i++) {
527 struct ldb_message_element *el1 = &msg2->elements[i-1];
528 struct ldb_message_element *el2 = &msg2->elements[i];
529 if (ldb_msg_element_compare_name(el1, el2) == 0) {
530 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
531 el1->num_values + el2->num_values);
532 if (el1->values == NULL) {
535 memcpy(el1->values + el1->num_values,
537 sizeof(struct ldb_val) * el2->num_values);
538 el1->num_values += el2->num_values;
539 talloc_free(discard_const_p(char, el2->name));
540 if (i+1<msg2->num_elements) {
541 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
542 (msg2->num_elements - (i+1)));
544 msg2->num_elements--;
554 return a ldb_message representing the differences between msg1 and msg2. If you
555 then use this in a ldb_modify() call it can be used to save edits to a message
557 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
558 struct ldb_message *msg1,
559 struct ldb_message *msg2)
561 struct ldb_message *mod;
562 struct ldb_message_element *el;
565 mod = ldb_msg_new(ldb);
568 mod->num_elements = 0;
569 mod->elements = NULL;
571 msg2 = ldb_msg_canonicalize(ldb, msg2);
576 /* look in msg2 to find elements that need to be added
578 for (i=0;i<msg2->num_elements;i++) {
579 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
581 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
587 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
592 /* look in msg1 to find elements that need to be deleted */
593 for (i=0;i<msg1->num_elements;i++) {
594 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
596 if (ldb_msg_add_empty(mod,
597 msg1->elements[i].name,
598 LDB_FLAG_MOD_DELETE, NULL) != 0) {
607 int ldb_msg_sanity_check(struct ldb_context *ldb,
608 const struct ldb_message *msg)
612 /* basic check on DN */
613 if (msg->dn == NULL) {
614 /* TODO: return also an error string */
615 ldb_set_errstring(ldb, "ldb message lacks a DN!");
616 return LDB_ERR_INVALID_DN_SYNTAX;
619 /* basic syntax checks */
620 for (i = 0; i < msg->num_elements; i++) {
621 for (j = 0; j < msg->elements[i].num_values; j++) {
622 if (msg->elements[i].values[j].length == 0) {
623 TALLOC_CTX *mem_ctx = talloc_new(ldb);
624 /* an attribute cannot be empty */
625 /* TODO: return also an error string */
626 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
627 msg->elements[i].name,
628 ldb_dn_get_linearized(msg->dn));
629 talloc_free(mem_ctx);
630 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
642 copy an attribute list. This only copies the array, not the elements
643 (ie. the elements are left as the same pointers)
645 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
649 for (i=0;attrs[i];i++) /* noop */ ;
650 ret = talloc_array(mem_ctx, const char *, i+1);
654 for (i=0;attrs[i];i++) {
663 copy an attribute list. This only copies the array, not the elements
664 (ie. the elements are left as the same pointers). The new attribute is added to the list.
666 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++) /* noop */ ;
671 ret = talloc_array(mem_ctx, const char *, i+2);
675 for (i=0;attrs[i];i++) {
685 return 1 if an attribute is in a list of attributes, or 0 otherwise
687 int ldb_attr_in_list(const char * const *attrs, const char *attr)
690 for (i=0;attrs[i];i++) {
691 if (ldb_attr_cmp(attrs[i], attr) == 0) {
700 rename the specified attribute in a search result
702 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
704 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
708 el->name = talloc_strdup(msg->elements, replace);
709 if (el->name == NULL) {
710 return LDB_ERR_OPERATIONS_ERROR;
717 copy the specified attribute in a search result to a new attribute
719 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
721 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
725 if (ldb_msg_add(msg, el, 0) != 0) {
726 return LDB_ERR_OPERATIONS_ERROR;
728 return ldb_msg_rename_attr(msg, attr, replace);
733 remove the specified attribute in a search result
735 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
737 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
739 int n = (el - msg->elements);
740 if (n != msg->num_elements-1) {
741 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
748 remove the specified element in a search result
750 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
752 int n = (el - msg->elements);
753 if (n != msg->num_elements-1) {
754 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
760 return a LDAP formatted time string
762 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
764 struct tm *tm = gmtime(&t);
772 /* we now excatly how long this string will be */
773 ts = talloc_array(mem_ctx, char, 18);
775 /* formatted like: 20040408072012.0Z */
777 "%04u%02u%02u%02u%02u%02u.0Z",
778 tm->tm_year+1900, tm->tm_mon+1,
779 tm->tm_mday, tm->tm_hour, tm->tm_min,
792 convert a LDAP time string to a time_t. Return 0 if unable to convert
794 time_t ldb_string_to_time(const char *s)
798 if (s == NULL) return 0;
800 memset(&tm, 0, sizeof(tm));
801 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
802 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
803 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
814 dump a set of results to a file. Useful from within gdb
816 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
820 for (i = 0; i < result->count; i++) {
821 struct ldb_ldif ldif;
822 fprintf(f, "# record %d\n", i+1);
823 ldif.changetype = LDB_CHANGETYPE_NONE;
824 ldif.msg = result->msgs[i];
825 ldb_ldif_write_file(ldb, f, &ldif);
829 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
831 struct ldb_message_element *el;
834 el = ldb_msg_find_element(msg, name);
838 val.data = discard_const_p(uint8_t, value);
839 val.length = strlen(value);
841 if (ldb_msg_find_val(el, &val))