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 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;
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 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 ZERO_STRUCT(els
[msg
->num_elements
]);
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
572 WARNING: this uses the linearized string from the dn, and does not
575 int ldb_msg_add_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
578 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
581 /* we don't want to have unknown DNs added */
582 return LDB_ERR_OPERATIONS_ERROR
;
585 return ldb_msg_add_steal_string(msg
, attr_name
, str
);
589 add a printf formatted element to a message
591 int ldb_msg_add_fmt(struct ldb_message
*msg
,
592 const char *attr_name
, const char *fmt
, ...)
599 str
= talloc_vasprintf(msg
, fmt
, ap
);
602 if (str
== NULL
) return LDB_ERR_OPERATIONS_ERROR
;
604 val
.data
= (uint8_t *)str
;
605 val
.length
= strlen(str
);
607 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
610 static int ldb_msg_append_value_impl(struct ldb_message
*msg
,
611 const char *attr_name
,
612 const struct ldb_val
*val
,
614 struct ldb_message_element
**return_el
)
616 struct ldb_message_element
*el
= NULL
;
619 ret
= ldb_msg_add_empty(msg
, attr_name
, flags
, &el
);
620 if (ret
!= LDB_SUCCESS
) {
624 ret
= ldb_msg_element_add_value(msg
->elements
, el
, val
);
625 if (ret
!= LDB_SUCCESS
) {
629 if (return_el
!= NULL
) {
637 append a value to a message
639 int ldb_msg_append_value(struct ldb_message
*msg
,
640 const char *attr_name
,
641 const struct ldb_val
*val
,
644 return ldb_msg_append_value_impl(msg
, attr_name
, val
, flags
, NULL
);
648 append a value to a message, stealing it into the 'right' place
650 int ldb_msg_append_steal_value(struct ldb_message
*msg
,
651 const char *attr_name
,
656 struct ldb_message_element
*el
= NULL
;
658 ret
= ldb_msg_append_value_impl(msg
, attr_name
, val
, flags
, &el
);
659 if (ret
== LDB_SUCCESS
) {
660 talloc_steal(el
->values
, val
->data
);
666 append a string element to a message, stealing it into the 'right' place
668 int ldb_msg_append_steal_string(struct ldb_message
*msg
,
669 const char *attr_name
, char *str
,
674 val
.data
= (uint8_t *)str
;
675 val
.length
= strlen(str
);
677 if (val
.length
== 0) {
678 /* allow empty strings as non-existent attributes */
682 return ldb_msg_append_steal_value(msg
, attr_name
, &val
, flags
);
686 append a string element to a message
688 int ldb_msg_append_string(struct ldb_message
*msg
,
689 const char *attr_name
, const char *str
, int flags
)
693 val
.data
= discard_const_p(uint8_t, str
);
694 val
.length
= strlen(str
);
696 if (val
.length
== 0) {
697 /* allow empty strings as non-existent attributes */
701 return ldb_msg_append_value(msg
, attr_name
, &val
, flags
);
705 append a DN element to a message
706 WARNING: this uses the linearized string from the dn, and does not
709 int ldb_msg_append_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
710 struct ldb_dn
*dn
, int flags
)
712 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
715 /* we don't want to have unknown DNs added */
716 return LDB_ERR_OPERATIONS_ERROR
;
719 return ldb_msg_append_steal_string(msg
, attr_name
, str
, flags
);
723 append a printf formatted element to a message
725 int ldb_msg_append_fmt(struct ldb_message
*msg
, int flags
,
726 const char *attr_name
, const char *fmt
, ...)
733 str
= talloc_vasprintf(msg
, fmt
, ap
);
737 return LDB_ERR_OPERATIONS_ERROR
;
740 val
.data
= (uint8_t *)str
;
741 val
.length
= strlen(str
);
743 return ldb_msg_append_steal_value(msg
, attr_name
, &val
, flags
);
747 compare two ldb_message_element structures
748 assumes case sensitive comparison
750 int ldb_msg_element_compare(struct ldb_message_element
*el1
,
751 struct ldb_message_element
*el2
)
755 if (el1
->num_values
!= el2
->num_values
) {
756 return el1
->num_values
- el2
->num_values
;
759 for (i
=0;i
<el1
->num_values
;i
++) {
760 if (!ldb_msg_find_val(el2
, &el1
->values
[i
])) {
769 compare two ldb_message_element structures.
770 Different ordering is considered a mismatch
772 bool ldb_msg_element_equal_ordered(const struct ldb_message_element
*el1
,
773 const struct ldb_message_element
*el2
)
776 if (el1
->num_values
!= el2
->num_values
) {
779 for (i
=0;i
<el1
->num_values
;i
++) {
780 if (ldb_val_equal_exact(&el1
->values
[i
],
781 &el2
->values
[i
]) != 1) {
789 compare two ldb_message_element structures
790 comparing by element name
792 int ldb_msg_element_compare_name(struct ldb_message_element
*el1
,
793 struct ldb_message_element
*el2
)
795 return ldb_attr_cmp(el1
->name
, el2
->name
);
798 void ldb_msg_element_mark_inaccessible(struct ldb_message_element
*el
)
800 el
->flags
|= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE
;
803 bool ldb_msg_element_is_inaccessible(const struct ldb_message_element
*el
)
805 return (el
->flags
& LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE
) != 0;
808 void ldb_msg_remove_inaccessible(struct ldb_message
*msg
)
811 unsigned num_del
= 0;
813 for (i
= 0; i
< msg
->num_elements
; ++i
) {
814 if (ldb_msg_element_is_inaccessible(&msg
->elements
[i
])) {
816 } else if (num_del
) {
817 msg
->elements
[i
- num_del
] = msg
->elements
[i
];
821 msg
->num_elements
-= num_del
;
825 convenience functions to return common types from a message
826 these return the first value if the attribute is multi-valued
828 const struct ldb_val
*ldb_msg_find_ldb_val(const struct ldb_message
*msg
,
829 const char *attr_name
)
831 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr_name
);
832 if (!el
|| el
->num_values
== 0) {
835 return &el
->values
[0];
838 int ldb_msg_find_attr_as_int(const struct ldb_message
*msg
,
839 const char *attr_name
,
842 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
843 char buf
[sizeof("-2147483648")];
847 if (!v
|| !v
->data
) {
848 return default_value
;
852 if (v
->length
>= sizeof(buf
)) {
853 return default_value
;
856 memcpy(buf
, v
->data
, v
->length
);
858 ret
= (int) strtoll(buf
, &end
, 10);
860 return default_value
;
862 if (end
&& end
[0] != '\0') {
863 return default_value
;
868 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message
*msg
,
869 const char *attr_name
,
870 unsigned int default_value
)
872 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
873 char buf
[sizeof("-2147483648")];
877 if (!v
|| !v
->data
) {
878 return default_value
;
882 if (v
->length
>= sizeof(buf
)) {
883 return default_value
;
886 memcpy(buf
, v
->data
, v
->length
);
888 ret
= (unsigned int) strtoll(buf
, &end
, 10);
891 ret
= (unsigned int) strtoull(buf
, &end
, 10);
893 return default_value
;
896 if (end
&& end
[0] != '\0') {
897 return default_value
;
902 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message
*msg
,
903 const char *attr_name
,
904 int64_t default_value
)
906 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
907 char buf
[sizeof("-9223372036854775808")];
911 if (!v
|| !v
->data
) {
912 return default_value
;
916 if (v
->length
>= sizeof(buf
)) {
917 return default_value
;
920 memcpy(buf
, v
->data
, v
->length
);
922 ret
= (int64_t) strtoll(buf
, &end
, 10);
924 return default_value
;
926 if (end
&& end
[0] != '\0') {
927 return default_value
;
932 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message
*msg
,
933 const char *attr_name
,
934 uint64_t default_value
)
936 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
937 char buf
[sizeof("-9223372036854775808")];
941 if (!v
|| !v
->data
) {
942 return default_value
;
946 if (v
->length
>= sizeof(buf
)) {
947 return default_value
;
950 memcpy(buf
, v
->data
, v
->length
);
952 ret
= (uint64_t) strtoll(buf
, &end
, 10);
955 ret
= (uint64_t) strtoull(buf
, &end
, 10);
957 return default_value
;
960 if (end
&& end
[0] != '\0') {
961 return default_value
;
966 double ldb_msg_find_attr_as_double(const struct ldb_message
*msg
,
967 const char *attr_name
,
968 double default_value
)
970 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
975 if (!v
|| !v
->data
) {
976 return default_value
;
978 buf
= talloc_strndup(msg
, (const char *)v
->data
, v
->length
);
980 return default_value
;
984 ret
= strtod(buf
, &end
);
987 return default_value
;
989 if (end
&& end
[0] != '\0') {
990 return default_value
;
995 int ldb_msg_find_attr_as_bool(const struct ldb_message
*msg
,
996 const char *attr_name
,
999 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1000 if (!v
|| !v
->data
) {
1001 return default_value
;
1003 if (v
->length
== 5 && strncasecmp((const char *)v
->data
, "FALSE", 5) == 0) {
1006 if (v
->length
== 4 && strncasecmp((const char *)v
->data
, "TRUE", 4) == 0) {
1009 return default_value
;
1012 const char *ldb_msg_find_attr_as_string(const struct ldb_message
*msg
,
1013 const char *attr_name
,
1014 const char *default_value
)
1016 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1017 if (!v
|| !v
->data
) {
1018 return default_value
;
1020 if (v
->data
[v
->length
] != '\0') {
1021 return default_value
;
1023 return (const char *)v
->data
;
1026 struct ldb_dn
*ldb_msg_find_attr_as_dn(struct ldb_context
*ldb
,
1027 TALLOC_CTX
*mem_ctx
,
1028 const struct ldb_message
*msg
,
1029 const char *attr_name
)
1031 struct ldb_dn
*res_dn
;
1032 const struct ldb_val
*v
;
1034 v
= ldb_msg_find_ldb_val(msg
, attr_name
);
1035 if (!v
|| !v
->data
) {
1038 res_dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v
);
1039 if ( ! ldb_dn_validate(res_dn
)) {
1040 talloc_free(res_dn
);
1047 sort the elements of a message by name
1049 void ldb_msg_sort_elements(struct ldb_message
*msg
)
1051 TYPESAFE_QSORT(msg
->elements
, msg
->num_elements
,
1052 ldb_msg_element_compare_name
);
1055 static struct ldb_message
*ldb_msg_copy_shallow_impl(TALLOC_CTX
*mem_ctx
,
1056 const struct ldb_message
*msg
)
1058 struct ldb_message
*msg2
;
1061 msg2
= talloc(mem_ctx
, struct ldb_message
);
1062 if (msg2
== NULL
) return NULL
;
1066 msg2
->elements
= talloc_array(msg2
, struct ldb_message_element
,
1067 msg2
->num_elements
);
1068 if (msg2
->elements
== NULL
) goto failed
;
1070 for (i
=0;i
<msg2
->num_elements
;i
++) {
1071 msg2
->elements
[i
] = msg
->elements
[i
];
1082 shallow copy a message - copying only the elements array so that the caller
1083 can safely add new elements without changing the message
1085 struct ldb_message
*ldb_msg_copy_shallow(TALLOC_CTX
*mem_ctx
,
1086 const struct ldb_message
*msg
)
1088 struct ldb_message
*msg2
;
1091 msg2
= ldb_msg_copy_shallow_impl(mem_ctx
, msg
);
1096 for (i
= 0; i
< msg2
->num_elements
; ++i
) {
1098 * Mark this message's elements as sharing their values with the
1099 * original message, so that we don't inadvertently modify or
1100 * free them. We don't mark the original message element as
1101 * shared, so the original message element should not be
1102 * modified or freed while the shallow copy lives.
1104 struct ldb_message_element
*el
= &msg2
->elements
[i
];
1105 el
->flags
|= LDB_FLAG_INTERNAL_SHARED_VALUES
;
1112 copy a message, allocating new memory for all parts
1114 struct ldb_message
*ldb_msg_copy(TALLOC_CTX
*mem_ctx
,
1115 const struct ldb_message
*msg
)
1117 struct ldb_message
*msg2
;
1120 msg2
= ldb_msg_copy_shallow_impl(mem_ctx
, msg
);
1121 if (msg2
== NULL
) return NULL
;
1123 if (msg2
->dn
!= NULL
) {
1124 msg2
->dn
= ldb_dn_copy(msg2
, msg2
->dn
);
1125 if (msg2
->dn
== NULL
) goto failed
;
1128 for (i
=0;i
<msg2
->num_elements
;i
++) {
1129 struct ldb_message_element
*el
= &msg2
->elements
[i
];
1130 struct ldb_val
*values
= el
->values
;
1131 el
->name
= talloc_strdup(msg2
->elements
, el
->name
);
1132 if (el
->name
== NULL
) goto failed
;
1133 el
->values
= talloc_array(msg2
->elements
, struct ldb_val
, el
->num_values
);
1134 if (el
->values
== NULL
) goto failed
;
1135 for (j
=0;j
<el
->num_values
;j
++) {
1136 el
->values
[j
] = ldb_val_dup(el
->values
, &values
[j
]);
1137 if (el
->values
[j
].data
== NULL
&& values
[j
].length
!= 0) {
1143 * Since we copied this element's values, we can mark them as
1146 el
->flags
&= ~LDB_FLAG_INTERNAL_SHARED_VALUES
;
1158 * Canonicalize a message, merging elements of the same name
1160 struct ldb_message
*ldb_msg_canonicalize(struct ldb_context
*ldb
,
1161 const struct ldb_message
*msg
)
1164 struct ldb_message
*msg2
;
1167 * Preserve previous behavior and allocate
1168 * *msg2 into *ldb context
1170 ret
= ldb_msg_normalize(ldb
, ldb
, msg
, &msg2
);
1171 if (ret
!= LDB_SUCCESS
) {
1179 * Canonicalize a message, merging elements of the same name
1181 int ldb_msg_normalize(struct ldb_context
*ldb
,
1182 TALLOC_CTX
*mem_ctx
,
1183 const struct ldb_message
*msg
,
1184 struct ldb_message
**_msg_out
)
1187 struct ldb_message
*msg2
;
1189 msg2
= ldb_msg_copy(mem_ctx
, msg
);
1191 return LDB_ERR_OPERATIONS_ERROR
;
1194 ldb_msg_sort_elements(msg2
);
1196 for (i
=1; i
< msg2
->num_elements
; i
++) {
1197 struct ldb_message_element
*el1
= &msg2
->elements
[i
-1];
1198 struct ldb_message_element
*el2
= &msg2
->elements
[i
];
1200 if (ldb_msg_element_compare_name(el1
, el2
) == 0) {
1201 el1
->values
= talloc_realloc(msg2
->elements
,
1202 el1
->values
, struct ldb_val
,
1203 el1
->num_values
+ el2
->num_values
);
1204 if (el1
->num_values
+ el2
->num_values
> 0 && el1
->values
== NULL
) {
1206 return LDB_ERR_OPERATIONS_ERROR
;
1208 memcpy(el1
->values
+ el1
->num_values
,
1210 sizeof(struct ldb_val
) * el2
->num_values
);
1211 el1
->num_values
+= el2
->num_values
;
1212 talloc_free(discard_const_p(char, el2
->name
));
1213 if ((i
+1) < msg2
->num_elements
) {
1214 memmove(el2
, el2
+1, sizeof(struct ldb_message_element
) *
1215 (msg2
->num_elements
- (i
+1)));
1217 msg2
->num_elements
--;
1228 * return a ldb_message representing the differences between msg1 and msg2.
1229 * If you then use this in a ldb_modify() call,
1230 * it can be used to save edits to a message
1232 struct ldb_message
*ldb_msg_diff(struct ldb_context
*ldb
,
1233 struct ldb_message
*msg1
,
1234 struct ldb_message
*msg2
)
1237 struct ldb_message
*mod
;
1239 ldb_ret
= ldb_msg_difference(ldb
, ldb
, msg1
, msg2
, &mod
);
1240 if (ldb_ret
!= LDB_SUCCESS
) {
1248 * return a ldb_message representing the differences between msg1 and msg2.
1249 * If you then use this in a ldb_modify() call it can be used to save edits to a message
1251 * Result message is constructed as follows:
1252 * - LDB_FLAG_MOD_ADD - elements found only in msg2
1253 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1254 * Value for msg2 element is used
1255 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
1257 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1259 int ldb_msg_difference(struct ldb_context
*ldb
,
1260 TALLOC_CTX
*mem_ctx
,
1261 struct ldb_message
*msg1
,
1262 struct ldb_message
*msg2
,
1263 struct ldb_message
**_msg_out
)
1267 struct ldb_message
*mod
;
1268 struct ldb_message_element
*el
;
1269 TALLOC_CTX
*temp_ctx
;
1271 temp_ctx
= talloc_new(mem_ctx
);
1273 return LDB_ERR_OPERATIONS_ERROR
;
1276 mod
= ldb_msg_new(temp_ctx
);
1282 mod
->num_elements
= 0;
1283 mod
->elements
= NULL
;
1286 * Canonicalize *msg2 so we have no repeated elements
1287 * Resulting message is allocated in *mod's mem context,
1288 * as we are going to move some elements from *msg2 to
1291 ldb_res
= ldb_msg_normalize(ldb
, mod
, msg2
, &msg2
);
1292 if (ldb_res
!= LDB_SUCCESS
) {
1296 /* look in msg2 to find elements that need to be added or modified */
1297 for (i
=0;i
<msg2
->num_elements
;i
++) {
1298 el
= ldb_msg_find_element(msg1
, msg2
->elements
[i
].name
);
1300 if (el
&& ldb_msg_element_compare(el
, &msg2
->elements
[i
]) == 0) {
1304 ldb_res
= ldb_msg_add(mod
,
1306 el
? LDB_FLAG_MOD_REPLACE
: LDB_FLAG_MOD_ADD
);
1307 if (ldb_res
!= LDB_SUCCESS
) {
1312 /* look in msg1 to find elements that need to be deleted */
1313 for (i
=0;i
<msg1
->num_elements
;i
++) {
1314 el
= ldb_msg_find_element(msg2
, msg1
->elements
[i
].name
);
1316 ldb_res
= ldb_msg_add_empty(mod
,
1317 msg1
->elements
[i
].name
,
1318 LDB_FLAG_MOD_DELETE
, NULL
);
1319 if (ldb_res
!= LDB_SUCCESS
) {
1325 /* steal resulting message into supplied context */
1326 talloc_steal(mem_ctx
, mod
);
1329 talloc_free(temp_ctx
);
1333 talloc_free(temp_ctx
);
1334 return LDB_ERR_OPERATIONS_ERROR
;
1338 int ldb_msg_sanity_check(struct ldb_context
*ldb
,
1339 const struct ldb_message
*msg
)
1343 /* basic check on DN */
1344 if (msg
->dn
== NULL
) {
1345 ldb_set_errstring(ldb
, "ldb message lacks a DN!");
1346 return LDB_ERR_INVALID_DN_SYNTAX
;
1349 /* basic syntax checks */
1350 for (i
= 0; i
< msg
->num_elements
; i
++) {
1351 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
1352 if (msg
->elements
[i
].values
[j
].length
== 0) {
1353 /* an attribute cannot be empty */
1354 ldb_asprintf_errstring(ldb
, "Element %s has empty attribute in ldb message (%s)!",
1355 msg
->elements
[i
].name
,
1356 ldb_dn_get_linearized(msg
->dn
));
1357 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1369 copy an attribute list. This only copies the array, not the elements
1370 (ie. the elements are left as the same pointers)
1372 const char **ldb_attr_list_copy(TALLOC_CTX
*mem_ctx
, const char * const *attrs
)
1377 for (i
=0;attrs
&& attrs
[i
];i
++) /* noop */ ;
1378 ret
= talloc_array(mem_ctx
, const char *, i
+1);
1382 for (i
=0;attrs
&& attrs
[i
];i
++) {
1391 copy an attribute list. This only copies the array, not the elements
1392 (ie. the elements are left as the same pointers). The new attribute is added to the list.
1394 const char **ldb_attr_list_copy_add(TALLOC_CTX
*mem_ctx
, const char * const *attrs
, const char *new_attr
)
1400 for (i
=0;attrs
&& attrs
[i
];i
++) {
1401 if (ldb_attr_cmp(attrs
[i
], new_attr
) == 0) {
1406 return ldb_attr_list_copy(mem_ctx
, attrs
);
1408 ret
= talloc_array(mem_ctx
, const char *, i
+2);
1412 for (i
=0;attrs
&& attrs
[i
];i
++) {
1422 return 1 if an attribute is in a list of attributes, or 0 otherwise
1424 int ldb_attr_in_list(const char * const *attrs
, const char *attr
)
1427 for (i
=0;attrs
&& attrs
[i
];i
++) {
1428 if (ldb_attr_cmp(attrs
[i
], attr
) == 0) {
1437 rename the specified attribute in a search result
1439 int ldb_msg_rename_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
1441 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
1445 el
->name
= talloc_strdup(msg
->elements
, replace
);
1446 if (el
->name
== NULL
) {
1447 return LDB_ERR_OPERATIONS_ERROR
;
1454 copy the specified attribute in a search result to a new attribute
1456 int ldb_msg_copy_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
1458 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
1464 ret
= ldb_msg_add(msg
, el
, 0);
1465 if (ret
!= LDB_SUCCESS
) {
1468 return ldb_msg_rename_attr(msg
, attr
, replace
);
1472 remove the specified element in a search result
1474 void ldb_msg_remove_element(struct ldb_message
*msg
, struct ldb_message_element
*el
)
1476 ptrdiff_t n
= (el
- msg
->elements
);
1477 if (n
>= msg
->num_elements
|| n
< 0) {
1478 /* the element is not in the list. the caller is crazy. */
1481 msg
->num_elements
--;
1482 if (n
!= msg
->num_elements
) {
1483 memmove(el
, el
+1, (msg
->num_elements
- n
)*sizeof(*el
));
1489 remove the specified attribute in a search result
1491 void ldb_msg_remove_attr(struct ldb_message
*msg
, const char *attr
)
1493 struct ldb_message_element
*el
;
1495 while ((el
= ldb_msg_find_element(msg
, attr
)) != NULL
) {
1496 ldb_msg_remove_element(msg
, el
);
1501 return a LDAP formatted GeneralizedTime string
1503 char *ldb_timestring(TALLOC_CTX
*mem_ctx
, time_t t
)
1505 struct tm
*tm
= gmtime(&t
);
1513 /* we now excatly how long this string will be */
1514 ts
= talloc_array(mem_ctx
, char, 18);
1516 /* formatted like: 20040408072012.0Z */
1517 r
= snprintf(ts
, 18,
1518 "%04u%02u%02u%02u%02u%02u.0Z",
1519 tm
->tm_year
+1900, tm
->tm_mon
+1,
1520 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1533 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1535 time_t ldb_string_to_time(const char *s
)
1539 if (s
== NULL
) return 0;
1541 memset(&tm
, 0, sizeof(tm
));
1542 if (sscanf(s
, "%04u%02u%02u%02u%02u%02u.0Z",
1543 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1544 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1554 convert a LDAP GeneralizedTime string in ldb_val format to a
1557 int ldb_val_to_time(const struct ldb_val
*v
, time_t *t
)
1565 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1568 if (v
->data
== NULL
) {
1569 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1572 if (v
->length
< 16 && v
->length
!= 13) {
1573 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1576 if (v
->data
[v
->length
- 1] != 'Z') {
1577 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1580 if (v
->length
== 13) {
1581 memcpy(val
, v
->data
, 12);
1583 if (sscanf(val
, "%02u%02u%02u%02u%02u%02u",
1584 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1585 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1586 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1588 if (tm
.tm_year
< 50) {
1594 * anything between '.' and 'Z' is silently ignored.
1596 if (v
->data
[14] != '.') {
1597 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1600 memcpy(val
, v
->data
, 14);
1602 if (sscanf(val
, "%04u%02u%02u%02u%02u%02u",
1603 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1604 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1605 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1617 return a LDAP formatted UTCTime string
1619 char *ldb_timestring_utc(TALLOC_CTX
*mem_ctx
, time_t t
)
1621 struct tm
*tm
= gmtime(&t
);
1629 /* we now excatly how long this string will be */
1630 ts
= talloc_array(mem_ctx
, char, 14);
1632 /* formatted like: 20040408072012.0Z => 040408072012Z */
1633 r
= snprintf(ts
, 14,
1634 "%02u%02u%02u%02u%02u%02uZ",
1635 (tm
->tm_year
+1900)%100, tm
->tm_mon
+1,
1636 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1648 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1650 time_t ldb_string_utc_to_time(const char *s
)
1654 if (s
== NULL
) return 0;
1656 memset(&tm
, 0, sizeof(tm
));
1657 if (sscanf(s
, "%02u%02u%02u%02u%02u%02uZ",
1658 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1659 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1662 if (tm
.tm_year
< 50) {
1672 dump a set of results to a file. Useful from within gdb
1674 void ldb_dump_results(struct ldb_context
*ldb
, struct ldb_result
*result
, FILE *f
)
1678 for (i
= 0; i
< result
->count
; i
++) {
1679 struct ldb_ldif ldif
;
1680 fprintf(f
, "# record %d\n", i
+1);
1681 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
1682 ldif
.msg
= result
->msgs
[i
];
1683 ldb_ldif_write_file(ldb
, f
, &ldif
);
1688 checks for a string attribute. Returns "1" on match and otherwise "0".
1690 int ldb_msg_check_string_attribute(const struct ldb_message
*msg
,
1691 const char *name
, const char *value
)
1693 struct ldb_message_element
*el
;
1696 el
= ldb_msg_find_element(msg
, name
);
1701 val
.data
= discard_const_p(uint8_t, value
);
1702 val
.length
= strlen(value
);
1704 if (ldb_msg_find_val(el
, &val
)) {
1713 compare a ldb_val to a string
1715 int ldb_val_string_cmp(const struct ldb_val
*v
, const char *str
)
1717 size_t len
= strlen(str
);
1718 if (len
!= v
->length
) {
1719 return len
- v
->length
;
1721 return strncmp((const char *)v
->data
, str
, len
);