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