bbed284dcdae25b240a2cd5eafdae3982d950ec9
[metze/samba/wip.git] / lib / ldb / common / ldb_msg.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
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.
14
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.
19
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/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb message component utility functions
28  *
29  *  Description: functions for manipulating ldb_message structures
30  *
31  *  Author: Andrew Tridgell
32  */
33
34 #include "ldb_private.h"
35
36 /*
37   create a new ldb_message in a given memory context (NULL for top level)
38 */
39 struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
40 {
41         return talloc_zero(mem_ctx, struct ldb_message);
42 }
43
44 /*
45   find an element in a message by attribute name
46 */
47 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, 
48                                                  const char *attr_name)
49 {
50         unsigned int i;
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];
54                 }
55         }
56         return NULL;
57 }
58
59 /*
60   see if two ldb_val structures contain exactly the same data
61   return 1 for a match, 0 for a mis-match
62 */
63 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
64 {
65         if (v1->length != v2->length) return 0;
66         if (v1->data == v2->data) return 1;
67         if (v1->length == 0) return 1;
68
69         if (memcmp(v1->data, v2->data, v1->length) == 0) {
70                 return 1;
71         }
72
73         return 0;
74 }
75
76 /*
77   find a value in an element
78   assumes case sensitive comparison
79 */
80 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, 
81                                  const struct ldb_val *val)
82 {
83         unsigned int i;
84         for (i=0;i<el->num_values;i++) {
85                 if (ldb_val_equal_exact(val, &el->values[i])) {
86                         return &el->values[i];
87                 }
88         }
89         return NULL;
90 }
91
92 /*
93   duplicate a ldb_val structure
94 */
95 struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
96 {
97         struct ldb_val v2;
98         v2.length = v->length;
99         if (v->data == NULL) {
100                 v2.data = NULL;
101                 return v2;
102         }
103
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);
107         if (!v2.data) {
108                 v2.length = 0;
109                 return v2;
110         }
111
112         memcpy(v2.data, v->data, v->length);
113         ((char *)v2.data)[v->length] = 0;
114         return v2;
115 }
116
117 /**
118  * Adds new empty element to msg->elements
119  */
120 static int _ldb_msg_add_el(struct ldb_message *msg,
121                            struct ldb_message_element **return_el)
122 {
123         struct ldb_message_element *els;
124
125         /*
126          * TODO: Find out a way to assert on input parameters.
127          * msg and return_el must be valid
128          */
129
130         els = talloc_realloc(msg, msg->elements,
131                              struct ldb_message_element, msg->num_elements + 1);
132         if (!els) {
133                 return LDB_ERR_OPERATIONS_ERROR;
134         }
135
136         ZERO_STRUCT(els[msg->num_elements]);
137
138         msg->elements = els;
139         msg->num_elements++;
140
141         *return_el = &els[msg->num_elements-1];
142
143         return LDB_SUCCESS;
144 }
145
146 /**
147  * Add an empty element with a given name to a message
148  */
149 int ldb_msg_add_empty(struct ldb_message *msg,
150                       const char *attr_name,
151                       int flags,
152                       struct ldb_message_element **return_el)
153 {
154         int ret;
155         struct ldb_message_element *el;
156
157         ret = _ldb_msg_add_el(msg, &el);
158         if (ret != LDB_SUCCESS) {
159                 return ret;
160         }
161
162         /* initialize newly added element */
163         el->flags = flags;
164         el->name = talloc_strdup(msg->elements, attr_name);
165         if (!el->name) {
166                 return LDB_ERR_OPERATIONS_ERROR;
167         }
168
169         if (return_el) {
170                 *return_el = el;
171         }
172
173         return LDB_SUCCESS;
174 }
175
176 /**
177  * Adds an element to a message.
178  *
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
183  */
184 int ldb_msg_add(struct ldb_message *msg, 
185                 const struct ldb_message_element *el, 
186                 int flags)
187 {
188         int ret;
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;
193
194         ret = _ldb_msg_add_el(msg, &el_new);
195         if (ret != LDB_SUCCESS) {
196                 return ret;
197         }
198
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;
203
204         return LDB_SUCCESS;
205 }
206
207 /*
208   add a value to a message
209 */
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)
214 {
215         struct ldb_message_element *el;
216         struct ldb_val *vals;
217         int ret;
218
219         el = ldb_msg_find_element(msg, attr_name);
220         if (!el) {
221                 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
222                 if (ret != LDB_SUCCESS) {
223                         return ret;
224                 }
225         }
226
227         vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
228                               el->num_values+1);
229         if (!vals) {
230                 return LDB_ERR_OPERATIONS_ERROR;
231         }
232         el->values = vals;
233         el->values[el->num_values] = *val;
234         el->num_values++;
235
236         if (return_el) {
237                 *return_el = el;
238         }
239
240         return LDB_SUCCESS;
241 }
242
243
244 /*
245   add a value to a message, stealing it into the 'right' place
246 */
247 int ldb_msg_add_steal_value(struct ldb_message *msg, 
248                             const char *attr_name,
249                             struct ldb_val *val)
250 {
251         int ret;
252         struct ldb_message_element *el;
253
254         ret = ldb_msg_add_value(msg, attr_name, val, &el);
255         if (ret == LDB_SUCCESS) {
256                 talloc_steal(el->values, val->data);
257         }
258         return ret;
259 }
260
261
262 /*
263   add a string element to a message
264 */
265 int ldb_msg_add_string(struct ldb_message *msg, 
266                        const char *attr_name, const char *str)
267 {
268         struct ldb_val val;
269
270         val.data = discard_const_p(uint8_t, str);
271         val.length = strlen(str);
272
273         if (val.length == 0) {
274                 /* allow empty strings as non-existent attributes */
275                 return LDB_SUCCESS;
276         }
277
278         return ldb_msg_add_value(msg, attr_name, &val, NULL);
279 }
280
281 /*
282   add a string element to a message, stealing it into the 'right' place
283 */
284 int ldb_msg_add_steal_string(struct ldb_message *msg, 
285                              const char *attr_name, char *str)
286 {
287         struct ldb_val val;
288
289         val.data = (uint8_t *)str;
290         val.length = strlen(str);
291
292         if (val.length == 0) {
293                 /* allow empty strings as non-existent attributes */
294                 return LDB_SUCCESS;
295         }
296
297         return ldb_msg_add_steal_value(msg, attr_name, &val);
298 }
299
300 /*
301   add a DN element to a message
302   WARNING: this uses the linearized string from the dn, and does not
303   copy the string.
304 */
305 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
306                               struct ldb_dn *dn)
307 {
308         char *str = ldb_dn_alloc_linearized(msg, dn);
309
310         if (str == NULL) {
311                 /* we don't want to have unknown DNs added */
312                 return LDB_ERR_OPERATIONS_ERROR;
313         }
314
315         return ldb_msg_add_steal_string(msg, attr_name, str);
316 }
317
318 /*
319   add a printf formatted element to a message
320 */
321 int ldb_msg_add_fmt(struct ldb_message *msg, 
322                     const char *attr_name, const char *fmt, ...)
323 {
324         struct ldb_val val;
325         va_list ap;
326         char *str;
327
328         va_start(ap, fmt);
329         str = talloc_vasprintf(msg, fmt, ap);
330         va_end(ap);
331
332         if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
333
334         val.data   = (uint8_t *)str;
335         val.length = strlen(str);
336
337         return ldb_msg_add_steal_value(msg, attr_name, &val);
338 }
339
340 /*
341   compare two ldb_message_element structures
342   assumes case sensitive comparison
343 */
344 int ldb_msg_element_compare(struct ldb_message_element *el1, 
345                             struct ldb_message_element *el2)
346 {
347         unsigned int i;
348
349         if (el1->num_values != el2->num_values) {
350                 return el1->num_values - el2->num_values;
351         }
352
353         for (i=0;i<el1->num_values;i++) {
354                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
355                         return -1;
356                 }
357         }
358
359         return 0;
360 }
361
362 /*
363   compare two ldb_message_element structures.
364   Different ordering is considered a mismatch
365 */
366 bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
367                                    const struct ldb_message_element *el2)
368 {
369         unsigned i;
370         if (el1->num_values != el2->num_values) {
371                 return false;
372         }
373         for (i=0;i<el1->num_values;i++) {
374                 if (ldb_val_equal_exact(&el1->values[i],
375                                         &el2->values[i]) != 1) {
376                         return false;
377                 }
378         }
379         return true;
380 }
381
382 /*
383   compare two ldb_message_element structures
384   comparing by element name
385 */
386 int ldb_msg_element_compare_name(struct ldb_message_element *el1, 
387                                  struct ldb_message_element *el2)
388 {
389         return ldb_attr_cmp(el1->name, el2->name);
390 }
391
392 /*
393   convenience functions to return common types from a message
394   these return the first value if the attribute is multi-valued
395 */
396 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, 
397                                            const char *attr_name)
398 {
399         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
400         if (!el || el->num_values == 0) {
401                 return NULL;
402         }
403         return &el->values[0];
404 }
405
406 int ldb_msg_find_attr_as_int(const struct ldb_message *msg, 
407                              const char *attr_name,
408                              int default_value)
409 {
410         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
411         char buf[sizeof("-2147483648")];
412         char *end = NULL;
413         int ret;
414
415         if (!v || !v->data) {
416                 return default_value;
417         }
418
419         ZERO_STRUCT(buf);
420         if (v->length >= sizeof(buf)) {
421                 return default_value;
422         }
423
424         memcpy(buf, v->data, v->length);
425         errno = 0;
426         ret = (int) strtoll(buf, &end, 10);
427         if (errno != 0) {
428                 return default_value;
429         }
430         if (end && end[0] != '\0') {
431                 return default_value;
432         }
433         return ret;
434 }
435
436 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
437                                        const char *attr_name,
438                                        unsigned int default_value)
439 {
440         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
441         char buf[sizeof("-2147483648")];
442         char *end = NULL;
443         unsigned int ret;
444
445         if (!v || !v->data) {
446                 return default_value;
447         }
448
449         ZERO_STRUCT(buf);
450         if (v->length >= sizeof(buf)) {
451                 return default_value;
452         }
453
454         memcpy(buf, v->data, v->length);
455         errno = 0;
456         ret = (unsigned int) strtoll(buf, &end, 10);
457         if (errno != 0) {
458                 errno = 0;
459                 ret = (unsigned int) strtoull(buf, &end, 10);
460                 if (errno != 0) {
461                         return default_value;
462                 }
463         }
464         if (end && end[0] != '\0') {
465                 return default_value;
466         }
467         return ret;
468 }
469
470 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, 
471                                    const char *attr_name,
472                                    int64_t default_value)
473 {
474         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
475         char buf[sizeof("-9223372036854775808")];
476         char *end = NULL;
477         int64_t ret;
478
479         if (!v || !v->data) {
480                 return default_value;
481         }
482
483         ZERO_STRUCT(buf);
484         if (v->length >= sizeof(buf)) {
485                 return default_value;
486         }
487
488         memcpy(buf, v->data, v->length);
489         errno = 0;
490         ret = (int64_t) strtoll(buf, &end, 10);
491         if (errno != 0) {
492                 return default_value;
493         }
494         if (end && end[0] != '\0') {
495                 return default_value;
496         }
497         return ret;
498 }
499
500 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
501                                      const char *attr_name,
502                                      uint64_t default_value)
503 {
504         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
505         char buf[sizeof("-9223372036854775808")];
506         char *end = NULL;
507         uint64_t ret;
508
509         if (!v || !v->data) {
510                 return default_value;
511         }
512
513         ZERO_STRUCT(buf);
514         if (v->length >= sizeof(buf)) {
515                 return default_value;
516         }
517
518         memcpy(buf, v->data, v->length);
519         errno = 0;
520         ret = (uint64_t) strtoll(buf, &end, 10);
521         if (errno != 0) {
522                 errno = 0;
523                 ret = (uint64_t) strtoull(buf, &end, 10);
524                 if (errno != 0) {
525                         return default_value;
526                 }
527         }
528         if (end && end[0] != '\0') {
529                 return default_value;
530         }
531         return ret;
532 }
533
534 double ldb_msg_find_attr_as_double(const struct ldb_message *msg, 
535                                    const char *attr_name,
536                                    double default_value)
537 {
538         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
539         char *buf;
540         char *end = NULL;
541         double ret;
542
543         if (!v || !v->data) {
544                 return default_value;
545         }
546         buf = talloc_strndup(msg, (const char *)v->data, v->length);
547         if (buf == NULL) {
548                 return default_value;
549         }
550
551         errno = 0;
552         ret = strtod(buf, &end);
553         talloc_free(buf);
554         if (errno != 0) {
555                 return default_value;
556         }
557         if (end && end[0] != '\0') {
558                 return default_value;
559         }
560         return ret;
561 }
562
563 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, 
564                               const char *attr_name,
565                               int default_value)
566 {
567         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
568         if (!v || !v->data) {
569                 return default_value;
570         }
571         if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
572                 return 0;
573         }
574         if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
575                 return 1;
576         }
577         return default_value;
578 }
579
580 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, 
581                                         const char *attr_name,
582                                         const char *default_value)
583 {
584         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
585         if (!v || !v->data) {
586                 return default_value;
587         }
588         if (v->data[v->length] != '\0') {
589                 return default_value;
590         }
591         return (const char *)v->data;
592 }
593
594 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
595                                        TALLOC_CTX *mem_ctx,
596                                        const struct ldb_message *msg,
597                                        const char *attr_name)
598 {
599         struct ldb_dn *res_dn;
600         const struct ldb_val *v;
601
602         v = ldb_msg_find_ldb_val(msg, attr_name);
603         if (!v || !v->data) {
604                 return NULL;
605         }
606         res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
607         if ( ! ldb_dn_validate(res_dn)) {
608                 talloc_free(res_dn);
609                 return NULL;
610         }
611         return res_dn;
612 }
613
614 /*
615   sort the elements of a message by name
616 */
617 void ldb_msg_sort_elements(struct ldb_message *msg)
618 {
619         TYPESAFE_QSORT(msg->elements, msg->num_elements,
620                        ldb_msg_element_compare_name);
621 }
622
623 /*
624   shallow copy a message - copying only the elements array so that the caller
625   can safely add new elements without changing the message
626 */
627 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, 
628                                          const struct ldb_message *msg)
629 {
630         struct ldb_message *msg2;
631         unsigned int i;
632
633         msg2 = talloc(mem_ctx, struct ldb_message);
634         if (msg2 == NULL) return NULL;
635
636         *msg2 = *msg;
637
638         msg2->elements = talloc_array(msg2, struct ldb_message_element, 
639                                       msg2->num_elements);
640         if (msg2->elements == NULL) goto failed;
641
642         for (i=0;i<msg2->num_elements;i++) {
643                 msg2->elements[i] = msg->elements[i];
644         }
645
646         return msg2;
647
648 failed:
649         talloc_free(msg2);
650         return NULL;
651 }
652
653
654 /*
655   copy a message, allocating new memory for all parts
656 */
657 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, 
658                                  const struct ldb_message *msg)
659 {
660         struct ldb_message *msg2;
661         unsigned int i, j;
662
663         msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
664         if (msg2 == NULL) return NULL;
665
666         msg2->dn = ldb_dn_copy(msg2, msg2->dn);
667         if (msg2->dn == NULL) goto failed;
668
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) {
679                                 goto failed;
680                         }
681                 }
682         }
683
684         return msg2;
685
686 failed:
687         talloc_free(msg2);
688         return NULL;
689 }
690
691
692 /**
693  * Canonicalize a message, merging elements of the same name
694  */
695 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 
696                                          const struct ldb_message *msg)
697 {
698         int ret;
699         struct ldb_message *msg2;
700
701         /*
702          * Preserve previous behavior and allocate
703          * *msg2 into *ldb context
704          */
705         ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
706         if (ret != LDB_SUCCESS) {
707                 return NULL;
708         }
709
710         return msg2;
711 }
712
713 /**
714  * Canonicalize a message, merging elements of the same name
715  */
716 int ldb_msg_normalize(struct ldb_context *ldb,
717                       TALLOC_CTX *mem_ctx,
718                       const struct ldb_message *msg,
719                       struct ldb_message **_msg_out)
720 {
721         unsigned int i;
722         struct ldb_message *msg2;
723
724         msg2 = ldb_msg_copy(mem_ctx, msg);
725         if (msg2 == NULL) {
726                 return LDB_ERR_OPERATIONS_ERROR;
727         }
728
729         ldb_msg_sort_elements(msg2);
730
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];
734
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) {
740                                 talloc_free(msg2);
741                                 return LDB_ERR_OPERATIONS_ERROR;
742                         }
743                         memcpy(el1->values + el1->num_values,
744                                el2->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)));
751                         }
752                         msg2->num_elements--;
753                         i--;
754                 }
755         }
756
757         *_msg_out = msg2;
758         return LDB_SUCCESS;
759 }
760
761
762 /**
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
766  */
767 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, 
768                                  struct ldb_message *msg1,
769                                  struct ldb_message *msg2)
770 {
771         int ldb_ret;
772         struct ldb_message *mod;
773
774         ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
775         if (ldb_ret != LDB_SUCCESS) {
776                 return NULL;
777         }
778
779         return mod;
780 }
781
782 /**
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
785  *
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
791  *
792  * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
793  */
794 int ldb_msg_difference(struct ldb_context *ldb,
795                        TALLOC_CTX *mem_ctx,
796                        struct ldb_message *msg1,
797                        struct ldb_message *msg2,
798                        struct ldb_message **_msg_out)
799 {
800         int ldb_res;
801         unsigned int i;
802         struct ldb_message *mod;
803         struct ldb_message_element *el;
804         TALLOC_CTX *temp_ctx;
805
806         temp_ctx = talloc_new(mem_ctx);
807         if (!temp_ctx) {
808                 return LDB_ERR_OPERATIONS_ERROR;
809         }
810
811         mod = ldb_msg_new(temp_ctx);
812         if (mod == NULL) {
813                 goto failed;
814         }
815
816         mod->dn = msg1->dn;
817         mod->num_elements = 0;
818         mod->elements = NULL;
819
820         /*
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
824          * *mod object later
825          */
826         ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
827         if (ldb_res != LDB_SUCCESS) {
828                 goto failed;
829         }
830
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);
834
835                 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
836                         continue;
837                 }
838
839                 ldb_res = ldb_msg_add(mod,
840                                       &msg2->elements[i],
841                                       el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
842                 if (ldb_res != LDB_SUCCESS) {
843                         goto failed;
844                 }
845         }
846
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);
850                 if (el == NULL) {
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) {
855                                 goto failed;
856                         }
857                 }
858         }
859
860         /* steal resulting message into supplied context */
861         talloc_steal(mem_ctx, mod);
862         *_msg_out = mod;
863
864         talloc_free(temp_ctx);
865         return LDB_SUCCESS;
866
867 failed:
868         talloc_free(temp_ctx);
869         return LDB_ERR_OPERATIONS_ERROR;
870 }
871
872
873 int ldb_msg_sanity_check(struct ldb_context *ldb, 
874                          const struct ldb_message *msg)
875 {
876         unsigned int i, j;
877
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;
882         }
883
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;
893                         }
894                 }
895         }
896
897         return LDB_SUCCESS;
898 }
899
900
901
902
903 /*
904   copy an attribute list. This only copies the array, not the elements
905   (ie. the elements are left as the same pointers)
906 */
907 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
908 {
909         const char **ret;
910         unsigned int i;
911
912         for (i=0;attrs && attrs[i];i++) /* noop */ ;
913         ret = talloc_array(mem_ctx, const char *, i+1);
914         if (ret == NULL) {
915                 return NULL;
916         }
917         for (i=0;attrs && attrs[i];i++) {
918                 ret[i] = attrs[i];
919         }
920         ret[i] = attrs[i];
921         return ret;
922 }
923
924
925 /*
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.
928 */
929 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
930 {
931         const char **ret;
932         unsigned int i;
933         bool found = false;
934
935         for (i=0;attrs && attrs[i];i++) {
936                 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
937                         found = true;
938                 }
939         }
940         if (found) {
941                 return ldb_attr_list_copy(mem_ctx, attrs);
942         }
943         ret = talloc_array(mem_ctx, const char *, i+2);
944         if (ret == NULL) {
945                 return NULL;
946         }
947         for (i=0;attrs && attrs[i];i++) {
948                 ret[i] = attrs[i];
949         }
950         ret[i] = new_attr;
951         ret[i+1] = NULL;
952         return ret;
953 }
954
955
956 /*
957   return 1 if an attribute is in a list of attributes, or 0 otherwise
958 */
959 int ldb_attr_in_list(const char * const *attrs, const char *attr)
960 {
961         unsigned int i;
962         for (i=0;attrs && attrs[i];i++) {
963                 if (ldb_attr_cmp(attrs[i], attr) == 0) {
964                         return 1;
965                 }
966         }
967         return 0;
968 }
969
970
971 /*
972   rename the specified attribute in a search result
973 */
974 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
975 {
976         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
977         if (el == NULL) {
978                 return LDB_SUCCESS;
979         }
980         el->name = talloc_strdup(msg->elements, replace);
981         if (el->name == NULL) {
982                 return LDB_ERR_OPERATIONS_ERROR;
983         }
984         return LDB_SUCCESS;
985 }
986
987
988 /*
989   copy the specified attribute in a search result to a new attribute
990 */
991 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
992 {
993         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
994         int ret;
995
996         if (el == NULL) {
997                 return LDB_SUCCESS;
998         }
999         ret = ldb_msg_add(msg, el, 0);
1000         if (ret != LDB_SUCCESS) {
1001                 return ret;
1002         }
1003         return ldb_msg_rename_attr(msg, attr, replace);
1004 }
1005
1006 /*
1007   remove the specified element in a search result
1008 */
1009 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1010 {
1011         ptrdiff_t n = (el - msg->elements);
1012         if (n >= msg->num_elements) {
1013                 /* should we abort() here? */
1014                 return;
1015         }
1016         if (n != msg->num_elements-1) {
1017                 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
1018         }
1019         msg->num_elements--;
1020 }
1021
1022
1023 /*
1024   remove the specified attribute in a search result
1025 */
1026 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1027 {
1028         struct ldb_message_element *el;
1029
1030         while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
1031                 ldb_msg_remove_element(msg, el);
1032         }
1033 }
1034
1035 /*
1036   return a LDAP formatted GeneralizedTime string
1037 */
1038 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1039 {
1040         struct tm *tm = gmtime(&t);
1041         char *ts;
1042         int r;
1043
1044         if (!tm) {
1045                 return NULL;
1046         }
1047
1048         /* we now excatly how long this string will be */
1049         ts = talloc_array(mem_ctx, char, 18);
1050
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,
1056                         tm->tm_sec);
1057
1058         if (r != 17) {
1059                 talloc_free(ts);
1060                 return NULL;
1061         }
1062
1063         return ts;
1064 }
1065
1066 /*
1067   convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1068 */
1069 time_t ldb_string_to_time(const char *s)
1070 {
1071         struct tm tm;
1072         
1073         if (s == NULL) return 0;
1074         
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) {
1079                 return 0;
1080         }
1081         tm.tm_year -= 1900;
1082         tm.tm_mon -= 1;
1083         
1084         return timegm(&tm);
1085 }
1086
1087 /*
1088   convert a LDAP GeneralizedTime string in ldb_val format to a
1089   time_t.
1090 */
1091 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1092 {
1093         struct tm tm;
1094
1095         if (v == NULL || !v->data || (v->length != 17 && v->length != 13)) {
1096                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1097         }
1098
1099         memset(&tm, 0, sizeof(tm));
1100
1101         if (v->length == 13) {
1102                 if (sscanf((char *)v->data, "%02u%02u%02u%02u%02u%02uZ",
1103                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1104                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1105                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1106                 }
1107         } else {
1108                 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
1109                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1110                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1111                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1112                 }
1113         }
1114         tm.tm_year -= 1900;
1115         tm.tm_mon -= 1;
1116
1117         *t = timegm(&tm);
1118
1119         return LDB_SUCCESS;
1120 }
1121
1122 /*
1123   return a LDAP formatted UTCTime string
1124 */
1125 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1126 {
1127         struct tm *tm = gmtime(&t);
1128         char *ts;
1129         int r;
1130
1131         if (!tm) {
1132                 return NULL;
1133         }
1134
1135         /* we now excatly how long this string will be */
1136         ts = talloc_array(mem_ctx, char, 14);
1137
1138         /* formatted like: 20040408072012.0Z => 040408072012Z */
1139         r = snprintf(ts, 14,
1140                         "%02u%02u%02u%02u%02u%02uZ",
1141                         (tm->tm_year+1900)%100, tm->tm_mon+1,
1142                         tm->tm_mday, tm->tm_hour, tm->tm_min,
1143                         tm->tm_sec);
1144
1145         if (r != 13) {
1146                 talloc_free(ts);
1147                 return NULL;
1148         }
1149
1150         return ts;
1151 }
1152
1153 /*
1154   convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1155 */
1156 time_t ldb_string_utc_to_time(const char *s)
1157 {
1158         struct tm tm;
1159         
1160         if (s == NULL) return 0;
1161         
1162         memset(&tm, 0, sizeof(tm));
1163         if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1164                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
1165                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1166                 return 0;
1167         }
1168         if (tm.tm_year < 50) {
1169                 tm.tm_year += 100;
1170         }
1171         tm.tm_mon -= 1;
1172         
1173         return timegm(&tm);
1174 }
1175
1176
1177 /*
1178   dump a set of results to a file. Useful from within gdb
1179 */
1180 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1181 {
1182         unsigned int i;
1183
1184         for (i = 0; i < result->count; i++) {
1185                 struct ldb_ldif ldif;
1186                 fprintf(f, "# record %d\n", i+1);
1187                 ldif.changetype = LDB_CHANGETYPE_NONE;
1188                 ldif.msg = result->msgs[i];
1189                 ldb_ldif_write_file(ldb, f, &ldif);
1190         }
1191 }
1192
1193 /*
1194   checks for a string attribute. Returns "1" on match and otherwise "0".
1195 */
1196 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1197                                    const char *name, const char *value)
1198 {
1199         struct ldb_message_element *el;
1200         struct ldb_val val;
1201         
1202         el = ldb_msg_find_element(msg, name);
1203         if (el == NULL) {
1204                 return 0;
1205         }
1206
1207         val.data = discard_const_p(uint8_t, value);
1208         val.length = strlen(value);
1209
1210         if (ldb_msg_find_val(el, &val)) {
1211                 return 1;
1212         }
1213
1214         return 0;
1215 }
1216
1217
1218 /*
1219   compare a ldb_val to a string
1220 */
1221 int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1222 {
1223         size_t len = strlen(str);
1224         if (len != v->length) {
1225                 return len - v->length;
1226         }
1227         return strncmp((const char *)v->data, str, len);
1228 }