9c5a279b8a7d503474218f217957d1d027b82c3b
[samba.git] / source4 / 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                                  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                 errno = ENOMEM;
134                 return LDB_ERR_OPERATIONS_ERROR;
135         }
136
137         ZERO_STRUCT(els[msg->num_elements]);
138
139         msg->elements = els;
140         msg->num_elements++;
141
142         *return_el = &els[msg->num_elements-1];
143
144         return LDB_SUCCESS;
145 }
146
147 /**
148  * Add an empty element with a given name to a message
149  */
150 int ldb_msg_add_empty(struct ldb_message *msg,
151                       const char *attr_name,
152                       int flags,
153                       struct ldb_message_element **return_el)
154 {
155         int ret;
156         struct ldb_message_element *el;
157
158         ret = _ldb_msg_add_el(msg, &el);
159         if (ret != LDB_SUCCESS) {
160                 return ret;
161         }
162
163         /* initialize newly added element */
164         el->flags = flags;
165         el->name = talloc_strdup(msg->elements, attr_name);
166         if (!el->name) {
167                 errno = ENOMEM;
168                 return LDB_ERR_OPERATIONS_ERROR;
169         }
170
171         if (return_el) {
172                 *return_el = el;
173         }
174
175         return LDB_SUCCESS;
176 }
177
178 /**
179  * Adds an element to a message.
180  *
181  * NOTE: Ownership of ldb_message_element fields
182  *       is NOT transferred. Thus, if *el pointer
183  *       is invalidated for some reason, this will
184  *       corrupt *msg contents also
185  */
186 int ldb_msg_add(struct ldb_message *msg, 
187                 const struct ldb_message_element *el, 
188                 int flags)
189 {
190         int ret;
191         struct ldb_message_element *el_new;
192         /* We have to copy this, just in case *el is a pointer into
193          * what ldb_msg_add_empty() is about to realloc() */
194         struct ldb_message_element el_copy = *el;
195
196         ret = _ldb_msg_add_el(msg, &el_new);
197         if (ret != LDB_SUCCESS) {
198                 return ret;
199         }
200
201         el_new->flags      = flags;
202         el_new->name       = el_copy.name;
203         el_new->num_values = el_copy.num_values;
204         el_new->values     = el_copy.values;
205
206         return LDB_SUCCESS;
207 }
208
209 /*
210   add a value to a message
211 */
212 int ldb_msg_add_value(struct ldb_message *msg, 
213                       const char *attr_name,
214                       const struct ldb_val *val,
215                       struct ldb_message_element **return_el)
216 {
217         struct ldb_message_element *el;
218         struct ldb_val *vals;
219         int ret;
220
221         el = ldb_msg_find_element(msg, attr_name);
222         if (!el) {
223                 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
224                 if (ret != LDB_SUCCESS) {
225                         return ret;
226                 }
227         }
228
229         vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
230                               el->num_values+1);
231         if (!vals) {
232                 errno = ENOMEM;
233                 return LDB_ERR_OPERATIONS_ERROR;
234         }
235         el->values = vals;
236         el->values[el->num_values] = *val;
237         el->num_values++;
238
239         if (return_el) {
240                 *return_el = el;
241         }
242
243         return LDB_SUCCESS;
244 }
245
246
247 /*
248   add a value to a message, stealing it into the 'right' place
249 */
250 int ldb_msg_add_steal_value(struct ldb_message *msg, 
251                             const char *attr_name,
252                             struct ldb_val *val)
253 {
254         int ret;
255         struct ldb_message_element *el;
256
257         ret = ldb_msg_add_value(msg, attr_name, val, &el);
258         if (ret == LDB_SUCCESS) {
259                 talloc_steal(el->values, val->data);
260         }
261         return ret;
262 }
263
264
265 /*
266   add a string element to a message
267 */
268 int ldb_msg_add_string(struct ldb_message *msg, 
269                        const char *attr_name, const char *str)
270 {
271         struct ldb_val val;
272
273         val.data = discard_const_p(uint8_t, str);
274         val.length = strlen(str);
275
276         if (val.length == 0) {
277                 /* allow empty strings as non-existent attributes */
278                 return LDB_SUCCESS;
279         }
280
281         return ldb_msg_add_value(msg, attr_name, &val, NULL);
282 }
283
284 /*
285   add a string element to a message, stealing it into the 'right' place
286 */
287 int ldb_msg_add_steal_string(struct ldb_message *msg, 
288                              const char *attr_name, char *str)
289 {
290         struct ldb_val val;
291
292         val.data = (uint8_t *)str;
293         val.length = strlen(str);
294
295         if (val.length == 0) {
296                 /* allow empty strings as non-existent attributes */
297                 return LDB_SUCCESS;
298         }
299
300         return ldb_msg_add_steal_value(msg, attr_name, &val);
301 }
302
303 /*
304   add a DN element to a message
305   WARNING: this uses the linearized string from the dn, and does not
306   copy the string.
307 */
308 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
309                               struct ldb_dn *dn)
310 {
311         char *str = ldb_dn_alloc_linearized(msg, dn);
312
313         if (str == NULL) {
314                 /* we don't want to have unknown DNs added */
315                 return LDB_ERR_OPERATIONS_ERROR;
316         }
317
318         return ldb_msg_add_steal_string(msg, attr_name, str);
319 }
320
321 /*
322   add a printf formatted element to a message
323 */
324 int ldb_msg_add_fmt(struct ldb_message *msg, 
325                     const char *attr_name, const char *fmt, ...)
326 {
327         struct ldb_val val;
328         va_list ap;
329         char *str;
330
331         va_start(ap, fmt);
332         str = talloc_vasprintf(msg, fmt, ap);
333         va_end(ap);
334
335         if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
336
337         val.data   = (uint8_t *)str;
338         val.length = strlen(str);
339
340         return ldb_msg_add_steal_value(msg, attr_name, &val);
341 }
342
343 /*
344   compare two ldb_message_element structures
345   assumes case sensitive comparison
346 */
347 int ldb_msg_element_compare(struct ldb_message_element *el1, 
348                             struct ldb_message_element *el2)
349 {
350         unsigned int i;
351
352         if (el1->num_values != el2->num_values) {
353                 return el1->num_values - el2->num_values;
354         }
355
356         for (i=0;i<el1->num_values;i++) {
357                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
358                         return -1;
359                 }
360         }
361
362         return 0;
363 }
364
365 /*
366   compare two ldb_message_element structures
367   comparing by element name
368 */
369 int ldb_msg_element_compare_name(struct ldb_message_element *el1, 
370                                  struct ldb_message_element *el2)
371 {
372         return ldb_attr_cmp(el1->name, el2->name);
373 }
374
375 /*
376   convenience functions to return common types from a message
377   these return the first value if the attribute is multi-valued
378 */
379 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, 
380                                            const char *attr_name)
381 {
382         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
383         if (!el || el->num_values == 0) {
384                 return NULL;
385         }
386         return &el->values[0];
387 }
388
389 int ldb_msg_find_attr_as_int(const struct ldb_message *msg, 
390                              const char *attr_name,
391                              int default_value)
392 {
393         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
394         char buf[sizeof("-2147483648")];
395         char *end = NULL;
396         int ret;
397
398         if (!v || !v->data) {
399                 return default_value;
400         }
401
402         ZERO_STRUCT(buf);
403         if (v->length >= sizeof(buf)) {
404                 return default_value;
405         }
406
407         memcpy(buf, v->data, v->length);
408         errno = 0;
409         ret = (int) strtoll(buf, &end, 10);
410         if (errno != 0) {
411                 return default_value;
412         }
413         if (end && end[0] != '\0') {
414                 return default_value;
415         }
416         return ret;
417 }
418
419 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
420                                        const char *attr_name,
421                                        unsigned int default_value)
422 {
423         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
424         char buf[sizeof("-2147483648")];
425         char *end = NULL;
426         unsigned int ret;
427
428         if (!v || !v->data) {
429                 return default_value;
430         }
431
432         ZERO_STRUCT(buf);
433         if (v->length >= sizeof(buf)) {
434                 return default_value;
435         }
436
437         memcpy(buf, v->data, v->length);
438         errno = 0;
439         ret = (unsigned int) strtoll(buf, &end, 10);
440         if (errno != 0) {
441                 errno = 0;
442                 ret = (unsigned int) strtoull(buf, &end, 10);
443                 if (errno != 0) {
444                         return default_value;
445                 }
446         }
447         if (end && end[0] != '\0') {
448                 return default_value;
449         }
450         return ret;
451 }
452
453 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg, 
454                                    const char *attr_name,
455                                    int64_t default_value)
456 {
457         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
458         char buf[sizeof("-9223372036854775808")];
459         char *end = NULL;
460         int64_t ret;
461
462         if (!v || !v->data) {
463                 return default_value;
464         }
465
466         ZERO_STRUCT(buf);
467         if (v->length >= sizeof(buf)) {
468                 return default_value;
469         }
470
471         memcpy(buf, v->data, v->length);
472         errno = 0;
473         ret = (int64_t) strtoll(buf, &end, 10);
474         if (errno != 0) {
475                 return default_value;
476         }
477         if (end && end[0] != '\0') {
478                 return default_value;
479         }
480         return ret;
481 }
482
483 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
484                                      const char *attr_name,
485                                      uint64_t default_value)
486 {
487         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
488         char buf[sizeof("-9223372036854775808")];
489         char *end = NULL;
490         uint64_t ret;
491
492         if (!v || !v->data) {
493                 return default_value;
494         }
495
496         ZERO_STRUCT(buf);
497         if (v->length >= sizeof(buf)) {
498                 return default_value;
499         }
500
501         memcpy(buf, v->data, v->length);
502         errno = 0;
503         ret = (uint64_t) strtoll(buf, &end, 10);
504         if (errno != 0) {
505                 errno = 0;
506                 ret = (uint64_t) strtoull(buf, &end, 10);
507                 if (errno != 0) {
508                         return default_value;
509                 }
510         }
511         if (end && end[0] != '\0') {
512                 return default_value;
513         }
514         return ret;
515 }
516
517 double ldb_msg_find_attr_as_double(const struct ldb_message *msg, 
518                                    const char *attr_name,
519                                    double default_value)
520 {
521         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
522         char *buf;
523         char *end = NULL;
524         double ret;
525
526         if (!v || !v->data) {
527                 return default_value;
528         }
529         buf = talloc_strndup(msg, (const char *)v->data, v->length);
530         if (buf == NULL) {
531                 return default_value;
532         }
533
534         errno = 0;
535         ret = strtod(buf, &end);
536         talloc_free(buf);
537         if (errno != 0) {
538                 return default_value;
539         }
540         if (end && end[0] != '\0') {
541                 return default_value;
542         }
543         return ret;
544 }
545
546 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg, 
547                               const char *attr_name,
548                               int default_value)
549 {
550         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
551         if (!v || !v->data) {
552                 return default_value;
553         }
554         if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
555                 return 0;
556         }
557         if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
558                 return 1;
559         }
560         return default_value;
561 }
562
563 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg, 
564                                         const char *attr_name,
565                                         const char *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->data[v->length] != '\0') {
572                 return default_value;
573         }
574         return (const char *)v->data;
575 }
576
577 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
578                                        TALLOC_CTX *mem_ctx,
579                                        const struct ldb_message *msg,
580                                        const char *attr_name)
581 {
582         struct ldb_dn *res_dn;
583         const struct ldb_val *v;
584
585         v = ldb_msg_find_ldb_val(msg, attr_name);
586         if (!v || !v->data) {
587                 return NULL;
588         }
589         res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
590         if ( ! ldb_dn_validate(res_dn)) {
591                 talloc_free(res_dn);
592                 return NULL;
593         }
594         return res_dn;
595 }
596
597 /*
598   sort the elements of a message by name
599 */
600 void ldb_msg_sort_elements(struct ldb_message *msg)
601 {
602         TYPESAFE_QSORT(msg->elements, msg->num_elements,
603                        ldb_msg_element_compare_name);
604 }
605
606 /*
607   shallow copy a message - copying only the elements array so that the caller
608   can safely add new elements without changing the message
609 */
610 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, 
611                                          const struct ldb_message *msg)
612 {
613         struct ldb_message *msg2;
614         unsigned int i;
615
616         msg2 = talloc(mem_ctx, struct ldb_message);
617         if (msg2 == NULL) return NULL;
618
619         *msg2 = *msg;
620
621         msg2->elements = talloc_array(msg2, struct ldb_message_element, 
622                                       msg2->num_elements);
623         if (msg2->elements == NULL) goto failed;
624
625         for (i=0;i<msg2->num_elements;i++) {
626                 msg2->elements[i] = msg->elements[i];
627         }
628
629         return msg2;
630
631 failed:
632         talloc_free(msg2);
633         return NULL;
634 }
635
636
637 /*
638   copy a message, allocating new memory for all parts
639 */
640 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, 
641                                  const struct ldb_message *msg)
642 {
643         struct ldb_message *msg2;
644         unsigned int i, j;
645
646         msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
647         if (msg2 == NULL) return NULL;
648
649         msg2->dn = ldb_dn_copy(msg2, msg2->dn);
650         if (msg2->dn == NULL) goto failed;
651
652         for (i=0;i<msg2->num_elements;i++) {
653                 struct ldb_message_element *el = &msg2->elements[i];
654                 struct ldb_val *values = el->values;
655                 el->name = talloc_strdup(msg2->elements, el->name);
656                 if (el->name == NULL) goto failed;
657                 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
658                 for (j=0;j<el->num_values;j++) {
659                         el->values[j] = ldb_val_dup(el->values, &values[j]);
660                         if (el->values[j].data == NULL && values[j].length != 0) {
661                                 goto failed;
662                         }
663                 }
664         }
665
666         return msg2;
667
668 failed:
669         talloc_free(msg2);
670         return NULL;
671 }
672
673
674 /**
675  * Canonicalize a message, merging elements of the same name
676  */
677 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb, 
678                                          const struct ldb_message *msg)
679 {
680         int ret;
681         struct ldb_message *msg2;
682
683         /*
684          * Preserve previous behavior and allocate
685          * *msg2 into *ldb context
686          */
687         ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
688         if (ret != LDB_SUCCESS) {
689                 return NULL;
690         }
691
692         return msg2;
693 }
694
695 /**
696  * Canonicalize a message, merging elements of the same name
697  */
698 int ldb_msg_normalize(struct ldb_context *ldb,
699                       TALLOC_CTX *mem_ctx,
700                       const struct ldb_message *msg,
701                       struct ldb_message **_msg_out)
702 {
703         unsigned int i;
704         struct ldb_message *msg2;
705
706         msg2 = ldb_msg_copy(mem_ctx, msg);
707         if (msg2 == NULL) {
708                 return LDB_ERR_OPERATIONS_ERROR;
709         }
710
711         ldb_msg_sort_elements(msg2);
712
713         for (i=1; i < msg2->num_elements; i++) {
714                 struct ldb_message_element *el1 = &msg2->elements[i-1];
715                 struct ldb_message_element *el2 = &msg2->elements[i];
716
717                 if (ldb_msg_element_compare_name(el1, el2) == 0) {
718                         el1->values = talloc_realloc(msg2->elements,
719                                                      el1->values, struct ldb_val,
720                                                      el1->num_values + el2->num_values);
721                         if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
722                                 talloc_free(msg2);
723                                 return LDB_ERR_OPERATIONS_ERROR;
724                         }
725                         memcpy(el1->values + el1->num_values,
726                                el2->values,
727                                sizeof(struct ldb_val) * el2->num_values);
728                         el1->num_values += el2->num_values;
729                         talloc_free(discard_const_p(char, el2->name));
730                         if ((i+1) < msg2->num_elements) {
731                                 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
732                                         (msg2->num_elements - (i+1)));
733                         }
734                         msg2->num_elements--;
735                         i--;
736                 }
737         }
738
739         *_msg_out = msg2;
740         return LDB_SUCCESS;
741 }
742
743
744 /**
745  * return a ldb_message representing the differences between msg1 and msg2.
746  * If you then use this in a ldb_modify() call,
747  * it can be used to save edits to a message
748  */
749 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb, 
750                                  struct ldb_message *msg1,
751                                  struct ldb_message *msg2)
752 {
753         int ldb_ret;
754         struct ldb_message *mod;
755
756         ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
757         if (ldb_ret != LDB_SUCCESS) {
758                 return NULL;
759         }
760
761         return mod;
762 }
763
764 /**
765  * return a ldb_message representing the differences between msg1 and msg2.
766  * If you then use this in a ldb_modify() call it can be used to save edits to a message
767  *
768  * Result message is constructed as follows:
769  * - LDB_FLAG_MOD_ADD     - elements found only in msg2
770  * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
771  *                          Value for msg2 element is used
772  * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
773  *
774  * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
775  */
776 int ldb_msg_difference(struct ldb_context *ldb,
777                        TALLOC_CTX *mem_ctx,
778                        struct ldb_message *msg1,
779                        struct ldb_message *msg2,
780                        struct ldb_message **_msg_out)
781 {
782         int ldb_res;
783         unsigned int i;
784         struct ldb_message *mod;
785         struct ldb_message_element *el;
786         TALLOC_CTX *temp_ctx;
787
788         temp_ctx = talloc_new(mem_ctx);
789         if (!temp_ctx) {
790                 return LDB_ERR_OPERATIONS_ERROR;
791         }
792
793         mod = ldb_msg_new(temp_ctx);
794         if (mod == NULL) {
795                 goto failed;
796         }
797
798         mod->dn = msg1->dn;
799         mod->num_elements = 0;
800         mod->elements = NULL;
801
802         /*
803          * Canonicalize *msg2 so we have no repeated elements
804          * Resulting message is allocated in *mod's mem context,
805          * as we are going to move some elements from *msg2 to
806          * *mod object later
807          */
808         ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
809         if (ldb_res != LDB_SUCCESS) {
810                 goto failed;
811         }
812
813         /* look in msg2 to find elements that need to be added or modified */
814         for (i=0;i<msg2->num_elements;i++) {
815                 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
816
817                 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
818                         continue;
819                 }
820
821                 ldb_res = ldb_msg_add(mod,
822                                       &msg2->elements[i],
823                                       el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
824                 if (ldb_res != LDB_SUCCESS) {
825                         goto failed;
826                 }
827         }
828
829         /* look in msg1 to find elements that need to be deleted */
830         for (i=0;i<msg1->num_elements;i++) {
831                 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
832                 if (el == NULL) {
833                         ldb_res = ldb_msg_add_empty(mod,
834                                                     msg1->elements[i].name,
835                                                     LDB_FLAG_MOD_DELETE, NULL);
836                         if (ldb_res != LDB_SUCCESS) {
837                                 goto failed;
838                         }
839                 }
840         }
841
842         /* steal resulting message into supplied context */
843         talloc_steal(mem_ctx, mod);
844         *_msg_out = mod;
845
846         talloc_free(temp_ctx);
847         return LDB_SUCCESS;
848
849 failed:
850         talloc_free(temp_ctx);
851         return LDB_ERR_OPERATIONS_ERROR;
852 }
853
854
855 int ldb_msg_sanity_check(struct ldb_context *ldb, 
856                          const struct ldb_message *msg)
857 {
858         unsigned int i, j;
859
860         /* basic check on DN */
861         if (msg->dn == NULL) {
862                 ldb_set_errstring(ldb, "ldb message lacks a DN!");
863                 return LDB_ERR_INVALID_DN_SYNTAX;
864         }
865
866         /* basic syntax checks */
867         for (i = 0; i < msg->num_elements; i++) {
868                 for (j = 0; j < msg->elements[i].num_values; j++) {
869                         if (msg->elements[i].values[j].length == 0) {
870                                 /* an attribute cannot be empty */
871                                 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
872                                                             msg->elements[i].name, 
873                                                             ldb_dn_get_linearized(msg->dn));
874                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
875                         }
876                 }
877         }
878
879         return LDB_SUCCESS;
880 }
881
882
883
884
885 /*
886   copy an attribute list. This only copies the array, not the elements
887   (ie. the elements are left as the same pointers)
888 */
889 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
890 {
891         const char **ret;
892         unsigned int i;
893
894         for (i=0;attrs && attrs[i];i++) /* noop */ ;
895         ret = talloc_array(mem_ctx, const char *, i+1);
896         if (ret == NULL) {
897                 return NULL;
898         }
899         for (i=0;attrs && attrs[i];i++) {
900                 ret[i] = attrs[i];
901         }
902         ret[i] = attrs[i];
903         return ret;
904 }
905
906
907 /*
908   copy an attribute list. This only copies the array, not the elements
909   (ie. the elements are left as the same pointers).  The new attribute is added to the list.
910 */
911 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
912 {
913         const char **ret;
914         unsigned int i;
915         bool found = false;
916
917         for (i=0;attrs && attrs[i];i++) {
918                 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
919                         found = true;
920                 }
921         }
922         if (found) {
923                 return ldb_attr_list_copy(mem_ctx, attrs);
924         }
925         ret = talloc_array(mem_ctx, const char *, i+2);
926         if (ret == NULL) {
927                 return NULL;
928         }
929         for (i=0;attrs && attrs[i];i++) {
930                 ret[i] = attrs[i];
931         }
932         ret[i] = new_attr;
933         ret[i+1] = NULL;
934         return ret;
935 }
936
937
938 /*
939   return 1 if an attribute is in a list of attributes, or 0 otherwise
940 */
941 int ldb_attr_in_list(const char * const *attrs, const char *attr)
942 {
943         unsigned int i;
944         for (i=0;attrs && attrs[i];i++) {
945                 if (ldb_attr_cmp(attrs[i], attr) == 0) {
946                         return 1;
947                 }
948         }
949         return 0;
950 }
951
952
953 /*
954   rename the specified attribute in a search result
955 */
956 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
957 {
958         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
959         if (el == NULL) {
960                 return LDB_SUCCESS;
961         }
962         el->name = talloc_strdup(msg->elements, replace);
963         if (el->name == NULL) {
964                 return LDB_ERR_OPERATIONS_ERROR;
965         }
966         return LDB_SUCCESS;
967 }
968
969
970 /*
971   copy the specified attribute in a search result to a new attribute
972 */
973 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
974 {
975         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
976         int ret;
977
978         if (el == NULL) {
979                 return LDB_SUCCESS;
980         }
981         ret = ldb_msg_add(msg, el, 0);
982         if (ret != LDB_SUCCESS) {
983                 return ret;
984         }
985         return ldb_msg_rename_attr(msg, attr, replace);
986 }
987
988 /*
989   remove the specified element in a search result
990 */
991 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
992 {
993         ptrdiff_t n = (el - msg->elements);
994         if (n >= msg->num_elements) {
995                 /* should we abort() here? */
996                 return;
997         }
998         if (n != msg->num_elements-1) {
999                 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
1000         }
1001         msg->num_elements--;
1002 }
1003
1004
1005 /*
1006   remove the specified attribute in a search result
1007 */
1008 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1009 {
1010         struct ldb_message_element *el;
1011
1012         while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
1013                 ldb_msg_remove_element(msg, el);
1014         }
1015 }
1016
1017 /*
1018   return a LDAP formatted GeneralizedTime string
1019 */
1020 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1021 {
1022         struct tm *tm = gmtime(&t);
1023         char *ts;
1024         int r;
1025
1026         if (!tm) {
1027                 return NULL;
1028         }
1029
1030         /* we now excatly how long this string will be */
1031         ts = talloc_array(mem_ctx, char, 18);
1032
1033         /* formatted like: 20040408072012.0Z */
1034         r = snprintf(ts, 18,
1035                         "%04u%02u%02u%02u%02u%02u.0Z",
1036                         tm->tm_year+1900, tm->tm_mon+1,
1037                         tm->tm_mday, tm->tm_hour, tm->tm_min,
1038                         tm->tm_sec);
1039
1040         if (r != 17) {
1041                 talloc_free(ts);
1042                 return NULL;
1043         }
1044
1045         return ts;
1046 }
1047
1048 /*
1049   convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1050 */
1051 time_t ldb_string_to_time(const char *s)
1052 {
1053         struct tm tm;
1054         
1055         if (s == NULL) return 0;
1056         
1057         memset(&tm, 0, sizeof(tm));
1058         if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1059                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
1060                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1061                 return 0;
1062         }
1063         tm.tm_year -= 1900;
1064         tm.tm_mon -= 1;
1065         
1066         return timegm(&tm);
1067 }
1068
1069 /*
1070   convert a LDAP GeneralizedTime string in ldb_val format to a
1071   time_t.
1072 */
1073 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1074 {
1075         struct tm tm;
1076
1077         if (v == NULL || !v->data || v->length < 17) {
1078                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1079         }
1080
1081         memset(&tm, 0, sizeof(tm));
1082
1083         if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
1084                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1085                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1086                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1087         }
1088         tm.tm_year -= 1900;
1089         tm.tm_mon -= 1;
1090
1091         *t = timegm(&tm);
1092
1093         return LDB_SUCCESS;
1094 }
1095
1096 /*
1097   return a LDAP formatted UTCTime string
1098 */
1099 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1100 {
1101         struct tm *tm = gmtime(&t);
1102         char *ts;
1103         int r;
1104
1105         if (!tm) {
1106                 return NULL;
1107         }
1108
1109         /* we now excatly how long this string will be */
1110         ts = talloc_array(mem_ctx, char, 14);
1111
1112         /* formatted like: 20040408072012.0Z => 040408072012Z */
1113         r = snprintf(ts, 14,
1114                         "%02u%02u%02u%02u%02u%02uZ",
1115                         (tm->tm_year+1900)%100, tm->tm_mon+1,
1116                         tm->tm_mday, tm->tm_hour, tm->tm_min,
1117                         tm->tm_sec);
1118
1119         if (r != 13) {
1120                 talloc_free(ts);
1121                 return NULL;
1122         }
1123
1124         return ts;
1125 }
1126
1127 /*
1128   convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1129 */
1130 time_t ldb_string_utc_to_time(const char *s)
1131 {
1132         struct tm tm;
1133         
1134         if (s == NULL) return 0;
1135         
1136         memset(&tm, 0, sizeof(tm));
1137         if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1138                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
1139                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1140                 return 0;
1141         }
1142         if (tm.tm_year < 50) {
1143                 tm.tm_year += 100;
1144         }
1145         tm.tm_mon -= 1;
1146         
1147         return timegm(&tm);
1148 }
1149
1150
1151 /*
1152   dump a set of results to a file. Useful from within gdb
1153 */
1154 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1155 {
1156         unsigned int i;
1157
1158         for (i = 0; i < result->count; i++) {
1159                 struct ldb_ldif ldif;
1160                 fprintf(f, "# record %d\n", i+1);
1161                 ldif.changetype = LDB_CHANGETYPE_NONE;
1162                 ldif.msg = result->msgs[i];
1163                 ldb_ldif_write_file(ldb, f, &ldif);
1164         }
1165 }
1166
1167 /*
1168   checks for a string attribute. Returns "1" on match and otherwise "0".
1169 */
1170 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1171                                    const char *name, const char *value)
1172 {
1173         struct ldb_message_element *el;
1174         struct ldb_val val;
1175         
1176         el = ldb_msg_find_element(msg, name);
1177         if (el == NULL) {
1178                 return 0;
1179         }
1180
1181         val.data = discard_const_p(uint8_t, value);
1182         val.length = strlen(value);
1183
1184         if (ldb_msg_find_val(el, &val)) {
1185                 return 1;
1186         }
1187
1188         return 0;
1189 }
1190