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 duplicate a ldb_val structure
95 struct ldb_val
ldb_val_dup(TALLOC_CTX
*mem_ctx
, const struct ldb_val
*v
)
98 v2
.length
= v
->length
;
99 if (v
->data
== NULL
) {
104 /* the +1 is to cope with buggy C library routines like strndup
105 that look one byte beyond */
106 v2
.data
= talloc_array(mem_ctx
, uint8_t, v
->length
+1);
112 memcpy(v2
.data
, v
->data
, v
->length
);
113 ((char *)v2
.data
)[v
->length
] = 0;
118 * Adds new empty element to msg->elements
120 static int _ldb_msg_add_el(struct ldb_message
*msg
,
121 struct ldb_message_element
**return_el
)
123 struct ldb_message_element
*els
;
126 * TODO: Find out a way to assert on input parameters.
127 * msg and return_el must be valid
130 els
= talloc_realloc(msg
, msg
->elements
,
131 struct ldb_message_element
, msg
->num_elements
+ 1);
133 return LDB_ERR_OPERATIONS_ERROR
;
136 ZERO_STRUCT(els
[msg
->num_elements
]);
141 *return_el
= &els
[msg
->num_elements
-1];
147 * Add an empty element with a given name to a message
149 int ldb_msg_add_empty(struct ldb_message
*msg
,
150 const char *attr_name
,
152 struct ldb_message_element
**return_el
)
155 struct ldb_message_element
*el
;
157 ret
= _ldb_msg_add_el(msg
, &el
);
158 if (ret
!= LDB_SUCCESS
) {
162 /* initialize newly added element */
164 el
->name
= talloc_strdup(msg
->elements
, attr_name
);
166 return LDB_ERR_OPERATIONS_ERROR
;
177 * Adds an element to a message.
179 * NOTE: Ownership of ldb_message_element fields
180 * is NOT transferred. Thus, if *el pointer
181 * is invalidated for some reason, this will
182 * corrupt *msg contents also
184 int ldb_msg_add(struct ldb_message
*msg
,
185 const struct ldb_message_element
*el
,
189 struct ldb_message_element
*el_new
;
190 /* We have to copy this, just in case *el is a pointer into
191 * what ldb_msg_add_empty() is about to realloc() */
192 struct ldb_message_element el_copy
= *el
;
194 ret
= _ldb_msg_add_el(msg
, &el_new
);
195 if (ret
!= LDB_SUCCESS
) {
199 el_new
->flags
= flags
;
200 el_new
->name
= el_copy
.name
;
201 el_new
->num_values
= el_copy
.num_values
;
202 el_new
->values
= el_copy
.values
;
208 add a value to a message
210 int ldb_msg_add_value(struct ldb_message
*msg
,
211 const char *attr_name
,
212 const struct ldb_val
*val
,
213 struct ldb_message_element
**return_el
)
215 struct ldb_message_element
*el
;
216 struct ldb_val
*vals
;
219 el
= ldb_msg_find_element(msg
, attr_name
);
221 ret
= ldb_msg_add_empty(msg
, attr_name
, 0, &el
);
222 if (ret
!= LDB_SUCCESS
) {
227 vals
= talloc_realloc(msg
->elements
, el
->values
, struct ldb_val
,
230 return LDB_ERR_OPERATIONS_ERROR
;
233 el
->values
[el
->num_values
] = *val
;
245 add a value to a message, stealing it into the 'right' place
247 int ldb_msg_add_steal_value(struct ldb_message
*msg
,
248 const char *attr_name
,
252 struct ldb_message_element
*el
;
254 ret
= ldb_msg_add_value(msg
, attr_name
, val
, &el
);
255 if (ret
== LDB_SUCCESS
) {
256 talloc_steal(el
->values
, val
->data
);
263 add a string element to a message
265 int ldb_msg_add_string(struct ldb_message
*msg
,
266 const char *attr_name
, const char *str
)
270 val
.data
= discard_const_p(uint8_t, str
);
271 val
.length
= strlen(str
);
273 if (val
.length
== 0) {
274 /* allow empty strings as non-existent attributes */
278 return ldb_msg_add_value(msg
, attr_name
, &val
, NULL
);
282 add a string element to a message, stealing it into the 'right' place
284 int ldb_msg_add_steal_string(struct ldb_message
*msg
,
285 const char *attr_name
, char *str
)
289 val
.data
= (uint8_t *)str
;
290 val
.length
= strlen(str
);
292 if (val
.length
== 0) {
293 /* allow empty strings as non-existent attributes */
297 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
301 add a DN element to a message
302 WARNING: this uses the linearized string from the dn, and does not
305 int ldb_msg_add_linearized_dn(struct ldb_message
*msg
, const char *attr_name
,
308 char *str
= ldb_dn_alloc_linearized(msg
, dn
);
311 /* we don't want to have unknown DNs added */
312 return LDB_ERR_OPERATIONS_ERROR
;
315 return ldb_msg_add_steal_string(msg
, attr_name
, str
);
319 add a printf formatted element to a message
321 int ldb_msg_add_fmt(struct ldb_message
*msg
,
322 const char *attr_name
, const char *fmt
, ...)
329 str
= talloc_vasprintf(msg
, fmt
, ap
);
332 if (str
== NULL
) return LDB_ERR_OPERATIONS_ERROR
;
334 val
.data
= (uint8_t *)str
;
335 val
.length
= strlen(str
);
337 return ldb_msg_add_steal_value(msg
, attr_name
, &val
);
341 compare two ldb_message_element structures
342 assumes case sensitive comparison
344 int ldb_msg_element_compare(struct ldb_message_element
*el1
,
345 struct ldb_message_element
*el2
)
349 if (el1
->num_values
!= el2
->num_values
) {
350 return el1
->num_values
- el2
->num_values
;
353 for (i
=0;i
<el1
->num_values
;i
++) {
354 if (!ldb_msg_find_val(el2
, &el1
->values
[i
])) {
363 compare two ldb_message_element structures.
364 Different ordering is considered a mismatch
366 bool ldb_msg_element_equal_ordered(const struct ldb_message_element
*el1
,
367 const struct ldb_message_element
*el2
)
370 if (el1
->num_values
!= el2
->num_values
) {
373 for (i
=0;i
<el1
->num_values
;i
++) {
374 if (ldb_val_equal_exact(&el1
->values
[i
],
375 &el2
->values
[i
]) != 1) {
383 compare two ldb_message_element structures
384 comparing by element name
386 int ldb_msg_element_compare_name(struct ldb_message_element
*el1
,
387 struct ldb_message_element
*el2
)
389 return ldb_attr_cmp(el1
->name
, el2
->name
);
393 convenience functions to return common types from a message
394 these return the first value if the attribute is multi-valued
396 const struct ldb_val
*ldb_msg_find_ldb_val(const struct ldb_message
*msg
,
397 const char *attr_name
)
399 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr_name
);
400 if (!el
|| el
->num_values
== 0) {
403 return &el
->values
[0];
406 int ldb_msg_find_attr_as_int(const struct ldb_message
*msg
,
407 const char *attr_name
,
410 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
411 char buf
[sizeof("-2147483648")];
415 if (!v
|| !v
->data
) {
416 return default_value
;
420 if (v
->length
>= sizeof(buf
)) {
421 return default_value
;
424 memcpy(buf
, v
->data
, v
->length
);
426 ret
= (int) strtoll(buf
, &end
, 10);
428 return default_value
;
430 if (end
&& end
[0] != '\0') {
431 return default_value
;
436 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message
*msg
,
437 const char *attr_name
,
438 unsigned int default_value
)
440 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
441 char buf
[sizeof("-2147483648")];
445 if (!v
|| !v
->data
) {
446 return default_value
;
450 if (v
->length
>= sizeof(buf
)) {
451 return default_value
;
454 memcpy(buf
, v
->data
, v
->length
);
456 ret
= (unsigned int) strtoll(buf
, &end
, 10);
459 ret
= (unsigned int) strtoull(buf
, &end
, 10);
461 return default_value
;
464 if (end
&& end
[0] != '\0') {
465 return default_value
;
470 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message
*msg
,
471 const char *attr_name
,
472 int64_t default_value
)
474 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
475 char buf
[sizeof("-9223372036854775808")];
479 if (!v
|| !v
->data
) {
480 return default_value
;
484 if (v
->length
>= sizeof(buf
)) {
485 return default_value
;
488 memcpy(buf
, v
->data
, v
->length
);
490 ret
= (int64_t) strtoll(buf
, &end
, 10);
492 return default_value
;
494 if (end
&& end
[0] != '\0') {
495 return default_value
;
500 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message
*msg
,
501 const char *attr_name
,
502 uint64_t default_value
)
504 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
505 char buf
[sizeof("-9223372036854775808")];
509 if (!v
|| !v
->data
) {
510 return default_value
;
514 if (v
->length
>= sizeof(buf
)) {
515 return default_value
;
518 memcpy(buf
, v
->data
, v
->length
);
520 ret
= (uint64_t) strtoll(buf
, &end
, 10);
523 ret
= (uint64_t) strtoull(buf
, &end
, 10);
525 return default_value
;
528 if (end
&& end
[0] != '\0') {
529 return default_value
;
534 double ldb_msg_find_attr_as_double(const struct ldb_message
*msg
,
535 const char *attr_name
,
536 double default_value
)
538 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
543 if (!v
|| !v
->data
) {
544 return default_value
;
546 buf
= talloc_strndup(msg
, (const char *)v
->data
, v
->length
);
548 return default_value
;
552 ret
= strtod(buf
, &end
);
555 return default_value
;
557 if (end
&& end
[0] != '\0') {
558 return default_value
;
563 int ldb_msg_find_attr_as_bool(const struct ldb_message
*msg
,
564 const char *attr_name
,
567 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
568 if (!v
|| !v
->data
) {
569 return default_value
;
571 if (v
->length
== 5 && strncasecmp((const char *)v
->data
, "FALSE", 5) == 0) {
574 if (v
->length
== 4 && strncasecmp((const char *)v
->data
, "TRUE", 4) == 0) {
577 return default_value
;
580 const char *ldb_msg_find_attr_as_string(const struct ldb_message
*msg
,
581 const char *attr_name
,
582 const char *default_value
)
584 const struct ldb_val
*v
= ldb_msg_find_ldb_val(msg
, attr_name
);
585 if (!v
|| !v
->data
) {
586 return default_value
;
588 if (v
->data
[v
->length
] != '\0') {
589 return default_value
;
591 return (const char *)v
->data
;
594 struct ldb_dn
*ldb_msg_find_attr_as_dn(struct ldb_context
*ldb
,
596 const struct ldb_message
*msg
,
597 const char *attr_name
)
599 struct ldb_dn
*res_dn
;
600 const struct ldb_val
*v
;
602 v
= ldb_msg_find_ldb_val(msg
, attr_name
);
603 if (!v
|| !v
->data
) {
606 res_dn
= ldb_dn_from_ldb_val(mem_ctx
, ldb
, v
);
607 if ( ! ldb_dn_validate(res_dn
)) {
615 sort the elements of a message by name
617 void ldb_msg_sort_elements(struct ldb_message
*msg
)
619 TYPESAFE_QSORT(msg
->elements
, msg
->num_elements
,
620 ldb_msg_element_compare_name
);
624 shallow copy a message - copying only the elements array so that the caller
625 can safely add new elements without changing the message
627 struct ldb_message
*ldb_msg_copy_shallow(TALLOC_CTX
*mem_ctx
,
628 const struct ldb_message
*msg
)
630 struct ldb_message
*msg2
;
633 msg2
= talloc(mem_ctx
, struct ldb_message
);
634 if (msg2
== NULL
) return NULL
;
638 msg2
->elements
= talloc_array(msg2
, struct ldb_message_element
,
640 if (msg2
->elements
== NULL
) goto failed
;
642 for (i
=0;i
<msg2
->num_elements
;i
++) {
643 msg2
->elements
[i
] = msg
->elements
[i
];
655 copy a message, allocating new memory for all parts
657 struct ldb_message
*ldb_msg_copy(TALLOC_CTX
*mem_ctx
,
658 const struct ldb_message
*msg
)
660 struct ldb_message
*msg2
;
663 msg2
= ldb_msg_copy_shallow(mem_ctx
, msg
);
664 if (msg2
== NULL
) return NULL
;
666 msg2
->dn
= ldb_dn_copy(msg2
, msg2
->dn
);
667 if (msg2
->dn
== NULL
) goto failed
;
669 for (i
=0;i
<msg2
->num_elements
;i
++) {
670 struct ldb_message_element
*el
= &msg2
->elements
[i
];
671 struct ldb_val
*values
= el
->values
;
672 el
->name
= talloc_strdup(msg2
->elements
, el
->name
);
673 if (el
->name
== NULL
) goto failed
;
674 el
->values
= talloc_array(msg2
->elements
, struct ldb_val
, el
->num_values
);
675 if (el
->values
== NULL
) goto failed
;
676 for (j
=0;j
<el
->num_values
;j
++) {
677 el
->values
[j
] = ldb_val_dup(el
->values
, &values
[j
]);
678 if (el
->values
[j
].data
== NULL
&& values
[j
].length
!= 0) {
693 * Canonicalize a message, merging elements of the same name
695 struct ldb_message
*ldb_msg_canonicalize(struct ldb_context
*ldb
,
696 const struct ldb_message
*msg
)
699 struct ldb_message
*msg2
;
702 * Preserve previous behavior and allocate
703 * *msg2 into *ldb context
705 ret
= ldb_msg_normalize(ldb
, ldb
, msg
, &msg2
);
706 if (ret
!= LDB_SUCCESS
) {
714 * Canonicalize a message, merging elements of the same name
716 int ldb_msg_normalize(struct ldb_context
*ldb
,
718 const struct ldb_message
*msg
,
719 struct ldb_message
**_msg_out
)
722 struct ldb_message
*msg2
;
724 msg2
= ldb_msg_copy(mem_ctx
, msg
);
726 return LDB_ERR_OPERATIONS_ERROR
;
729 ldb_msg_sort_elements(msg2
);
731 for (i
=1; i
< msg2
->num_elements
; i
++) {
732 struct ldb_message_element
*el1
= &msg2
->elements
[i
-1];
733 struct ldb_message_element
*el2
= &msg2
->elements
[i
];
735 if (ldb_msg_element_compare_name(el1
, el2
) == 0) {
736 el1
->values
= talloc_realloc(msg2
->elements
,
737 el1
->values
, struct ldb_val
,
738 el1
->num_values
+ el2
->num_values
);
739 if (el1
->num_values
+ el2
->num_values
> 0 && el1
->values
== NULL
) {
741 return LDB_ERR_OPERATIONS_ERROR
;
743 memcpy(el1
->values
+ el1
->num_values
,
745 sizeof(struct ldb_val
) * el2
->num_values
);
746 el1
->num_values
+= el2
->num_values
;
747 talloc_free(discard_const_p(char, el2
->name
));
748 if ((i
+1) < msg2
->num_elements
) {
749 memmove(el2
, el2
+1, sizeof(struct ldb_message_element
) *
750 (msg2
->num_elements
- (i
+1)));
752 msg2
->num_elements
--;
763 * return a ldb_message representing the differences between msg1 and msg2.
764 * If you then use this in a ldb_modify() call,
765 * it can be used to save edits to a message
767 struct ldb_message
*ldb_msg_diff(struct ldb_context
*ldb
,
768 struct ldb_message
*msg1
,
769 struct ldb_message
*msg2
)
772 struct ldb_message
*mod
;
774 ldb_ret
= ldb_msg_difference(ldb
, ldb
, msg1
, msg2
, &mod
);
775 if (ldb_ret
!= LDB_SUCCESS
) {
783 * return a ldb_message representing the differences between msg1 and msg2.
784 * If you then use this in a ldb_modify() call it can be used to save edits to a message
786 * Result message is constructed as follows:
787 * - LDB_FLAG_MOD_ADD - elements found only in msg2
788 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
789 * Value for msg2 element is used
790 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
792 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
794 int ldb_msg_difference(struct ldb_context
*ldb
,
796 struct ldb_message
*msg1
,
797 struct ldb_message
*msg2
,
798 struct ldb_message
**_msg_out
)
802 struct ldb_message
*mod
;
803 struct ldb_message_element
*el
;
804 TALLOC_CTX
*temp_ctx
;
806 temp_ctx
= talloc_new(mem_ctx
);
808 return LDB_ERR_OPERATIONS_ERROR
;
811 mod
= ldb_msg_new(temp_ctx
);
817 mod
->num_elements
= 0;
818 mod
->elements
= NULL
;
821 * Canonicalize *msg2 so we have no repeated elements
822 * Resulting message is allocated in *mod's mem context,
823 * as we are going to move some elements from *msg2 to
826 ldb_res
= ldb_msg_normalize(ldb
, mod
, msg2
, &msg2
);
827 if (ldb_res
!= LDB_SUCCESS
) {
831 /* look in msg2 to find elements that need to be added or modified */
832 for (i
=0;i
<msg2
->num_elements
;i
++) {
833 el
= ldb_msg_find_element(msg1
, msg2
->elements
[i
].name
);
835 if (el
&& ldb_msg_element_compare(el
, &msg2
->elements
[i
]) == 0) {
839 ldb_res
= ldb_msg_add(mod
,
841 el
? LDB_FLAG_MOD_REPLACE
: LDB_FLAG_MOD_ADD
);
842 if (ldb_res
!= LDB_SUCCESS
) {
847 /* look in msg1 to find elements that need to be deleted */
848 for (i
=0;i
<msg1
->num_elements
;i
++) {
849 el
= ldb_msg_find_element(msg2
, msg1
->elements
[i
].name
);
851 ldb_res
= ldb_msg_add_empty(mod
,
852 msg1
->elements
[i
].name
,
853 LDB_FLAG_MOD_DELETE
, NULL
);
854 if (ldb_res
!= LDB_SUCCESS
) {
860 /* steal resulting message into supplied context */
861 talloc_steal(mem_ctx
, mod
);
864 talloc_free(temp_ctx
);
868 talloc_free(temp_ctx
);
869 return LDB_ERR_OPERATIONS_ERROR
;
873 int ldb_msg_sanity_check(struct ldb_context
*ldb
,
874 const struct ldb_message
*msg
)
878 /* basic check on DN */
879 if (msg
->dn
== NULL
) {
880 ldb_set_errstring(ldb
, "ldb message lacks a DN!");
881 return LDB_ERR_INVALID_DN_SYNTAX
;
884 /* basic syntax checks */
885 for (i
= 0; i
< msg
->num_elements
; i
++) {
886 for (j
= 0; j
< msg
->elements
[i
].num_values
; j
++) {
887 if (msg
->elements
[i
].values
[j
].length
== 0) {
888 /* an attribute cannot be empty */
889 ldb_asprintf_errstring(ldb
, "Element %s has empty attribute in ldb message (%s)!",
890 msg
->elements
[i
].name
,
891 ldb_dn_get_linearized(msg
->dn
));
892 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
904 copy an attribute list. This only copies the array, not the elements
905 (ie. the elements are left as the same pointers)
907 const char **ldb_attr_list_copy(TALLOC_CTX
*mem_ctx
, const char * const *attrs
)
912 for (i
=0;attrs
&& attrs
[i
];i
++) /* noop */ ;
913 ret
= talloc_array(mem_ctx
, const char *, i
+1);
917 for (i
=0;attrs
&& attrs
[i
];i
++) {
926 copy an attribute list. This only copies the array, not the elements
927 (ie. the elements are left as the same pointers). The new attribute is added to the list.
929 const char **ldb_attr_list_copy_add(TALLOC_CTX
*mem_ctx
, const char * const *attrs
, const char *new_attr
)
935 for (i
=0;attrs
&& attrs
[i
];i
++) {
936 if (ldb_attr_cmp(attrs
[i
], new_attr
) == 0) {
941 return ldb_attr_list_copy(mem_ctx
, attrs
);
943 ret
= talloc_array(mem_ctx
, const char *, i
+2);
947 for (i
=0;attrs
&& attrs
[i
];i
++) {
957 return 1 if an attribute is in a list of attributes, or 0 otherwise
959 int ldb_attr_in_list(const char * const *attrs
, const char *attr
)
962 for (i
=0;attrs
&& attrs
[i
];i
++) {
963 if (ldb_attr_cmp(attrs
[i
], attr
) == 0) {
972 rename the specified attribute in a search result
974 int ldb_msg_rename_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
976 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
980 el
->name
= talloc_strdup(msg
->elements
, replace
);
981 if (el
->name
== NULL
) {
982 return LDB_ERR_OPERATIONS_ERROR
;
989 copy the specified attribute in a search result to a new attribute
991 int ldb_msg_copy_attr(struct ldb_message
*msg
, const char *attr
, const char *replace
)
993 struct ldb_message_element
*el
= ldb_msg_find_element(msg
, attr
);
999 ret
= ldb_msg_add(msg
, el
, 0);
1000 if (ret
!= LDB_SUCCESS
) {
1003 return ldb_msg_rename_attr(msg
, attr
, replace
);
1007 remove the specified element in a search result
1009 void ldb_msg_remove_element(struct ldb_message
*msg
, struct ldb_message_element
*el
)
1011 ptrdiff_t n
= (el
- msg
->elements
);
1012 if (n
>= msg
->num_elements
) {
1013 /* should we abort() here? */
1016 if (n
!= msg
->num_elements
-1) {
1017 memmove(el
, el
+1, ((msg
->num_elements
-1) - n
)*sizeof(*el
));
1019 msg
->num_elements
--;
1024 remove the specified attribute in a search result
1026 void ldb_msg_remove_attr(struct ldb_message
*msg
, const char *attr
)
1028 struct ldb_message_element
*el
;
1030 while ((el
= ldb_msg_find_element(msg
, attr
)) != NULL
) {
1031 ldb_msg_remove_element(msg
, el
);
1036 return a LDAP formatted GeneralizedTime string
1038 char *ldb_timestring(TALLOC_CTX
*mem_ctx
, time_t t
)
1040 struct tm
*tm
= gmtime(&t
);
1048 /* we now excatly how long this string will be */
1049 ts
= talloc_array(mem_ctx
, char, 18);
1051 /* formatted like: 20040408072012.0Z */
1052 r
= snprintf(ts
, 18,
1053 "%04u%02u%02u%02u%02u%02u.0Z",
1054 tm
->tm_year
+1900, tm
->tm_mon
+1,
1055 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1067 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1069 time_t ldb_string_to_time(const char *s
)
1073 if (s
== NULL
) return 0;
1075 memset(&tm
, 0, sizeof(tm
));
1076 if (sscanf(s
, "%04u%02u%02u%02u%02u%02u.0Z",
1077 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1078 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1088 convert a LDAP GeneralizedTime string in ldb_val format to a
1091 int ldb_val_to_time(const struct ldb_val
*v
, time_t *t
)
1097 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1100 if (v
->data
== NULL
) {
1101 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1104 if (v
->length
< 16 && v
->length
!= 13) {
1105 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1108 if (v
->data
[v
->length
- 1] != 'Z') {
1109 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1112 if (v
->length
== 13) {
1113 memcpy(val
, v
->data
, 12);
1115 if (sscanf(val
, "%02u%02u%02u%02u%02u%02u",
1116 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1117 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1118 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1120 if (tm
.tm_year
< 50) {
1126 * anything between '.' and 'Z' is silently ignored.
1128 if (v
->data
[14] != '.') {
1129 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1132 memcpy(val
, v
->data
, 14);
1134 if (sscanf(val
, "%04u%02u%02u%02u%02u%02u",
1135 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1136 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1137 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
;
1149 return a LDAP formatted UTCTime string
1151 char *ldb_timestring_utc(TALLOC_CTX
*mem_ctx
, time_t t
)
1153 struct tm
*tm
= gmtime(&t
);
1161 /* we now excatly how long this string will be */
1162 ts
= talloc_array(mem_ctx
, char, 14);
1164 /* formatted like: 20040408072012.0Z => 040408072012Z */
1165 r
= snprintf(ts
, 14,
1166 "%02u%02u%02u%02u%02u%02uZ",
1167 (tm
->tm_year
+1900)%100, tm
->tm_mon
+1,
1168 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1180 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1182 time_t ldb_string_utc_to_time(const char *s
)
1186 if (s
== NULL
) return 0;
1188 memset(&tm
, 0, sizeof(tm
));
1189 if (sscanf(s
, "%02u%02u%02u%02u%02u%02uZ",
1190 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
1191 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
) != 6) {
1194 if (tm
.tm_year
< 50) {
1204 dump a set of results to a file. Useful from within gdb
1206 void ldb_dump_results(struct ldb_context
*ldb
, struct ldb_result
*result
, FILE *f
)
1210 for (i
= 0; i
< result
->count
; i
++) {
1211 struct ldb_ldif ldif
;
1212 fprintf(f
, "# record %d\n", i
+1);
1213 ldif
.changetype
= LDB_CHANGETYPE_NONE
;
1214 ldif
.msg
= result
->msgs
[i
];
1215 ldb_ldif_write_file(ldb
, f
, &ldif
);
1220 checks for a string attribute. Returns "1" on match and otherwise "0".
1222 int ldb_msg_check_string_attribute(const struct ldb_message
*msg
,
1223 const char *name
, const char *value
)
1225 struct ldb_message_element
*el
;
1228 el
= ldb_msg_find_element(msg
, name
);
1233 val
.data
= discard_const_p(uint8_t, value
);
1234 val
.length
= strlen(value
);
1236 if (ldb_msg_find_val(el
, &val
)) {
1245 compare a ldb_val to a string
1247 int ldb_val_string_cmp(const struct ldb_val
*v
, const char *str
)
1249 size_t len
= strlen(str
);
1250 if (len
!= v
->length
) {
1251 return len
- v
->length
;
1253 return strncmp((const char *)v
->data
, str
, len
);