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_private.h"
37 create a new ldb_message in a given memory context (NULL for top level)
39 struct ldb_message
*ldb_msg_new(TALLOC_CTX
*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 mismatch
63 int ldb_val_equal_exact(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
65 if (v1
->length
!= v2
->length
) return 0;
66 if (v1
->data
== v2
->data
) return 1;
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 static int ldb_val_cmp(const struct ldb_val
*v1
, const struct ldb_val
*v2
)
95 if (v1
->length
!= v2
->length
) {
96 return NUMERIC_CMP(v1
->length
, v2
->length
);
98 return memcmp(v1
->data
, v2
->data
, v1
->length
);
103 ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first
104 duplicate value it finds. It does a case sensitive comparison (memcmp).
106 LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
107 options flag, otherwise LDB_SUCCESS.
109 #define LDB_DUP_QUADRATIC_THRESHOLD 10
111 int ldb_msg_find_duplicate_val(struct ldb_context
*ldb
,
113 const struct ldb_message_element
*el
,
114 struct ldb_val
**duplicate
,
121 return LDB_ERR_OPERATIONS_ERROR
;
127 If there are not many values, it is best to avoid the talloc
128 overhead and just do a brute force search.
130 if (el
->num_values
< LDB_DUP_QUADRATIC_THRESHOLD
) {
131 for (j
= 0; j
< el
->num_values
; j
++) {
132 val
= &el
->values
[j
];
133 for ( i
= j
+ 1; i
< el
->num_values
; i
++) {
134 if (ldb_val_equal_exact(val
, &el
->values
[i
])) {
141 struct ldb_val
*values
;
142 values
= talloc_array(mem_ctx
, struct ldb_val
, el
->num_values
);
143 if (values
== NULL
) {
144 return LDB_ERR_OPERATIONS_ERROR
;
147 memcpy(values
, el
->values
,
148 el
->num_values
* sizeof(struct ldb_val
));
149 TYPESAFE_QSORT(values
, el
->num_values
, ldb_val_cmp
);
150 for (i
= 1; i
< el
->num_values
; i
++) {
151 if (ldb_val_equal_exact(&values
[i
],
153 /* find the original location */
154 for (j
= 0; j
< el
->num_values
; j
++) {
155 if (ldb_val_equal_exact(&values
[i
],
158 *duplicate
= &el
->values
[j
];
163 if (*duplicate
== NULL
) {
164 /* how we got here, I don't know */
165 return LDB_ERR_OPERATIONS_ERROR
;
177 Determine whether the values in an element are also in another element.
179 Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements
180 share values, or LDB_SUCCESS if they don't. In this case, the function
181 simply determines the set intersection and it doesn't matter in which order
182 the elements are provided.
184 With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are
185 removed from the first element and LDB_SUCCESS is returned.
187 LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option.
188 LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name.
191 int ldb_msg_find_common_values(struct ldb_context
*ldb
,
193 struct ldb_message_element
*el
,
194 struct ldb_message_element
*el2
,
197 struct ldb_val
*values
;
198 struct ldb_val
*values2
;
199 unsigned int i
, j
, k
, n_values
;
201 bool remove_duplicates
= options
& LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES
;
203 if ((options
& ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES
) != 0) {
204 return LDB_ERR_OPERATIONS_ERROR
;
207 if (strcmp(el
->name
, el2
->name
) != 0) {
208 return LDB_ERR_INAPPROPRIATE_MATCHING
;
210 if (el
->num_values
== 0 || el2
->num_values
== 0) {
214 With few values, it is better to do the brute-force search than the
215 clever search involving tallocs, memcpys, sorts, etc.
217 if (MIN(el
->num_values
, el2
->num_values
) == 1 ||
218 MAX(el
->num_values
, el2
->num_values
) < LDB_DUP_QUADRATIC_THRESHOLD
) {
219 for (i
= 0; i
< el2
->num_values
; i
++) {
220 for (j
= 0; j
< el
->num_values
; j
++) {
221 if (ldb_val_equal_exact(&el
->values
[j
],
223 if (! remove_duplicates
) {
225 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
228 With the remove_duplicates flag, we
229 resolve the intersection by removing
230 the offending one from el.
233 for (k
= j
; k
< el
->num_values
; k
++) {
244 values
= talloc_array(mem_ctx
, struct ldb_val
, el
->num_values
);
245 if (values
== NULL
) {
246 return LDB_ERR_OPERATIONS_ERROR
;
248 values2
= talloc_array(mem_ctx
, struct ldb_val
,
250 if (values2
== NULL
) {
251 return LDB_ERR_OPERATIONS_ERROR
;
254 memcpy(values
, el
->values
,
255 el
->num_values
* sizeof(struct ldb_val
));
256 memcpy(values2
, el2
->values
,
257 el2
->num_values
* sizeof(struct ldb_val
));
258 TYPESAFE_QSORT(values
, el
->num_values
, ldb_val_cmp
);
259 TYPESAFE_QSORT(values2
, el2
->num_values
, ldb_val_cmp
);
262 el->n_values may diverge from the number of values in the sorted
263 list when the remove_duplicates flag is used.
265 n_values
= el
->num_values
;
268 while (i
!= n_values
&& j
< el2
->num_values
) {
269 int ret
= ldb_val_cmp(&values
[i
], &values2
[j
]);
272 } else if (ret
> 0) {
275 /* we have a collision */
276 if (! remove_duplicates
) {
278 TALLOC_FREE(values2
);
279 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
;
282 With the remove_duplicates flag we need to find
283 this in the original list and remove it, which is
284 inefficient but hopefully rare.
286 for (k
= 0; k
< el
->num_values
; k
++) {
287 if (ldb_val_equal_exact(&el
->values
[k
],
293 for (; k
< el
->num_values
; k
++) {
294 el
->values
[k
] = el
->values
[k
+ 1];
300 TALLOC_FREE(values2
);
306 duplicate a ldb_val structure
308 struct ldb_val
ldb_val_dup(TALLOC_CTX
*mem_ctx
, const struct ldb_val
*v
)
311 v2
.length
= v
->length
;
312 if (v
->data
== NULL
) {
317 /* the +1 is to cope with buggy C library routines like strndup
318 that look one byte beyond */
319 v2
.data
= talloc_array(mem_ctx
, uint8_t, v
->length
+1);
325 memcpy(v2
.data
, v
->data
, v
->length
);
326 ((char *)v2
.data
)[v
->length
] = 0;
331 * Adds new empty element to msg->elements
333 static int _ldb_msg_add_el(struct ldb_message
*msg
,
334 struct ldb_message_element
**return_el
)
336 struct ldb_message_element
*els
;
339 * TODO: Find out a way to assert on input parameters.
340 * msg and return_el must be valid
343 els
= talloc_realloc(msg
, msg
->elements
,
344 struct ldb_message_element
, msg
->num_elements
+ 1);
346 return LDB_ERR_OPERATIONS_ERROR
;
349 els
[msg
->num_elements
] = (struct ldb_message_element
) {};
354 *return_el
= &els
[msg
->num_elements
-1];
360 * Add an empty element with a given name to a message
362 int ldb_msg_add_empty(struct ldb_message
*msg
,
363 const char *attr_name
,
365 struct ldb_message_element
**return_el
)
368 struct ldb_message_element
*el
;
370 ret
= _ldb_msg_add_el(msg
, &el
);
371 if (ret
!= LDB_SUCCESS
) {
375 /* initialize newly added element */
377 el
->name
= talloc_strdup(msg
->elements
, attr_name
);
379 return LDB_ERR_OPERATIONS_ERROR
;
390 * Adds an element to a message.
392 * NOTE: Ownership of ldb_message_element fields
393 * is NOT transferred. Thus, if *el pointer
394 * is invalidated for some reason, this will
395 * corrupt *msg contents also
397 int ldb_msg_add(struct ldb_message
*msg
,
398 const struct ldb_message_element
*el
,
402 struct ldb_message_element
*el_new
;
403 /* We have to copy this, just in case *el is a pointer into
404 * what ldb_msg_add_empty() is about to realloc() */
405 struct ldb_message_element el_copy
= *el
;
407 ret
= _ldb_msg_add_el(msg
, &el_new
);
408 if (ret
!= LDB_SUCCESS
) {
412 el_new
->flags
= flags
;
413 el_new
->name
= el_copy
.name
;
414 el_new
->num_values
= el_copy
.num_values
;
415 el_new
->values
= el_copy
.values
;
421 * add a value to a message element
423 int ldb_msg_element_add_value(TALLOC_CTX
*mem_ctx
,
424 struct ldb_message_element
*el
,
425 const struct ldb_val
*val
)
427 struct ldb_val
*vals
;
429 if (el
->flags
& LDB_FLAG_INTERNAL_SHARED_VALUES
) {
431 * Another message is using this message element's values array,
432 * so we don't want to make any modifications to the original
433 * message, or potentially invalidate its own values by calling
434 * talloc_realloc(). Make a copy instead.
436 el
->flags
&= ~LDB_FLAG_INTERNAL_SHARED_VALUES
;
438 vals
= talloc_array(mem_ctx
, struct ldb_val
,
441 return LDB_ERR_OPERATIONS_ERROR
;
444 if (el
->values
!= NULL
) {
445 memcpy(vals
, el
->values
, el
->num_values
* sizeof(struct ldb_val
));
448 vals
= talloc_realloc(mem_ctx
, el
->values
, struct ldb_val
,
451 return LDB_ERR_OPERATIONS_ERROR
;
455 el
->values
[el
->num_values
] = *val
;
462 add a value to a message
464 int ldb_msg_add_value(struct ldb_message
*msg
,
465 const char *attr_name
,
466 const struct ldb_val
*val
,
467 struct ldb_message_element
**return_el
)
469 struct ldb_message_element
*el
;
472 el
= ldb_msg_find_element(msg
, attr_name
);
474 ret
= ldb_msg_add_empty(msg
, attr_name
, 0, &el
);
475 if (ret
!= LDB_SUCCESS
) {
480 ret
= ldb_msg_element_add_value(msg
->elements
, el
, val
);
481 if (ret
!= LDB_SUCCESS
) {
494 add a value to a message, stealing it into the 'right' place
496 int ldb_msg_add_steal_value(struct ldb_message
*msg
,
497 const char *attr_name
,
501 struct ldb_message_element
*el
;
503 ret
= ldb_msg_add_value(msg
, attr_name
, val
, &el
);
504 if (ret
== LDB_SUCCESS
) {
505 talloc_steal(el
->values
, val
->data
);
512 add a string element to a message, specifying flags
514 int ldb_msg_add_string_flags(struct ldb_message
*msg
,
515 const char *attr_name
, const char *str
,
520 struct ldb_message_element
*el
= NULL
;
522 val
.data
= discard_const_p(uint8_t, str
);
523 val
.length
= strlen(str
);
525 if (val
.length
== 0) {
526 /* allow empty strings as non-existent attributes */
530 ret
= ldb_msg_add_value(msg
, attr_name
, &val
, &el
);
531 if (ret
!= LDB_SUCCESS
) {
543 add a string element to a message
545 int ldb_msg_add_string(struct ldb_message
*msg
,
546 const char *attr_name
, const char *str
)
548 return ldb_msg_add_string_flags(msg
, attr_name
, str
, 0);
552 add a string element to a message, stealing it into the 'right' place
554 int ldb_msg_add_steal_string(struct ldb_message
*msg
,
555 const char *attr_name
, char *str
)
559 val
.data
= (uint8_t *)str
;
560 val
.length
= strlen(str
);
562 if (val
.length
== 0) {
563 /* allow empty strings as non-existent attributes */
567 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
571 add a DN element to a message
573 int ldb_msg_add_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
576 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
579 /* we don't want to have unknown DNs added */
580 return LDB_ERR_OPERATIONS_ERROR
;
583 return ldb_msg_add_steal_string(msg
, attr_name
, str
);
587 add a printf formatted element to a message
589 int ldb_msg_add_fmt(struct ldb_message
*msg
,
590 const char *attr_name
, const char *fmt
, ...)
597 str
= talloc_vasprintf(msg
, fmt
, ap
);
600 if (str
== NULL
) return LDB_ERR_OPERATIONS_ERROR
;
602 val
.data
= (uint8_t *)str
;
603 val
.length
= strlen(str
);
605 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
608 static int ldb_msg_append_value_impl(struct ldb_message
*msg
,
609 const char *attr_name
,
610 const struct ldb_val
*val
,
612 struct ldb_message_element
**return_el
)
614 struct ldb_message_element
*el
= NULL
;
617 ret
= ldb_msg_add_empty(msg
, attr_name
, flags
, &el
);
618 if (ret
!= LDB_SUCCESS
) {
622 ret
= ldb_msg_element_add_value(msg
->elements
, el
, val
);
623 if (ret
!= LDB_SUCCESS
) {
627 if (return_el
!= NULL
) {
635 append a value to a message
637 int ldb_msg_append_value(struct ldb_message
*msg
,
638 const char *attr_name
,
639 const struct ldb_val
*val
,
642 return ldb_msg_append_value_impl(msg
, attr_name
, val
, flags
, NULL
);
646 append a value to a message, stealing it into the 'right' place
648 int ldb_msg_append_steal_value(struct ldb_message
*msg
,
649 const char *attr_name
,
654 struct ldb_message_element
*el
= NULL
;
656 ret
= ldb_msg_append_value_impl(msg
, attr_name
, val
, flags
, &el
);
657 if (ret
== LDB_SUCCESS
) {
658 talloc_steal(el
->values
, val
->data
);
664 append a string element to a message, stealing it into the 'right' place
666 int ldb_msg_append_steal_string(struct ldb_message
*msg
,
667 const char *attr_name
, char *str
,
672 val
.data
= (uint8_t *)str
;
673 val
.length
= strlen(str
);
675 if (val
.length
== 0) {
676 /* allow empty strings as non-existent attributes */
680 return ldb_msg_append_steal_value(msg
, attr_name
, &val
, flags
);
684 append a string element to a message
686 int ldb_msg_append_string(struct ldb_message
*msg
,
687 const char *attr_name
, const char *str
, int flags
)
691 val
.data
= discard_const_p(uint8_t, str
);
692 val
.length
= strlen(str
);
694 if (val
.length
== 0) {
695 /* allow empty strings as non-existent attributes */
699 return ldb_msg_append_value(msg
, attr_name
, &val
, flags
);
703 append a DN element to a message
705 int ldb_msg_append_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
706 struct ldb_dn
*dn
, int flags
)
708 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
711 /* we don't want to have unknown DNs added */
712 return LDB_ERR_OPERATIONS_ERROR
;
715 return ldb_msg_append_steal_string(msg
, attr_name
, str
, flags
);
719 append a printf formatted element to a message
721 int ldb_msg_append_fmt(struct ldb_message
*msg
, int flags
,
722 const char *attr_name
, const char *fmt
, ...)
729 str
= talloc_vasprintf(msg
, fmt
, ap
);
733 return LDB_ERR_OPERATIONS_ERROR
;
736 val
.data
= (uint8_t *)str
;
737 val
.length
= strlen(str
);
739 return ldb_msg_append_steal_value(msg
, attr_name
, &val
, flags
);
743 compare two ldb_message_element structures
744 assumes case sensitive comparison
746 int ldb_msg_element_compare(struct ldb_message_element
*el1
,
747 struct ldb_message_element
*el2
)
751 if (el1
->num_values
!= el2
->num_values
) {
752 return NUMERIC_CMP(el1
->num_values
, el2
->num_values
);
755 * Note this is an inconsistent comparison, unsuitable for
756 * sorting. If A has values {a, b} and B has values {b, c},
759 * ldb_msg_element_compare(A, B) returns -1, meaning A < B
760 * ldb_msg_element_compare(B, A) returns -1, meaning B < A
762 for (i
=0;i
<el1
->num_values
;i
++) {
763 if (!ldb_msg_find_val(el2
, &el1
->values
[i
])) {
772 compare two ldb_message_element structures.
773 Different ordering is considered a mismatch
775 bool ldb_msg_element_equal_ordered(const struct ldb_message_element
*el1
,
776 const struct ldb_message_element
*el2
)
779 if (el1
->num_values
!= el2
->num_values
) {
782 for (i
=0;i
<el1
->num_values
;i
++) {
783 if (ldb_val_equal_exact(&el1
->values
[i
],
784 &el2
->values
[i
]) != 1) {
792 compare two ldb_message_element structures
793 comparing by element name
795 int ldb_msg_element_compare_name(struct ldb_message_element
*el1
,
796 struct ldb_message_element
*el2
)
798 if (el1
->name
== el2
->name
) {
802 if (el1
->name
== NULL
) {
806 if (el2
->name
== NULL
) {
810 return ldb_attr_cmp(el1
->name
, el2
->name
);
813 void ldb_msg_element_mark_inaccessible(struct ldb_message_element
*el
)
815 el
->flags
|= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE
;
818 bool ldb_msg_element_is_inaccessible(const struct ldb_message_element
*el
)
820 return (el
->flags
& LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE
) != 0;
823 void ldb_msg_remove_inaccessible(struct ldb_message
*msg
)
826 unsigned num_del
= 0;
828 for (i
= 0; i
< msg
->num_elements
; ++i
) {
829 if (ldb_msg_element_is_inaccessible(&msg
->elements
[i
])) {
831 } else if (num_del
) {
832 msg
->elements
[i
- num_del
] = msg
->elements
[i
];
836 msg
->num_elements
-= num_del
;
840 convenience functions to return common types from a message
841 these return the first value if the attribute is multi-valued
843 const struct ldb_val
*ldb_msg_find_ldb_val(const struct ldb_message
*msg
,
844 const char *attr_name
)
846 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr_name
);
847 if (!el
|| el
->num_values
== 0) {
850 return &el
->values
[0];
853 int ldb_msg_find_attr_as_int(const struct ldb_message
*msg
,
854 const char *attr_name
,
857 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
858 char buf
[sizeof("-2147483648")] = {};
862 if (!v
|| !v
->data
) {
863 return default_value
;
866 if (v
->length
>= sizeof(buf
)) {
867 return default_value
;
870 memcpy(buf
, v
->data
, v
->length
);
872 ret
= (int) strtoll(buf
, &end
, 10);
874 return default_value
;
876 if (end
&& end
[0] != '\0') {
877 return default_value
;
882 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message
*msg
,
883 const char *attr_name
,
884 unsigned int default_value
)
886 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
887 char buf
[sizeof("-2147483648")] = {};
891 if (!v
|| !v
->data
) {
892 return default_value
;
895 if (v
->length
>= sizeof(buf
)) {
896 return default_value
;
899 memcpy(buf
, v
->data
, v
->length
);
901 ret
= (unsigned int) strtoll(buf
, &end
, 10);
904 ret
= (unsigned int) strtoull(buf
, &end
, 10);
906 return default_value
;
909 if (end
&& end
[0] != '\0') {
910 return default_value
;
915 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message
*msg
,
916 const char *attr_name
,
917 int64_t default_value
)
920 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
921 int ret
= ldb_val_as_int64(v
, &val
);
922 return ret
? default_value
: val
;
925 int ldb_val_as_int64(const struct ldb_val
*v
, int64_t *val
)
927 char buf
[sizeof("-9223372036854775808")] = {};
931 if (!v
|| !v
->data
) {
932 return LDB_ERR_OPERATIONS_ERROR
;
935 if (v
->length
>= sizeof(buf
)) {
936 return LDB_ERR_OPERATIONS_ERROR
;
939 memcpy(buf
, v
->data
, v
->length
);
941 result
= (int64_t) strtoll(buf
, &end
, 10);
943 return LDB_ERR_OPERATIONS_ERROR
;
945 if (end
&& end
[0] != '\0') {
946 return LDB_ERR_OPERATIONS_ERROR
;
953 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message
*msg
,
954 const char *attr_name
,
955 uint64_t default_value
)
958 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
959 int ret
= ldb_val_as_uint64(v
, &val
);
960 return ret
? default_value
: val
;
963 int ldb_val_as_uint64(const struct ldb_val
*v
, uint64_t *val
)
965 char buf
[sizeof("-9223372036854775808")] = {};
969 if (!v
|| !v
->data
) {
970 return LDB_ERR_OPERATIONS_ERROR
;
973 if (v
->length
>= sizeof(buf
)) {
974 return LDB_ERR_OPERATIONS_ERROR
;
977 memcpy(buf
, v
->data
, v
->length
);
979 result
= (uint64_t) strtoll(buf
, &end
, 10);
982 result
= (uint64_t) strtoull(buf
, &end
, 10);
984 return LDB_ERR_OPERATIONS_ERROR
;
987 if (end
&& end
[0] != '\0') {
988 return LDB_ERR_OPERATIONS_ERROR
;
995 double ldb_msg_find_attr_as_double(const struct ldb_message
*msg
,
996 const char *attr_name
,
997 double default_value
)
999 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1004 if (!v
|| !v
->data
) {
1005 return default_value
;
1007 buf
= talloc_strndup(msg
, (const char *)v
->data
, v
->length
);
1009 return default_value
;
1013 ret
= strtod(buf
, &end
);
1016 return default_value
;
1018 if (end
&& end
[0] != '\0') {
1019 return default_value
;
1024 int ldb_msg_find_attr_as_bool(const struct ldb_message
*msg
,
1025 const char *attr_name
,
1029 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1030 int ret
= ldb_val_as_bool(v
, &val
);
1031 return ret
? default_value
: val
;
1034 int ldb_val_as_bool(const struct ldb_val
*v
, bool *val
)
1036 if (!v
|| !v
->data
) {
1037 return LDB_ERR_OPERATIONS_ERROR
;
1039 if (v
->length
== 5 && strncasecmp((const char *)v
->data
, "FALSE", 5) == 0) {
1043 if (v
->length
== 4 && strncasecmp((const char *)v
->data
, "TRUE", 4) == 0) {
1047 return LDB_ERR_OPERATIONS_ERROR
;
1050 const char *ldb_msg_find_attr_as_string(const struct ldb_message
*msg
,
1051 const char *attr_name
,
1052 const char *default_value
)
1054 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1055 if (!v
|| !v
->data
) {
1056 return default_value
;
1058 if (v
->data
[v
->length
] != '\0') {
1059 return default_value
;
1061 return (const char *)v
->data
;
1064 struct ldb_dn
*ldb_msg_find_attr_as_dn(struct ldb_context
*ldb
,
1065 TALLOC_CTX
*mem_ctx
,
1066 const struct ldb_message
*msg
,
1067 const char *attr_name
)
1069 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1070 return ldb_val_as_dn(ldb
, mem_ctx
, v
);
1073 struct ldb_dn
*ldb_val_as_dn(struct ldb_context
*ldb
,
1074 TALLOC_CTX
*mem_ctx
,
1075 const struct ldb_val
*v
)
1077 struct ldb_dn
*res_dn
;
1079 if (!v
|| !v
->data
) {
1082 res_dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v
);
1083 if ( ! ldb_dn_validate(res_dn
)) {
1084 talloc_free(res_dn
);
1091 sort the elements of a message by name
1093 void ldb_msg_sort_elements(struct ldb_message
*msg
)
1095 TYPESAFE_QSORT(msg
->elements
, msg
->num_elements
,
1096 ldb_msg_element_compare_name
);
1099 static struct ldb_message
*ldb_msg_copy_shallow_impl(TALLOC_CTX
*mem_ctx
,
1100 const struct ldb_message
*msg
)
1102 struct ldb_message
*msg2
;
1105 msg2
= talloc(mem_ctx
, struct ldb_message
);
1106 if (msg2
== NULL
) return NULL
;
1110 msg2
->elements
= talloc_array(msg2
, struct ldb_message_element
,
1111 msg2
->num_elements
);
1112 if (msg2
->elements
== NULL
) goto failed
;
1114 for (i
=0;i
<msg2
->num_elements
;i
++) {
1115 msg2
->elements
[i
] = msg
->elements
[i
];
1126 shallow copy a message - copying only the elements array so that the caller
1127 can safely add new elements without changing the message
1129 struct ldb_message
*ldb_msg_copy_shallow(TALLOC_CTX
*mem_ctx
,
1130 const struct ldb_message
*msg
)
1132 struct ldb_message
*msg2
;
1135 msg2
= ldb_msg_copy_shallow_impl(mem_ctx
, msg
);
1140 for (i
= 0; i
< msg2
->num_elements
; ++i
) {
1142 * Mark this message's elements as sharing their values with the
1143 * original message, so that we don't inadvertently modify or
1144 * free them. We don't mark the original message element as
1145 * shared, so the original message element should not be
1146 * modified or freed while the shallow copy lives.
1148 struct ldb_message_element
*el
= &msg2
->elements
[i
];
1149 el
->flags
|= LDB_FLAG_INTERNAL_SHARED_VALUES
;
1156 copy a message, allocating new memory for all parts
1158 struct ldb_message
*ldb_msg_copy(TALLOC_CTX
*mem_ctx
,
1159 const struct ldb_message
*msg
)
1161 struct ldb_message
*msg2
;
1164 msg2
= ldb_msg_copy_shallow_impl(mem_ctx
, msg
);
1165 if (msg2
== NULL
) return NULL
;
1167 if (msg2
->dn
!= NULL
) {
1168 msg2
->dn
= ldb_dn_copy(msg2
, msg2
->dn
);
1169 if (msg2
->dn
== NULL
) goto failed
;
1172 for (i
=0;i
<msg2
->num_elements
;i
++) {
1173 struct ldb_message_element
*el
= &msg2
->elements
[i
];
1174 struct ldb_val
*values
= el
->values
;
1175 if (el
->name
!= NULL
) {
1176 el
->name
= talloc_strdup(msg2
->elements
, el
->name
);
1177 if (el
->name
== NULL
) goto failed
;
1179 el
->values
= talloc_array(msg2
->elements
, struct ldb_val
, el
->num_values
);
1180 if (el
->values
== NULL
) goto failed
;
1181 for (j
=0;j
<el
->num_values
;j
++) {
1182 el
->values
[j
] = ldb_val_dup(el
->values
, &values
[j
]);
1183 if (el
->values
[j
].data
== NULL
&& values
[j
].length
!= 0) {
1189 * Since we copied this element's values, we can mark them as
1192 el
->flags
&= ~LDB_FLAG_INTERNAL_SHARED_VALUES
;
1204 * Canonicalize a message, merging elements of the same name
1206 struct ldb_message
*ldb_msg_canonicalize(struct ldb_context
*ldb
,
1207 const struct ldb_message
*msg
)
1210 struct ldb_message
*msg2
;
1213 * Preserve previous behavior and allocate
1214 * *msg2 into *ldb context
1216 ret
= ldb_msg_normalize(ldb
, ldb
, msg
, &msg2
);
1217 if (ret
!= LDB_SUCCESS
) {
1225 * Canonicalize a message, merging elements of the same name
1227 int ldb_msg_normalize(struct ldb_context
*ldb
,
1228 TALLOC_CTX
*mem_ctx
,
1229 const struct ldb_message
*msg
,
1230 struct ldb_message
**_msg_out
)
1233 struct ldb_message
*msg2
;
1235 msg2
= ldb_msg_copy(mem_ctx
, msg
);
1237 return LDB_ERR_OPERATIONS_ERROR
;
1240 ldb_msg_sort_elements(msg2
);
1242 for (i
=1; i
< msg2
->num_elements
; i
++) {
1243 struct ldb_message_element
*el1
= &msg2
->elements
[i
-1];
1244 struct ldb_message_element
*el2
= &msg2
->elements
[i
];
1246 if (ldb_msg_element_compare_name(el1
, el2
) == 0) {
1247 el1
->values
= talloc_realloc(msg2
->elements
,
1248 el1
->values
, struct ldb_val
,
1249 el1
->num_values
+ el2
->num_values
);
1250 if (el1
->num_values
+ el2
->num_values
> 0 && el1
->values
== NULL
) {
1252 return LDB_ERR_OPERATIONS_ERROR
;
1254 memcpy(el1
->values
+ el1
->num_values
,
1256 sizeof(struct ldb_val
) * el2
->num_values
);
1257 el1
->num_values
+= el2
->num_values
;
1258 talloc_free(discard_const_p(char, el2
->name
));
1259 if ((i
+ 1 > i
) && ((i
+ 1) < msg2
->num_elements
)) {
1260 memmove(el2
, el2
+1, sizeof(struct ldb_message_element
) *
1261 (msg2
->num_elements
- (i
+1)));
1263 msg2
->num_elements
--;
1274 * return a ldb_message representing the differences between msg1 and msg2.
1275 * If you then use this in a ldb_modify() call,
1276 * it can be used to save edits to a message
1278 struct ldb_message
*ldb_msg_diff(struct ldb_context
*ldb
,
1279 struct ldb_message
*msg1
,
1280 struct ldb_message
*msg2
)
1283 struct ldb_message
*mod
;
1285 ldb_ret
= ldb_msg_difference(ldb
, ldb
, msg1
, msg2
, &mod
);
1286 if (ldb_ret
!= LDB_SUCCESS
) {
1294 * return a ldb_message representing the differences between msg1 and msg2.
1295 * If you then use this in a ldb_modify() call it can be used to save edits to a message
1297 * Result message is constructed as follows:
1298 * - LDB_FLAG_MOD_ADD - elements found only in msg2
1299 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1300 * Value for msg2 element is used
1301 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
1303 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1305 int ldb_msg_difference(struct ldb_context
*ldb
,
1306 TALLOC_CTX
*mem_ctx
,
1307 struct ldb_message
*msg1
,
1308 struct ldb_message
*msg2
,
1309 struct ldb_message
**_msg_out
)
1313 struct ldb_message
*mod
;
1314 struct ldb_message_element
*el
;
1315 TALLOC_CTX
*temp_ctx
;
1317 temp_ctx
= talloc_new(mem_ctx
);
1319 return LDB_ERR_OPERATIONS_ERROR
;
1322 mod
= ldb_msg_new(temp_ctx
);
1328 mod
->num_elements
= 0;
1329 mod
->elements
= NULL
;
1332 * Canonicalize *msg2 so we have no repeated elements
1333 * Resulting message is allocated in *mod's mem context,
1334 * as we are going to move some elements from *msg2 to
1337 ldb_res
= ldb_msg_normalize(ldb
, mod
, msg2
, &msg2
);
1338 if (ldb_res
!= LDB_SUCCESS
) {
1342 /* look in msg2 to find elements that need to be added or modified */
1343 for (i
=0;i
<msg2
->num_elements
;i
++) {
1344 el
= ldb_msg_find_element(msg1
, msg2
->elements
[i
].name
);
1346 if (el
&& ldb_msg_element_compare(el
, &msg2
->elements
[i
]) == 0) {
1350 ldb_res
= ldb_msg_add(mod
,
1352 el
? LDB_FLAG_MOD_REPLACE
: LDB_FLAG_MOD_ADD
);
1353 if (ldb_res
!= LDB_SUCCESS
) {
1358 /* look in msg1 to find elements that need to be deleted */
1359 for (i
=0;i
<msg1
->num_elements
;i
++) {
1360 el
= ldb_msg_find_element(msg2
, msg1
->elements
[i
].name
);
1362 ldb_res
= ldb_msg_add_empty(mod
,
1363 msg1
->elements
[i
].name
,
1364 LDB_FLAG_MOD_DELETE
, NULL
);
1365 if (ldb_res
!= LDB_SUCCESS
) {
1371 /* steal resulting message into supplied context */
1372 talloc_steal(mem_ctx
, mod
);
1375 talloc_free(temp_ctx
);
1379 talloc_free(temp_ctx
);
1380 return LDB_ERR_OPERATIONS_ERROR
;
1384 int ldb_msg_sanity_check(struct ldb_context
*ldb
,
1385 const struct ldb_message
*msg
)
1389 /* basic check on DN */
1390 if (msg
->dn
== NULL
) {
1391 ldb_set_errstring(ldb
, "ldb message lacks a DN!");
1392 return LDB_ERR_INVALID_DN_SYNTAX
;
1395 /* basic syntax checks */
1396 for (i
= 0; i
< msg
->num_elements
; i
++) {
1397 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
1398 if (msg
->elements
[i
].values
[j
].length
== 0) {
1399 /* an attribute cannot be empty */
1400 ldb_asprintf_errstring(ldb
, "Element %s has empty attribute in ldb message (%s)!",
1401 msg
->elements
[i
].name
,
1402 ldb_dn_get_linearized(msg
->dn
));
1403 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1415 copy an attribute list. This only copies the array, not the elements
1416 (ie. the elements are left as the same pointers)
1418 const char **ldb_attr_list_copy(TALLOC_CTX
*mem_ctx
, const char * const *attrs
)
1423 for (i
=0;attrs
&& attrs
[i
];i
++) /* noop */ ;
1424 ret
= talloc_array(mem_ctx
, const char *, i
+1);
1428 for (i
=0;attrs
&& attrs
[i
];i
++) {
1437 copy an attribute list. This only copies the array, not the elements
1438 (ie. the elements are left as the same pointers). The new attribute is added to the list.
1440 const char **ldb_attr_list_copy_add(TALLOC_CTX
*mem_ctx
, const char * const *attrs
, const char *new_attr
)
1446 for (i
=0;attrs
&& attrs
[i
];i
++) {
1447 if (ldb_attr_cmp(attrs
[i
], new_attr
) == 0) {
1452 return ldb_attr_list_copy(mem_ctx
, attrs
);
1454 ret
= talloc_array(mem_ctx
, const char *, i
+2);
1458 for (i
=0;attrs
&& attrs
[i
];i
++) {
1468 return 1 if an attribute is in a list of attributes, or 0 otherwise
1470 int ldb_attr_in_list(const char * const *attrs
, const char *attr
)
1473 for (i
=0;attrs
&& attrs
[i
];i
++) {
1474 if (ldb_attr_cmp(attrs
[i
], attr
) == 0) {
1483 rename the specified attribute in a search result
1485 int ldb_msg_rename_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
1487 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
1491 el
->name
= talloc_strdup(msg
->elements
, replace
);
1492 if (el
->name
== NULL
) {
1493 return LDB_ERR_OPERATIONS_ERROR
;
1500 copy the specified attribute in a search result to a new attribute
1502 int ldb_msg_copy_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
1504 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
1510 ret
= ldb_msg_add(msg
, el
, 0);
1511 if (ret
!= LDB_SUCCESS
) {
1514 return ldb_msg_rename_attr(msg
, attr
, replace
);
1518 remove the specified element in a search result
1520 void ldb_msg_remove_element(struct ldb_message
*msg
, struct ldb_message_element
*el
)
1522 ptrdiff_t n
= (el
- msg
->elements
);
1523 if (n
>= msg
->num_elements
|| n
< 0) {
1524 /* the element is not in the list. the caller is crazy. */
1527 msg
->num_elements
--;
1528 if (n
!= msg
->num_elements
) {
1529 memmove(el
, el
+1, (msg
->num_elements
- n
)*sizeof(*el
));
1535 remove the specified attribute in a search result
1537 void ldb_msg_remove_attr(struct ldb_message
*msg
, const char *attr
)
1540 unsigned int num_del
= 0;
1542 for (i
= 0; i
< msg
->num_elements
; ++i
) {
1543 if (ldb_attr_cmp(msg
->elements
[i
].name
, attr
) == 0) {
1545 } else if (num_del
) {
1546 msg
->elements
[i
- num_del
] = msg
->elements
[i
];
1550 msg
->num_elements
-= num_del
;
1553 /* Reallocate elements to drop any excess capacity. */
1554 void ldb_msg_shrink_to_fit(struct ldb_message
*msg
)
1556 if (msg
->num_elements
> 0) {
1557 struct ldb_message_element
*elements
= talloc_realloc(msg
,
1559 struct ldb_message_element
,
1561 if (elements
!= NULL
) {
1562 msg
->elements
= elements
;
1565 TALLOC_FREE(msg
->elements
);
1570 return a LDAP formatted GeneralizedTime string
1572 char *ldb_timestring(TALLOC_CTX
*mem_ctx
, time_t t
)
1574 struct tm
*tm
= gmtime(&t
);
1582 /* we know exactly how long this string will be */
1583 ts
= talloc_array(mem_ctx
, char, 18);
1585 /* formatted like: 20040408072012.0Z */
1586 r
= snprintf(ts
, 18,
1587 "%04u%02u%02u%02u%02u%02u.0Z",
1588 tm
->tm_year
+1900, tm
->tm_mon
+1,
1589 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1602 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1604 time_t ldb_string_to_time(const char *s
)
1609 if (s
== NULL
) return 0;
1611 memset(&tm
, 0, sizeof(tm
));
1612 if (sscanf(s
, "%04u%02u%02u%02u%02u%02u.0Z",
1613 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1614 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1622 if (t
== (time_t)-1 && errno
!= 0) {
1624 * timegm() returns -1 on error, but also for '19691231235959.0Z'.
1632 convert a LDAP GeneralizedTime string in ldb_val format to a
1635 int ldb_val_to_time(const struct ldb_val
*v
, time_t *t
)
1643 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1646 if (v
->data
== NULL
) {
1647 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1650 if (v
->length
< 16 && v
->length
!= 13) {
1651 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1654 if (v
->data
[v
->length
- 1] != 'Z') {
1655 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1658 if (v
->length
== 13) {
1659 memcpy(val
, v
->data
, 12);
1661 if (sscanf(val
, "%02u%02u%02u%02u%02u%02u",
1662 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1663 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1664 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1666 if (tm
.tm_year
< 50) {
1672 * anything between '.' and 'Z' is silently ignored.
1674 if (v
->data
[14] != '.') {
1675 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1678 memcpy(val
, v
->data
, 14);
1680 if (sscanf(val
, "%04u%02u%02u%02u%02u%02u",
1681 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1682 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1683 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1695 return a LDAP formatted UTCTime string
1697 char *ldb_timestring_utc(TALLOC_CTX
*mem_ctx
, time_t t
)
1699 struct tm
*tm
= gmtime(&t
);
1707 /* we know exactly how long this string will be */
1708 ts
= talloc_array(mem_ctx
, char, 14);
1710 /* formatted like: 20040408072012.0Z => 040408072012Z */
1711 r
= snprintf(ts
, 14,
1712 "%02u%02u%02u%02u%02u%02uZ",
1713 (tm
->tm_year
+1900)%100, tm
->tm_mon
+1,
1714 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1726 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1728 time_t ldb_string_utc_to_time(const char *s
)
1732 if (s
== NULL
) return 0;
1734 memset(&tm
, 0, sizeof(tm
));
1735 if (sscanf(s
, "%02u%02u%02u%02u%02u%02uZ",
1736 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1737 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1740 if (tm
.tm_year
< 50) {
1750 dump a set of results to a file. Useful from within gdb
1752 void ldb_dump_results(struct ldb_context
*ldb
, struct ldb_result
*result
, FILE *f
)
1756 for (i
= 0; i
< result
->count
; i
++) {
1757 struct ldb_ldif ldif
;
1758 fprintf(f
, "# record %d\n", i
+1);
1759 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
1760 ldif
.msg
= result
->msgs
[i
];
1761 ldb_ldif_write_file(ldb
, f
, &ldif
);
1766 checks for a string attribute. Returns "1" on match and otherwise "0".
1768 int ldb_msg_check_string_attribute(const struct ldb_message
*msg
,
1769 const char *name
, const char *value
)
1771 struct ldb_message_element
*el
;
1774 el
= ldb_msg_find_element(msg
, name
);
1779 val
.data
= discard_const_p(uint8_t, value
);
1780 val
.length
= strlen(value
);
1782 if (ldb_msg_find_val(el
, &val
)) {
1791 compare a ldb_val to a string
1793 int ldb_val_string_cmp(const struct ldb_val
*v
, const char *str
)
1795 size_t len
= strlen(str
);
1796 if (len
!= v
->length
) {
1797 return len
- v
->length
;
1799 return strncmp((const char *)v
->data
, str
, len
);