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;
458 msg2->private_data = 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)
671 for (i=0;attrs[i];i++) /* noop */ ;
672 ret = talloc_array(mem_ctx, const char *, i+2);
676 for (i=0;attrs[i];i++) {
686 return 1 if an attribute is in a list of attributes, or 0 otherwise
688 int ldb_attr_in_list(const char * const *attrs, const char *attr)
691 for (i=0;attrs[i];i++) {
692 if (ldb_attr_cmp(attrs[i], attr) == 0) {
701 rename the specified attribute in a search result
703 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
705 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
709 el->name = talloc_strdup(msg->elements, replace);
710 if (el->name == NULL) {
711 return LDB_ERR_OPERATIONS_ERROR;
718 copy the specified attribute in a search result to a new attribute
720 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
722 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
726 if (ldb_msg_add(msg, el, 0) != 0) {
727 return LDB_ERR_OPERATIONS_ERROR;
729 return ldb_msg_rename_attr(msg, attr, replace);
734 remove the specified attribute in a search result
736 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
738 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
740 int n = (el - msg->elements);
741 if (n != msg->num_elements-1) {
742 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
749 remove the specified element in a search result
751 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
753 int n = (el - msg->elements);
754 if (n != msg->num_elements-1) {
755 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
761 return a LDAP formatted time string
763 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
765 struct tm *tm = gmtime(&t);
771 /* formatted like: 20040408072012.0Z */
772 return talloc_asprintf(mem_ctx,
773 "%04u%02u%02u%02u%02u%02u.0Z",
774 tm->tm_year+1900, tm->tm_mon+1,
775 tm->tm_mday, tm->tm_hour, tm->tm_min,
781 convert a LDAP time string to a time_t. Return 0 if unable to convert
783 time_t ldb_string_to_time(const char *s)
787 if (s == NULL) return 0;
789 memset(&tm, 0, sizeof(tm));
790 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
791 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
792 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
803 dump a set of results to a file. Useful from within gdb
805 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
809 for (i = 0; i < result->count; i++) {
810 struct ldb_ldif ldif;
811 fprintf(f, "# record %d\n", i+1);
812 ldif.changetype = LDB_CHANGETYPE_NONE;
813 ldif.msg = result->msgs[i];
814 ldb_ldif_write_file(ldb, f, &ldif);
818 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
820 struct ldb_message_element *el;
823 el = ldb_msg_find_element(msg, name);
827 val.data = discard_const_p(uint8_t, value);
828 val.length = strlen(value);
830 if (ldb_msg_find_val(el, &val))