LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_msg.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-lts cc996e7c Lines: 556 689 80.7 %
Date: 2025-10-17 03:45:34 Functions: 60 66 90.9 %

          Line data    Source code
       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   527353849 : struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
      40             : {
      41   527353849 :         return talloc_zero(mem_ctx, struct ldb_message);
      42             : }
      43             : 
      44             : /*
      45             :   find an element in a message by attribute name
      46             : */
      47  6591984562 : struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
      48             :                                                  const char *attr_name)
      49             : {
      50             :         unsigned int i;
      51 92878459116 :         for (i=0;i<msg->num_elements;i++) {
      52 88225835522 :                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
      53  1939360968 :                         return &msg->elements[i];
      54             :                 }
      55             :         }
      56  4652623594 :         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   228254104 : int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
      64             : {
      65   228254104 :         if (v1->length != v2->length) return 0;
      66    39550898 :         if (v1->data == v2->data) return 1;
      67    39473350 :         if (v1->length == 0) return 1;
      68             : 
      69    39473350 :         if (memcmp(v1->data, v2->data, v1->length) == 0) {
      70    24211128 :                 return 1;
      71             :         }
      72             : 
      73    15262222 :         return 0;
      74             : }
      75             : 
      76             : /*
      77             :   find a value in an element
      78             :   assumes case sensitive comparison
      79             : */
      80    18041768 : struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
      81             :                                  struct ldb_val *val)
      82             : {
      83             :         unsigned int i;
      84   211488128 :         for (i=0;i<el->num_values;i++) {
      85   211238973 :                 if (ldb_val_equal_exact(val, &el->values[i])) {
      86    17792613 :                         return &el->values[i];
      87             :                 }
      88             :         }
      89      249155 :         return NULL;
      90             : }
      91             : 
      92             : 
      93     6441380 : static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
      94             : {
      95     6441380 :         if (v1->length != v2->length) {
      96     5383669 :                 return v1->length - v2->length;
      97             :         }
      98     1057711 :         return memcmp(v1->data, v2->data, v1->length);
      99             : }
     100             : 
     101             : 
     102             : /*
     103             :   ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first
     104             :   duplicate value it finds. It does a case sensitive comparison (memcmp).
     105             : 
     106             :   LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
     107             :   options flag, otherwise LDB_SUCCESS.
     108             : */
     109             : #define LDB_DUP_QUADRATIC_THRESHOLD 10
     110             : 
     111    22046369 : int ldb_msg_find_duplicate_val(struct ldb_context *ldb,
     112             :                                TALLOC_CTX *mem_ctx,
     113             :                                const struct ldb_message_element *el,
     114             :                                struct ldb_val **duplicate,
     115             :                                uint32_t options)
     116             : {
     117             :         unsigned int i, j;
     118             :         struct ldb_val *val;
     119             : 
     120    22046369 :         if (options != 0) {
     121           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     122             :         }
     123             : 
     124    22046369 :         *duplicate = NULL;
     125             : 
     126             :         /*
     127             :            If there are not many values, it is best to avoid the talloc
     128             :            overhead and just do a brute force search.
     129             :          */
     130    22046369 :         if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
     131    45875179 :                 for (j = 0; j < el->num_values; j++) {
     132    23870501 :                         val = &el->values[j];
     133    27546556 :                         for ( i = j + 1; i < el->num_values; i++) {
     134     3676058 :                                 if (ldb_val_equal_exact(val, &el->values[i])) {
     135           3 :                                         *duplicate = val;
     136           3 :                                         return LDB_SUCCESS;
     137             :                                 }
     138             :                         }
     139             :                 }
     140             :         } else {
     141             :                 struct ldb_val *values;
     142       41688 :                 values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
     143       41688 :                 if (values == NULL) {
     144           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     145             :                 }
     146             : 
     147       41688 :                 memcpy(values, el->values,
     148       41688 :                        el->num_values * sizeof(struct ldb_val));
     149       41688 :                 TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
     150     1496087 :                 for (i = 1; i < el->num_values; i++) {
     151     1454400 :                         if (ldb_val_equal_exact(&values[i],
     152     1454400 :                                                 &values[i - 1])) {
     153             :                                 /* find the original location */
     154           3 :                                 for (j = 0; j < el->num_values; j++) {
     155           3 :                                         if (ldb_val_equal_exact(&values[i],
     156           3 :                                                                 &el->values[j])
     157             :                                                 ) {
     158           1 :                                                 *duplicate = &el->values[j];
     159           1 :                                                 break;
     160             :                                         }
     161             :                                 }
     162           1 :                                 talloc_free(values);
     163           1 :                                 if (*duplicate == NULL) {
     164             :                                         /* how we got here, I don't know */
     165           0 :                                         return LDB_ERR_OPERATIONS_ERROR;
     166             :                                 }
     167           1 :                                 return LDB_SUCCESS;
     168             :                         }
     169             :                 }
     170       41687 :                 talloc_free(values);
     171             :         }
     172    22046365 :         return LDB_SUCCESS;
     173             : }
     174             : 
     175             : 
     176             : /*
     177             :   Determine whether the values in an element are also in another element.
     178             : 
     179             :   Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements
     180             :   share values, or LDB_SUCCESS if they don't. In this case, the function
     181             :   simply determines the set intersection and it doesn't matter in which order
     182             :   the elements are provided.
     183             : 
     184             :   With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are
     185             :   removed from the first element and LDB_SUCCESS is returned.
     186             : 
     187             :   LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option.
     188             :   LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name.
     189             : */
     190             : 
     191        3472 : int ldb_msg_find_common_values(struct ldb_context *ldb,
     192             :                                TALLOC_CTX *mem_ctx,
     193             :                                struct ldb_message_element *el,
     194             :                                struct ldb_message_element *el2,
     195             :                                uint32_t options)
     196             : {
     197             :         struct ldb_val *values;
     198             :         struct ldb_val *values2;
     199             :         unsigned int i, j, k, n_values;
     200             : 
     201        3472 :         bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
     202             : 
     203        3472 :         if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
     204           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     205             :         }
     206             : 
     207        3472 :         if (strcmp(el->name, el2->name) != 0) {
     208           1 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     209             :         }
     210        3471 :         if (el->num_values == 0 || el2->num_values == 0) {
     211          12 :                 return LDB_SUCCESS;
     212             :         }
     213             :         /*
     214             :            With few values, it is better to do the brute-force search than the
     215             :            clever search involving tallocs, memcpys, sorts, etc.
     216             :         */
     217        3591 :         if (MIN(el->num_values, el2->num_values) == 1 ||
     218         157 :             MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
     219       15396 :                 for (i = 0; i < el2->num_values; i++) {
     220       24592 :                         for (j = 0; j < el->num_values; j++) {
     221       12555 :                                 if (ldb_val_equal_exact(&el->values[j],
     222       12555 :                                                         &el2->values[i])) {
     223           8 :                                         if (! remove_duplicates) {
     224             :                                             return                      \
     225           6 :                                               LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     226             :                                         }
     227             :                                         /*
     228             :                                           With the remove_duplicates flag, we
     229             :                                           resolve the intersection by removing
     230             :                                           the offending one from el.
     231             :                                         */
     232           2 :                                         el->num_values--;
     233           3 :                                         for (k = j; k < el->num_values; k++) {
     234           1 :                                                 el->values[k] = \
     235           1 :                                                         el->values[k + 1];
     236             :                                         }
     237           2 :                                         j--; /* rewind */
     238             :                                 }
     239             :                         }
     240             :                 }
     241        3353 :                 return LDB_SUCCESS;
     242             :         }
     243             : 
     244         100 :         values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
     245         100 :         if (values == NULL) {
     246           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     247             :         }
     248         100 :         values2 = talloc_array(mem_ctx, struct ldb_val,
     249             :                                     el2->num_values);
     250         100 :         if (values2 == NULL) {
     251           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     252             :         }
     253             : 
     254         100 :         memcpy(values, el->values,
     255         100 :                el->num_values * sizeof(struct ldb_val));
     256         100 :         memcpy(values2, el2->values,
     257         100 :                el2->num_values * sizeof(struct ldb_val));
     258         100 :         TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
     259         100 :         TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp);
     260             : 
     261             :         /*
     262             :            el->n_values may diverge from the number of values in the sorted
     263             :            list when the remove_duplicates flag is used.
     264             :         */
     265         100 :         n_values = el->num_values;
     266         100 :         i = 0;
     267         100 :         j = 0;
     268        3380 :         while (i != n_values && j < el2->num_values) {
     269        3196 :                 int ret = ldb_val_cmp(&values[i], &values2[j]);
     270        3196 :                 if (ret < 0) {
     271         721 :                         i++;
     272        2475 :                 } else if (ret > 0) {
     273        2457 :                         j++;
     274             :                 } else {
     275             :                         /* we have a collision */
     276          18 :                         if (! remove_duplicates) {
     277           4 :                                 TALLOC_FREE(values);
     278           4 :                                 TALLOC_FREE(values2);
     279           4 :                                 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
     280             :                         }
     281             :                         /*
     282             :                            With the remove_duplicates flag we need to find
     283             :                            this in the original list and remove it, which is
     284             :                            inefficient but hopefully rare.
     285             :                         */
     286          23 :                         for (k = 0; k < el->num_values; k++) {
     287          23 :                                 if (ldb_val_equal_exact(&el->values[k],
     288          23 :                                                         &values[i])) {
     289          14 :                                         break;
     290             :                                 }
     291             :                         }
     292          14 :                         el->num_values--;
     293          76 :                         for (; k < el->num_values; k++) {
     294          62 :                                 el->values[k] = el->values[k + 1];
     295             :                         }
     296          14 :                         i++;
     297             :                 }
     298             :         }
     299          96 :         TALLOC_FREE(values);
     300          96 :         TALLOC_FREE(values2);
     301             : 
     302          96 :         return LDB_SUCCESS;
     303             : }
     304             : 
     305             : /*
     306             :   duplicate a ldb_val structure
     307             : */
     308  2156775160 : struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
     309             : {
     310             :         struct ldb_val v2;
     311  2156775160 :         v2.length = v->length;
     312  2156775160 :         if (v->data == NULL) {
     313       93122 :                 v2.data = NULL;
     314       93122 :                 return v2;
     315             :         }
     316             : 
     317             :         /* the +1 is to cope with buggy C library routines like strndup
     318             :            that look one byte beyond */
     319  2156682038 :         v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
     320  2156682038 :         if (!v2.data) {
     321           0 :                 v2.length = 0;
     322           0 :                 return v2;
     323             :         }
     324             : 
     325  2156682038 :         memcpy(v2.data, v->data, v->length);
     326  2156682038 :         ((char *)v2.data)[v->length] = 0;
     327  2156682038 :         return v2;
     328             : }
     329             : 
     330             : /**
     331             :  * Adds new empty element to msg->elements
     332             :  */
     333   169624015 : static int _ldb_msg_add_el(struct ldb_message *msg,
     334             :                            struct ldb_message_element **return_el)
     335             : {
     336             :         struct ldb_message_element *els;
     337             : 
     338             :         /*
     339             :          * TODO: Find out a way to assert on input parameters.
     340             :          * msg and return_el must be valid
     341             :          */
     342             : 
     343   169624015 :         els = talloc_realloc(msg, msg->elements,
     344             :                              struct ldb_message_element, msg->num_elements + 1);
     345   169624015 :         if (!els) {
     346           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     347             :         }
     348             : 
     349   169624015 :         ZERO_STRUCT(els[msg->num_elements]);
     350             : 
     351   169624015 :         msg->elements = els;
     352   169624015 :         msg->num_elements++;
     353             : 
     354   169624015 :         *return_el = &els[msg->num_elements-1];
     355             : 
     356   169624015 :         return LDB_SUCCESS;
     357             : }
     358             : 
     359             : /**
     360             :  * Add an empty element with a given name to a message
     361             :  */
     362   168038712 : int ldb_msg_add_empty(struct ldb_message *msg,
     363             :                       const char *attr_name,
     364             :                       int flags,
     365             :                       struct ldb_message_element **return_el)
     366             : {
     367             :         int ret;
     368             :         struct ldb_message_element *el;
     369             : 
     370   168038712 :         ret = _ldb_msg_add_el(msg, &el);
     371   168038712 :         if (ret != LDB_SUCCESS) {
     372           0 :                 return ret;
     373             :         }
     374             : 
     375             :         /* initialize newly added element */
     376   168038712 :         el->flags = flags;
     377   168038712 :         el->name = talloc_strdup(msg->elements, attr_name);
     378   168038712 :         if (!el->name) {
     379           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     380             :         }
     381             : 
     382   168038712 :         if (return_el) {
     383   167698405 :                 *return_el = el;
     384             :         }
     385             : 
     386   168038712 :         return LDB_SUCCESS;
     387             : }
     388             : 
     389             : /**
     390             :  * Adds an element to a message.
     391             :  *
     392             :  * NOTE: Ownership of ldb_message_element fields
     393             :  *       is NOT transferred. Thus, if *el pointer
     394             :  *       is invalidated for some reason, this will
     395             :  *       corrupt *msg contents also
     396             :  */
     397     1585303 : int ldb_msg_add(struct ldb_message *msg,
     398             :                 const struct ldb_message_element *el,
     399             :                 int flags)
     400             : {
     401             :         int ret;
     402             :         struct ldb_message_element *el_new;
     403             :         /* We have to copy this, just in case *el is a pointer into
     404             :          * what ldb_msg_add_empty() is about to realloc() */
     405     1585303 :         struct ldb_message_element el_copy = *el;
     406             : 
     407     1585303 :         ret = _ldb_msg_add_el(msg, &el_new);
     408     1585303 :         if (ret != LDB_SUCCESS) {
     409           0 :                 return ret;
     410             :         }
     411             : 
     412     1585303 :         el_new->flags      = flags;
     413     1585303 :         el_new->name       = el_copy.name;
     414     1585303 :         el_new->num_values = el_copy.num_values;
     415     1585303 :         el_new->values     = el_copy.values;
     416             : 
     417     1585303 :         return LDB_SUCCESS;
     418             : }
     419             : 
     420             : /*
     421             :  * add a value to a message element
     422             :  */
     423   162218742 : int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
     424             :                               struct ldb_message_element *el,
     425             :                               const struct ldb_val *val)
     426             : {
     427             :         struct ldb_val *vals;
     428             : 
     429   162218742 :         if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
     430             :                 /*
     431             :                  * Another message is using this message element's values array,
     432             :                  * so we don't want to make any modifications to the original
     433             :                  * message, or potentially invalidate its own values by calling
     434             :                  * talloc_realloc(). Make a copy instead.
     435             :                  */
     436          26 :                 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
     437             : 
     438          26 :                 vals = talloc_array(mem_ctx, struct ldb_val,
     439             :                                     el->num_values + 1);
     440          26 :                 if (vals == NULL) {
     441           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     442             :                 }
     443             : 
     444          26 :                 if (el->values != NULL) {
     445          26 :                         memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
     446             :                 }
     447             :         } else {
     448   162218716 :                 vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
     449             :                                       el->num_values + 1);
     450   162218716 :                 if (vals == NULL) {
     451           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     452             :                 }
     453             :         }
     454   162218742 :         el->values = vals;
     455   162218742 :         el->values[el->num_values] = *val;
     456   162218742 :         el->num_values++;
     457             : 
     458   162218742 :         return LDB_SUCCESS;
     459             : }
     460             : 
     461             : /*
     462             :   add a value to a message
     463             : */
     464   162041490 : int ldb_msg_add_value(struct ldb_message *msg,
     465             :                       const char *attr_name,
     466             :                       const struct ldb_val *val,
     467             :                       struct ldb_message_element **return_el)
     468             : {
     469             :         struct ldb_message_element *el;
     470             :         int ret;
     471             : 
     472   162041490 :         el = ldb_msg_find_element(msg, attr_name);
     473   162041490 :         if (!el) {
     474   158235074 :                 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
     475   158235074 :                 if (ret != LDB_SUCCESS) {
     476           0 :                         return ret;
     477             :                 }
     478             :         }
     479             : 
     480   162041490 :         ret = ldb_msg_element_add_value(msg->elements, el, val);
     481   162041490 :         if (ret != LDB_SUCCESS) {
     482           0 :                 return ret;
     483             :         }
     484             : 
     485   162041490 :         if (return_el) {
     486   160330554 :                 *return_el = el;
     487             :         }
     488             : 
     489   162041490 :         return LDB_SUCCESS;
     490             : }
     491             : 
     492             : 
     493             : /*
     494             :   add a value to a message, stealing it into the 'right' place
     495             : */
     496   137206501 : int ldb_msg_add_steal_value(struct ldb_message *msg,
     497             :                             const char *attr_name,
     498             :                             struct ldb_val *val)
     499             : {
     500             :         int ret;
     501             :         struct ldb_message_element *el;
     502             : 
     503   137206501 :         ret = ldb_msg_add_value(msg, attr_name, val, &el);
     504   137206501 :         if (ret == LDB_SUCCESS) {
     505   137206501 :                 talloc_steal(el->values, val->data);
     506             :         }
     507   137206501 :         return ret;
     508             : }
     509             : 
     510             : 
     511             : /*
     512             :   add a string element to a message, specifying flags
     513             : */
     514    22718403 : int ldb_msg_add_string_flags(struct ldb_message *msg,
     515             :                              const char *attr_name, const char *str,
     516             :                              int flags)
     517             : {
     518             :         struct ldb_val val;
     519             :         int ret;
     520    22718403 :         struct ldb_message_element *el = NULL;
     521             : 
     522    22718403 :         val.data = discard_const_p(uint8_t, str);
     523    22718403 :         val.length = strlen(str);
     524             : 
     525    22718403 :         if (val.length == 0) {
     526             :                 /* allow empty strings as non-existent attributes */
     527         268 :                 return LDB_SUCCESS;
     528             :         }
     529             : 
     530    22718135 :         ret = ldb_msg_add_value(msg, attr_name, &val, &el);
     531    22718135 :         if (ret != LDB_SUCCESS) {
     532           0 :                 return ret;
     533             :         }
     534             : 
     535    22718135 :         if (flags != 0) {
     536       62241 :                 el->flags = flags;
     537             :         }
     538             : 
     539    22718135 :         return LDB_SUCCESS;
     540             : }
     541             : 
     542             : /*
     543             :   add a string element to a message
     544             : */
     545    22656162 : int ldb_msg_add_string(struct ldb_message *msg,
     546             :                        const char *attr_name, const char *str)
     547             : {
     548    22656162 :         return ldb_msg_add_string_flags(msg, attr_name, str, 0);
     549             : }
     550             : 
     551             : /*
     552             :   add a string element to a message, stealing it into the 'right' place
     553             : */
     554   123301286 : int ldb_msg_add_steal_string(struct ldb_message *msg,
     555             :                              const char *attr_name, char *str)
     556             : {
     557             :         struct ldb_val val;
     558             : 
     559   123301286 :         val.data = (uint8_t *)str;
     560   123301286 :         val.length = strlen(str);
     561             : 
     562   123301286 :         if (val.length == 0) {
     563             :                 /* allow empty strings as non-existent attributes */
     564           0 :                 return LDB_SUCCESS;
     565             :         }
     566             : 
     567   123301286 :         return ldb_msg_add_steal_value(msg, attr_name, &val);
     568             : }
     569             : 
     570             : /*
     571             :   add a DN element to a message
     572             :   WARNING: this uses the linearized string from the dn, and does not
     573             :   copy the string.
     574             : */
     575        1601 : int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
     576             :                               struct ldb_dn *dn)
     577             : {
     578        1601 :         char *str = ldb_dn_alloc_linearized(msg, dn);
     579             : 
     580        1601 :         if (str == NULL) {
     581             :                 /* we don't want to have unknown DNs added */
     582           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     583             :         }
     584             : 
     585        1601 :         return ldb_msg_add_steal_string(msg, attr_name, str);
     586             : }
     587             : 
     588             : /*
     589             :   add a printf formatted element to a message
     590             : */
     591     7764204 : int ldb_msg_add_fmt(struct ldb_message *msg,
     592             :                     const char *attr_name, const char *fmt, ...)
     593             : {
     594             :         struct ldb_val val;
     595             :         va_list ap;
     596             :         char *str;
     597             : 
     598     7764204 :         va_start(ap, fmt);
     599     7764204 :         str = talloc_vasprintf(msg, fmt, ap);
     600     7764204 :         va_end(ap);
     601             : 
     602     7764204 :         if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
     603             : 
     604     7764204 :         val.data   = (uint8_t *)str;
     605     7764204 :         val.length = strlen(str);
     606             : 
     607     7764204 :         return ldb_msg_add_steal_value(msg, attr_name, &val);
     608             : }
     609             : 
     610      176824 : static int ldb_msg_append_value_impl(struct ldb_message *msg,
     611             :                                      const char *attr_name,
     612             :                                      const struct ldb_val *val,
     613             :                                      int flags,
     614             :                                      struct ldb_message_element **return_el)
     615             : {
     616      176824 :         struct ldb_message_element *el = NULL;
     617             :         int ret;
     618             : 
     619      176824 :         ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
     620      176824 :         if (ret != LDB_SUCCESS) {
     621           0 :                 return ret;
     622             :         }
     623             : 
     624      176824 :         ret = ldb_msg_element_add_value(msg->elements, el, val);
     625      176824 :         if (ret != LDB_SUCCESS) {
     626           0 :                 return ret;
     627             :         }
     628             : 
     629      176824 :         if (return_el != NULL) {
     630        1553 :                 *return_el = el;
     631             :         }
     632             : 
     633      176824 :         return LDB_SUCCESS;
     634             : }
     635             : 
     636             : /*
     637             :   append a value to a message
     638             : */
     639      175271 : int ldb_msg_append_value(struct ldb_message *msg,
     640             :                          const char *attr_name,
     641             :                          const struct ldb_val *val,
     642             :                          int flags)
     643             : {
     644      175271 :         return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
     645             : }
     646             : 
     647             : /*
     648             :   append a value to a message, stealing it into the 'right' place
     649             : */
     650        1553 : int ldb_msg_append_steal_value(struct ldb_message *msg,
     651             :                                const char *attr_name,
     652             :                                struct ldb_val *val,
     653             :                                int flags)
     654             : {
     655             :         int ret;
     656        1553 :         struct ldb_message_element *el = NULL;
     657             : 
     658        1553 :         ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
     659        1553 :         if (ret == LDB_SUCCESS) {
     660        1553 :                 talloc_steal(el->values, val->data);
     661             :         }
     662        1553 :         return ret;
     663             : }
     664             : 
     665             : /*
     666             :   append a string element to a message, stealing it into the 'right' place
     667             : */
     668         696 : int ldb_msg_append_steal_string(struct ldb_message *msg,
     669             :                                 const char *attr_name, char *str,
     670             :                                 int flags)
     671             : {
     672             :         struct ldb_val val;
     673             : 
     674         696 :         val.data = (uint8_t *)str;
     675         696 :         val.length = strlen(str);
     676             : 
     677         696 :         if (val.length == 0) {
     678             :                 /* allow empty strings as non-existent attributes */
     679           0 :                 return LDB_SUCCESS;
     680             :         }
     681             : 
     682         696 :         return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
     683             : }
     684             : 
     685             : /*
     686             :   append a string element to a message
     687             : */
     688       45685 : int ldb_msg_append_string(struct ldb_message *msg,
     689             :                           const char *attr_name, const char *str, int flags)
     690             : {
     691             :         struct ldb_val val;
     692             : 
     693       45685 :         val.data = discard_const_p(uint8_t, str);
     694       45685 :         val.length = strlen(str);
     695             : 
     696       45685 :         if (val.length == 0) {
     697             :                 /* allow empty strings as non-existent attributes */
     698           0 :                 return LDB_SUCCESS;
     699             :         }
     700             : 
     701       45685 :         return ldb_msg_append_value(msg, attr_name, &val, flags);
     702             : }
     703             : 
     704             : /*
     705             :   append a DN element to a message
     706             :   WARNING: this uses the linearized string from the dn, and does not
     707             :   copy the string.
     708             : */
     709           0 : int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
     710             :                                  struct ldb_dn *dn, int flags)
     711             : {
     712           0 :         char *str = ldb_dn_alloc_linearized(msg, dn);
     713             : 
     714           0 :         if (str == NULL) {
     715             :                 /* we don't want to have unknown DNs added */
     716           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     717             :         }
     718             : 
     719           0 :         return ldb_msg_append_steal_string(msg, attr_name, str, flags);
     720             : }
     721             : 
     722             : /*
     723             :   append a printf formatted element to a message
     724             : */
     725         857 : int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
     726             :                        const char *attr_name, const char *fmt, ...)
     727             : {
     728             :         struct ldb_val val;
     729             :         va_list ap;
     730         857 :         char *str = NULL;
     731             : 
     732         857 :         va_start(ap, fmt);
     733         857 :         str = talloc_vasprintf(msg, fmt, ap);
     734         857 :         va_end(ap);
     735             : 
     736         857 :         if (str == NULL) {
     737           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     738             :         }
     739             : 
     740         857 :         val.data   = (uint8_t *)str;
     741         857 :         val.length = strlen(str);
     742             : 
     743         857 :         return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
     744             : }
     745             : 
     746             : /*
     747             :   compare two ldb_message_element structures
     748             :   assumes case sensitive comparison
     749             : */
     750    13659694 : int ldb_msg_element_compare(struct ldb_message_element *el1,
     751             :                             struct ldb_message_element *el2)
     752             : {
     753             :         unsigned int i;
     754             : 
     755    13659694 :         if (el1->num_values != el2->num_values) {
     756          95 :                 return el1->num_values - el2->num_values;
     757             :         }
     758             : 
     759    30210159 :         for (i=0;i<el1->num_values;i++) {
     760    16605012 :                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
     761       54452 :                         return -1;
     762             :                 }
     763             :         }
     764             : 
     765    13605147 :         return 0;
     766             : }
     767             : 
     768             : /*
     769             :   compare two ldb_message_element structures.
     770             :   Different ordering is considered a mismatch
     771             : */
     772     8799920 : bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
     773             :                                    const struct ldb_message_element *el2)
     774             : {
     775             :         unsigned i;
     776     8799920 :         if (el1->num_values != el2->num_values) {
     777      825927 :                 return false;
     778             :         }
     779    12133945 :         for (i=0;i<el1->num_values;i++) {
     780     8440142 :                 if (ldb_val_equal_exact(&el1->values[i],
     781     8440142 :                                         &el2->values[i]) != 1) {
     782     4280190 :                         return false;
     783             :                 }
     784             :         }
     785     3693803 :         return true;
     786             : }
     787             : 
     788             : /*
     789             :   compare two ldb_message_element structures
     790             :   comparing by element name
     791             : */
     792   167379913 : int ldb_msg_element_compare_name(struct ldb_message_element *el1,
     793             :                                  struct ldb_message_element *el2)
     794             : {
     795   167379913 :         return ldb_attr_cmp(el1->name, el2->name);
     796             : }
     797             : 
     798     4571303 : void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
     799             : {
     800     4571303 :         el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
     801     4571303 : }
     802             : 
     803   151454545 : bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
     804             : {
     805   151454545 :         return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
     806             : }
     807             : 
     808     1306578 : void ldb_msg_remove_inaccessible(struct ldb_message *msg)
     809             : {
     810             :         unsigned i;
     811     1306578 :         unsigned num_del = 0;
     812             : 
     813     9261683 :         for (i = 0; i < msg->num_elements; ++i) {
     814     7955105 :                 if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
     815     4566651 :                         ++num_del;
     816     3388454 :                 } else if (num_del) {
     817     2473590 :                         msg->elements[i - num_del] = msg->elements[i];
     818             :                 }
     819             :         }
     820             : 
     821     1306578 :         msg->num_elements -= num_del;
     822     1306578 : }
     823             : 
     824             : /*
     825             :   convenience functions to return common types from a message
     826             :   these return the first value if the attribute is multi-valued
     827             : */
     828  2296815226 : const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
     829             :                                            const char *attr_name)
     830             : {
     831  2296815226 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
     832  2296815226 :         if (!el || el->num_values == 0) {
     833  1020711502 :                 return NULL;
     834             :         }
     835  1276103724 :         return &el->values[0];
     836             : }
     837             : 
     838   100858505 : int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
     839             :                              const char *attr_name,
     840             :                              int default_value)
     841             : {
     842   100858505 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     843             :         char buf[sizeof("-2147483648")];
     844   100858505 :         char *end = NULL;
     845             :         int ret;
     846             : 
     847   100858505 :         if (!v || !v->data) {
     848     1341518 :                 return default_value;
     849             :         }
     850             : 
     851    99516987 :         ZERO_STRUCT(buf);
     852    99516987 :         if (v->length >= sizeof(buf)) {
     853          66 :                 return default_value;
     854             :         }
     855             : 
     856    99516921 :         memcpy(buf, v->data, v->length);
     857    99516921 :         errno = 0;
     858    99516921 :         ret = (int) strtoll(buf, &end, 10);
     859    99516921 :         if (errno != 0) {
     860           0 :                 return default_value;
     861             :         }
     862    99516921 :         if (end && end[0] != '\0') {
     863           0 :                 return default_value;
     864             :         }
     865    99516921 :         return ret;
     866             : }
     867             : 
     868   411380400 : unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
     869             :                                        const char *attr_name,
     870             :                                        unsigned int default_value)
     871             : {
     872   411380400 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     873             :         char buf[sizeof("-2147483648")];
     874   411380400 :         char *end = NULL;
     875             :         unsigned int ret;
     876             : 
     877   411380400 :         if (!v || !v->data) {
     878   204774206 :                 return default_value;
     879             :         }
     880             : 
     881   206606194 :         ZERO_STRUCT(buf);
     882   206606194 :         if (v->length >= sizeof(buf)) {
     883          39 :                 return default_value;
     884             :         }
     885             : 
     886   206606155 :         memcpy(buf, v->data, v->length);
     887   206606155 :         errno = 0;
     888   206606155 :         ret = (unsigned int) strtoll(buf, &end, 10);
     889   206606155 :         if (errno != 0) {
     890           0 :                 errno = 0;
     891           0 :                 ret = (unsigned int) strtoull(buf, &end, 10);
     892           0 :                 if (errno != 0) {
     893           0 :                         return default_value;
     894             :                 }
     895             :         }
     896   206606155 :         if (end && end[0] != '\0') {
     897          39 :                 return default_value;
     898             :         }
     899   206606116 :         return ret;
     900             : }
     901             : 
     902     1826992 : int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
     903             :                                    const char *attr_name,
     904             :                                    int64_t default_value)
     905             : {
     906     1826992 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     907             :         char buf[sizeof("-9223372036854775808")];
     908     1826992 :         char *end = NULL;
     909             :         int64_t ret;
     910             : 
     911     1826992 :         if (!v || !v->data) {
     912      396639 :                 return default_value;
     913             :         }
     914             : 
     915     1430353 :         ZERO_STRUCT(buf);
     916     1430353 :         if (v->length >= sizeof(buf)) {
     917           0 :                 return default_value;
     918             :         }
     919             : 
     920     1430353 :         memcpy(buf, v->data, v->length);
     921     1430353 :         errno = 0;
     922     1430353 :         ret = (int64_t) strtoll(buf, &end, 10);
     923     1430353 :         if (errno != 0) {
     924           0 :                 return default_value;
     925             :         }
     926     1430353 :         if (end && end[0] != '\0') {
     927           0 :                 return default_value;
     928             :         }
     929     1430353 :         return ret;
     930             : }
     931             : 
     932   161766270 : uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
     933             :                                      const char *attr_name,
     934             :                                      uint64_t default_value)
     935             : {
     936   161766270 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     937             :         char buf[sizeof("-9223372036854775808")];
     938   161766270 :         char *end = NULL;
     939             :         uint64_t ret;
     940             : 
     941   161766270 :         if (!v || !v->data) {
     942    79972670 :                 return default_value;
     943             :         }
     944             : 
     945    81793600 :         ZERO_STRUCT(buf);
     946    81793600 :         if (v->length >= sizeof(buf)) {
     947           0 :                 return default_value;
     948             :         }
     949             : 
     950    81793600 :         memcpy(buf, v->data, v->length);
     951    81793600 :         errno = 0;
     952    81793600 :         ret = (uint64_t) strtoll(buf, &end, 10);
     953    81793600 :         if (errno != 0) {
     954           0 :                 errno = 0;
     955           0 :                 ret = (uint64_t) strtoull(buf, &end, 10);
     956           0 :                 if (errno != 0) {
     957           0 :                         return default_value;
     958             :                 }
     959             :         }
     960    81793600 :         if (end && end[0] != '\0') {
     961           0 :                 return default_value;
     962             :         }
     963    81793600 :         return ret;
     964             : }
     965             : 
     966           0 : double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
     967             :                                    const char *attr_name,
     968             :                                    double default_value)
     969             : {
     970           0 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
     971             :         char *buf;
     972           0 :         char *end = NULL;
     973             :         double ret;
     974             : 
     975           0 :         if (!v || !v->data) {
     976           0 :                 return default_value;
     977             :         }
     978           0 :         buf = talloc_strndup(msg, (const char *)v->data, v->length);
     979           0 :         if (buf == NULL) {
     980           0 :                 return default_value;
     981             :         }
     982             : 
     983           0 :         errno = 0;
     984           0 :         ret = strtod(buf, &end);
     985           0 :         talloc_free(buf);
     986           0 :         if (errno != 0) {
     987           0 :                 return default_value;
     988             :         }
     989           0 :         if (end && end[0] != '\0') {
     990           0 :                 return default_value;
     991             :         }
     992           0 :         return ret;
     993             : }
     994             : 
     995     6696169 : int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
     996             :                               const char *attr_name,
     997             :                               int default_value)
     998             : {
     999     6696169 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    1000     6696169 :         if (!v || !v->data) {
    1001     2646663 :                 return default_value;
    1002             :         }
    1003     4049506 :         if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
    1004       69798 :                 return 0;
    1005             :         }
    1006     3979708 :         if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
    1007     3979708 :                 return 1;
    1008             :         }
    1009           0 :         return default_value;
    1010             : }
    1011             : 
    1012   536180524 : const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
    1013             :                                         const char *attr_name,
    1014             :                                         const char *default_value)
    1015             : {
    1016   536180524 :         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
    1017   536180524 :         if (!v || !v->data) {
    1018   341699627 :                 return default_value;
    1019             :         }
    1020   194480897 :         if (v->data[v->length] != '\0') {
    1021           0 :                 return default_value;
    1022             :         }
    1023   194480897 :         return (const char *)v->data;
    1024             : }
    1025             : 
    1026     4195840 : struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
    1027             :                                        TALLOC_CTX *mem_ctx,
    1028             :                                        const struct ldb_message *msg,
    1029             :                                        const char *attr_name)
    1030             : {
    1031             :         struct ldb_dn *res_dn;
    1032             :         const struct ldb_val *v;
    1033             : 
    1034     4195840 :         v = ldb_msg_find_ldb_val(msg, attr_name);
    1035     4195840 :         if (!v || !v->data) {
    1036      838744 :                 return NULL;
    1037             :         }
    1038     3357096 :         res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
    1039     3357096 :         if ( ! ldb_dn_validate(res_dn)) {
    1040           0 :                 talloc_free(res_dn);
    1041           0 :                 return NULL;
    1042             :         }
    1043     3357096 :         return res_dn;
    1044             : }
    1045             : 
    1046             : /*
    1047             :   sort the elements of a message by name
    1048             : */
    1049     1191413 : void ldb_msg_sort_elements(struct ldb_message *msg)
    1050             : {
    1051     1191413 :         TYPESAFE_QSORT(msg->elements, msg->num_elements,
    1052             :                        ldb_msg_element_compare_name);
    1053     1191413 : }
    1054             : 
    1055     6564365 : static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
    1056             :                                          const struct ldb_message *msg)
    1057             : {
    1058             :         struct ldb_message *msg2;
    1059             :         unsigned int i;
    1060             : 
    1061     6564365 :         msg2 = talloc(mem_ctx, struct ldb_message);
    1062     6564365 :         if (msg2 == NULL) return NULL;
    1063             : 
    1064     6564365 :         *msg2 = *msg;
    1065             : 
    1066     6564365 :         msg2->elements = talloc_array(msg2, struct ldb_message_element,
    1067             :                                       msg2->num_elements);
    1068     6564365 :         if (msg2->elements == NULL) goto failed;
    1069             : 
    1070    69880343 :         for (i=0;i<msg2->num_elements;i++) {
    1071    63315978 :                 msg2->elements[i] = msg->elements[i];
    1072             :         }
    1073             : 
    1074     6564365 :         return msg2;
    1075             : 
    1076           0 : failed:
    1077           0 :         talloc_free(msg2);
    1078           0 :         return NULL;
    1079             : }
    1080             : 
    1081             : /*
    1082             :   shallow copy a message - copying only the elements array so that the caller
    1083             :   can safely add new elements without changing the message
    1084             : */
    1085     5240976 : struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
    1086             :                                          const struct ldb_message *msg)
    1087             : {
    1088             :         struct ldb_message *msg2;
    1089             :         unsigned int i;
    1090             : 
    1091     5240976 :         msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
    1092     5240976 :         if (msg2 == NULL) {
    1093           0 :                 return NULL;
    1094             :         }
    1095             : 
    1096    40779582 :         for (i = 0; i < msg2->num_elements; ++i) {
    1097             :                 /*
    1098             :                  * Mark this message's elements as sharing their values with the
    1099             :                  * original message, so that we don't inadvertently modify or
    1100             :                  * free them. We don't mark the original message element as
    1101             :                  * shared, so the original message element should not be
    1102             :                  * modified or freed while the shallow copy lives.
    1103             :                  */
    1104    35538606 :                 struct ldb_message_element *el = &msg2->elements[i];
    1105    35538606 :                 el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
    1106             :         }
    1107             : 
    1108     5240976 :         return msg2;
    1109             : }
    1110             : 
    1111             : /*
    1112             :   copy a message, allocating new memory for all parts
    1113             : */
    1114     1323389 : struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
    1115             :                                  const struct ldb_message *msg)
    1116             : {
    1117             :         struct ldb_message *msg2;
    1118             :         unsigned int i, j;
    1119             : 
    1120     1323389 :         msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
    1121     1323389 :         if (msg2 == NULL) return NULL;
    1122             : 
    1123     1323389 :         if (msg2->dn != NULL) {
    1124     1323377 :                 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
    1125     1323377 :                 if (msg2->dn == NULL) goto failed;
    1126             :         }
    1127             : 
    1128    29100761 :         for (i=0;i<msg2->num_elements;i++) {
    1129    27777372 :                 struct ldb_message_element *el = &msg2->elements[i];
    1130    27777372 :                 struct ldb_val *values = el->values;
    1131    27777372 :                 el->name = talloc_strdup(msg2->elements, el->name);
    1132    27777372 :                 if (el->name == NULL) goto failed;
    1133    27777372 :                 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
    1134    27777372 :                 if (el->values == NULL) goto failed;
    1135    61385603 :                 for (j=0;j<el->num_values;j++) {
    1136    33608231 :                         el->values[j] = ldb_val_dup(el->values, &values[j]);
    1137    33608231 :                         if (el->values[j].data == NULL && values[j].length != 0) {
    1138           0 :                                 goto failed;
    1139             :                         }
    1140             :                 }
    1141             : 
    1142             :                 /*
    1143             :                  * Since we copied this element's values, we can mark them as
    1144             :                  * not shared.
    1145             :                  */
    1146    27777372 :                 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
    1147             :         }
    1148             : 
    1149     1323389 :         return msg2;
    1150             : 
    1151           0 : failed:
    1152           0 :         talloc_free(msg2);
    1153           0 :         return NULL;
    1154             : }
    1155             : 
    1156             : 
    1157             : /**
    1158             :  * Canonicalize a message, merging elements of the same name
    1159             :  */
    1160           0 : struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
    1161             :                                          const struct ldb_message *msg)
    1162             : {
    1163             :         int ret;
    1164             :         struct ldb_message *msg2;
    1165             : 
    1166             :         /*
    1167             :          * Preserve previous behavior and allocate
    1168             :          * *msg2 into *ldb context
    1169             :          */
    1170           0 :         ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
    1171           0 :         if (ret != LDB_SUCCESS) {
    1172           0 :                 return NULL;
    1173             :         }
    1174             : 
    1175           0 :         return msg2;
    1176             : }
    1177             : 
    1178             : /**
    1179             :  * Canonicalize a message, merging elements of the same name
    1180             :  */
    1181     1191238 : int ldb_msg_normalize(struct ldb_context *ldb,
    1182             :                       TALLOC_CTX *mem_ctx,
    1183             :                       const struct ldb_message *msg,
    1184             :                       struct ldb_message **_msg_out)
    1185             : {
    1186             :         unsigned int i;
    1187             :         struct ldb_message *msg2;
    1188             : 
    1189     1191238 :         msg2 = ldb_msg_copy(mem_ctx, msg);
    1190     1191238 :         if (msg2 == NULL) {
    1191           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1192             :         }
    1193             : 
    1194     1191238 :         ldb_msg_sort_elements(msg2);
    1195             : 
    1196    26697355 :         for (i=1; i < msg2->num_elements; i++) {
    1197    25506117 :                 struct ldb_message_element *el1 = &msg2->elements[i-1];
    1198    25506117 :                 struct ldb_message_element *el2 = &msg2->elements[i];
    1199             : 
    1200    25506117 :                 if (ldb_msg_element_compare_name(el1, el2) == 0) {
    1201        5367 :                         el1->values = talloc_realloc(msg2->elements,
    1202             :                                                      el1->values, struct ldb_val,
    1203             :                                                      el1->num_values + el2->num_values);
    1204        5367 :                         if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
    1205           0 :                                 talloc_free(msg2);
    1206           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
    1207             :                         }
    1208       10480 :                         memcpy(el1->values + el1->num_values,
    1209        5367 :                                el2->values,
    1210        5367 :                                sizeof(struct ldb_val) * el2->num_values);
    1211        5367 :                         el1->num_values += el2->num_values;
    1212        5367 :                         talloc_free(discard_const_p(char, el2->name));
    1213        5367 :                         if ((i+1) < msg2->num_elements) {
    1214           0 :                                 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
    1215           0 :                                         (msg2->num_elements - (i+1)));
    1216             :                         }
    1217        5367 :                         msg2->num_elements--;
    1218        5367 :                         i--;
    1219             :                 }
    1220             :         }
    1221             : 
    1222     1191238 :         *_msg_out = msg2;
    1223     1191238 :         return LDB_SUCCESS;
    1224             : }
    1225             : 
    1226             : 
    1227             : /**
    1228             :  * return a ldb_message representing the differences between msg1 and msg2.
    1229             :  * If you then use this in a ldb_modify() call,
    1230             :  * it can be used to save edits to a message
    1231             :  */
    1232           0 : struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
    1233             :                                  struct ldb_message *msg1,
    1234             :                                  struct ldb_message *msg2)
    1235             : {
    1236             :         int ldb_ret;
    1237             :         struct ldb_message *mod;
    1238             : 
    1239           0 :         ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
    1240           0 :         if (ldb_ret != LDB_SUCCESS) {
    1241           0 :                 return NULL;
    1242             :         }
    1243             : 
    1244           0 :         return mod;
    1245             : }
    1246             : 
    1247             : /**
    1248             :  * return a ldb_message representing the differences between msg1 and msg2.
    1249             :  * If you then use this in a ldb_modify() call it can be used to save edits to a message
    1250             :  *
    1251             :  * Result message is constructed as follows:
    1252             :  * - LDB_FLAG_MOD_ADD     - elements found only in msg2
    1253             :  * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
    1254             :  *                          Value for msg2 element is used
    1255             :  * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
    1256             :  *
    1257             :  * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
    1258             :  */
    1259       64924 : int ldb_msg_difference(struct ldb_context *ldb,
    1260             :                        TALLOC_CTX *mem_ctx,
    1261             :                        struct ldb_message *msg1,
    1262             :                        struct ldb_message *msg2,
    1263             :                        struct ldb_message **_msg_out)
    1264             : {
    1265             :         int ldb_res;
    1266             :         unsigned int i;
    1267             :         struct ldb_message *mod;
    1268             :         struct ldb_message_element *el;
    1269             :         TALLOC_CTX *temp_ctx;
    1270             : 
    1271       64924 :         temp_ctx = talloc_new(mem_ctx);
    1272       64924 :         if (!temp_ctx) {
    1273           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1274             :         }
    1275             : 
    1276       64924 :         mod = ldb_msg_new(temp_ctx);
    1277       64924 :         if (mod == NULL) {
    1278           0 :                 goto failed;
    1279             :         }
    1280             : 
    1281       64924 :         mod->dn = msg1->dn;
    1282       64924 :         mod->num_elements = 0;
    1283       64924 :         mod->elements = NULL;
    1284             : 
    1285             :         /*
    1286             :          * Canonicalize *msg2 so we have no repeated elements
    1287             :          * Resulting message is allocated in *mod's mem context,
    1288             :          * as we are going to move some elements from *msg2 to
    1289             :          * *mod object later
    1290             :          */
    1291       64924 :         ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
    1292       64924 :         if (ldb_res != LDB_SUCCESS) {
    1293           0 :                 goto failed;
    1294             :         }
    1295             : 
    1296             :         /* look in msg2 to find elements that need to be added or modified */
    1297    13719074 :         for (i=0;i<msg2->num_elements;i++) {
    1298    13654150 :                 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
    1299             : 
    1300    13654150 :                 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
    1301    13598415 :                         continue;
    1302             :                 }
    1303             : 
    1304      111324 :                 ldb_res = ldb_msg_add(mod,
    1305       55735 :                                       &msg2->elements[i],
    1306             :                                       el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
    1307       55735 :                 if (ldb_res != LDB_SUCCESS) {
    1308           0 :                         goto failed;
    1309             :                 }
    1310             :         }
    1311             : 
    1312             :         /* look in msg1 to find elements that need to be deleted */
    1313    13718448 :         for (i=0;i<msg1->num_elements;i++) {
    1314    13653524 :                 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
    1315    13653524 :                 if (el == NULL) {
    1316         575 :                         ldb_res = ldb_msg_add_empty(mod,
    1317         575 :                                                     msg1->elements[i].name,
    1318             :                                                     LDB_FLAG_MOD_DELETE, NULL);
    1319         575 :                         if (ldb_res != LDB_SUCCESS) {
    1320           0 :                                 goto failed;
    1321             :                         }
    1322             :                 }
    1323             :         }
    1324             : 
    1325             :         /* steal resulting message into supplied context */
    1326       64924 :         talloc_steal(mem_ctx, mod);
    1327       64924 :         *_msg_out = mod;
    1328             : 
    1329       64924 :         talloc_free(temp_ctx);
    1330       64924 :         return LDB_SUCCESS;
    1331             : 
    1332           0 : failed:
    1333           0 :         talloc_free(temp_ctx);
    1334           0 :         return LDB_ERR_OPERATIONS_ERROR;
    1335             : }
    1336             : 
    1337             : 
    1338      928460 : int ldb_msg_sanity_check(struct ldb_context *ldb,
    1339             :                          const struct ldb_message *msg)
    1340             : {
    1341             :         unsigned int i, j;
    1342             : 
    1343             :         /* basic check on DN */
    1344      928460 :         if (msg->dn == NULL) {
    1345           0 :                 ldb_set_errstring(ldb, "ldb message lacks a DN!");
    1346           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
    1347             :         }
    1348             : 
    1349             :         /* basic syntax checks */
    1350     5204319 :         for (i = 0; i < msg->num_elements; i++) {
    1351    10075251 :                 for (j = 0; j < msg->elements[i].num_values; j++) {
    1352     5799392 :                         if (msg->elements[i].values[j].length == 0) {
    1353             :                                 /* an attribute cannot be empty */
    1354           4 :                                 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
    1355           2 :                                                             msg->elements[i].name,
    1356           0 :                                                             ldb_dn_get_linearized(msg->dn));
    1357           2 :                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1358             :                         }
    1359             :                 }
    1360             :         }
    1361             : 
    1362      928458 :         return LDB_SUCCESS;
    1363             : }
    1364             : 
    1365             : 
    1366             : 
    1367             : 
    1368             : /*
    1369             :   copy an attribute list. This only copies the array, not the elements
    1370             :   (ie. the elements are left as the same pointers)
    1371             : */
    1372     8027973 : const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
    1373             : {
    1374             :         const char **ret;
    1375             :         unsigned int i;
    1376             : 
    1377    15395399 :         for (i=0;attrs && attrs[i];i++) /* noop */ ;
    1378     8027973 :         ret = talloc_array(mem_ctx, const char *, i+1);
    1379     8027973 :         if (ret == NULL) {
    1380           0 :                 return NULL;
    1381             :         }
    1382   214998474 :         for (i=0;attrs && attrs[i];i++) {
    1383   206970501 :                 ret[i] = attrs[i];
    1384             :         }
    1385     8027973 :         ret[i] = attrs[i];
    1386     8027973 :         return ret;
    1387             : }
    1388             : 
    1389             : 
    1390             : /*
    1391             :   copy an attribute list. This only copies the array, not the elements
    1392             :   (ie. the elements are left as the same pointers).  The new attribute is added to the list.
    1393             : */
    1394     8316826 : const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
    1395             : {
    1396             :         const char **ret;
    1397             :         unsigned int i;
    1398     8316826 :         bool found = false;
    1399             : 
    1400   191557143 :         for (i=0;attrs && attrs[i];i++) {
    1401   183240317 :                 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
    1402     5773221 :                         found = true;
    1403             :                 }
    1404             :         }
    1405     8316826 :         if (found) {
    1406     5144198 :                 return ldb_attr_list_copy(mem_ctx, attrs);
    1407             :         }
    1408     3172628 :         ret = talloc_array(mem_ctx, const char *, i+2);
    1409     3172628 :         if (ret == NULL) {
    1410           0 :                 return NULL;
    1411             :         }
    1412    26338876 :         for (i=0;attrs && attrs[i];i++) {
    1413    23166248 :                 ret[i] = attrs[i];
    1414             :         }
    1415     3172628 :         ret[i] = new_attr;
    1416     3172628 :         ret[i+1] = NULL;
    1417     3172628 :         return ret;
    1418             : }
    1419             : 
    1420             : 
    1421             : /*
    1422             :   return 1 if an attribute is in a list of attributes, or 0 otherwise
    1423             : */
    1424  1446327057 : int ldb_attr_in_list(const char * const *attrs, const char *attr)
    1425             : {
    1426             :         unsigned int i;
    1427  4120819148 :         for (i=0;attrs && attrs[i];i++) {
    1428  2747224118 :                 if (ldb_attr_cmp(attrs[i], attr) == 0) {
    1429    72732027 :                         return 1;
    1430             :                 }
    1431             :         }
    1432  1373595030 :         return 0;
    1433             : }
    1434             : 
    1435             : 
    1436             : /*
    1437             :   rename the specified attribute in a search result
    1438             : */
    1439           3 : int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
    1440             : {
    1441           3 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
    1442           3 :         if (el == NULL) {
    1443           0 :                 return LDB_SUCCESS;
    1444             :         }
    1445           3 :         el->name = talloc_strdup(msg->elements, replace);
    1446           3 :         if (el->name == NULL) {
    1447           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1448             :         }
    1449           3 :         return LDB_SUCCESS;
    1450             : }
    1451             : 
    1452             : 
    1453             : /*
    1454             :   copy the specified attribute in a search result to a new attribute
    1455             : */
    1456           3 : int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
    1457             : {
    1458           3 :         struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
    1459             :         int ret;
    1460             : 
    1461           3 :         if (el == NULL) {
    1462           0 :                 return LDB_SUCCESS;
    1463             :         }
    1464           3 :         ret = ldb_msg_add(msg, el, 0);
    1465           3 :         if (ret != LDB_SUCCESS) {
    1466           0 :                 return ret;
    1467             :         }
    1468           3 :         return ldb_msg_rename_attr(msg, attr, replace);
    1469             : }
    1470             : 
    1471             : /*
    1472             :   remove the specified element in a search result
    1473             : */
    1474    44482052 : void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
    1475             : {
    1476    44482052 :         ptrdiff_t n = (el - msg->elements);
    1477    44482052 :         if (n >= msg->num_elements || n < 0) {
    1478             :                 /* the element is not in the list. the caller is crazy. */
    1479           0 :                 return;
    1480             :         }
    1481    44482052 :         msg->num_elements--;
    1482    44482052 :         if (n != msg->num_elements) {
    1483    21609723 :                 memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
    1484             :         }
    1485             : }
    1486             : 
    1487             : 
    1488             : /*
    1489             :   remove the specified attribute in a search result
    1490             : */
    1491  1788464355 : void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
    1492             : {
    1493             :         struct ldb_message_element *el;
    1494             : 
    1495  3232433123 :         while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
    1496    38046153 :                 ldb_msg_remove_element(msg, el);
    1497             :         }
    1498  1788464355 : }
    1499             : 
    1500             : /* Reallocate elements to drop any excess capacity. */
    1501   119058923 : void ldb_msg_shrink_to_fit(struct ldb_message *msg)
    1502             : {
    1503   119058923 :         if (msg->num_elements > 0) {
    1504   105643239 :                 struct ldb_message_element *elements = talloc_realloc(msg,
    1505             :                                                                       msg->elements,
    1506             :                                                                       struct ldb_message_element,
    1507             :                                                                       msg->num_elements);
    1508   105643239 :                 if (elements != NULL) {
    1509   105643239 :                         msg->elements = elements;
    1510             :                 }
    1511             :         } else {
    1512    13415684 :                 TALLOC_FREE(msg->elements);
    1513             :         }
    1514   119058923 : }
    1515             : 
    1516             : /*
    1517             :   return a LDAP formatted GeneralizedTime string
    1518             : */
    1519     4473923 : char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
    1520             : {
    1521     4473923 :         struct tm *tm = gmtime(&t);
    1522             :         char *ts;
    1523             :         int r;
    1524             : 
    1525     4473923 :         if (!tm) {
    1526           2 :                 return NULL;
    1527             :         }
    1528             : 
    1529             :         /* we now excatly how long this string will be */
    1530     4473921 :         ts = talloc_array(mem_ctx, char, 18);
    1531             : 
    1532             :         /* formatted like: 20040408072012.0Z */
    1533    12510979 :         r = snprintf(ts, 18,
    1534             :                         "%04u%02u%02u%02u%02u%02u.0Z",
    1535     8492450 :                         tm->tm_year+1900, tm->tm_mon+1,
    1536             :                         tm->tm_mday, tm->tm_hour, tm->tm_min,
    1537             :                         tm->tm_sec);
    1538             : 
    1539     4473921 :         if (r != 17) {
    1540           4 :                 talloc_free(ts);
    1541           4 :                 errno = EOVERFLOW;
    1542           4 :                 return NULL;
    1543             :         }
    1544             : 
    1545     4473917 :         return ts;
    1546             : }
    1547             : 
    1548             : /*
    1549             :   convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
    1550             : */
    1551       20032 : time_t ldb_string_to_time(const char *s)
    1552             : {
    1553             :         struct tm tm;
    1554             : 
    1555       20032 :         if (s == NULL) return 0;
    1556             : 
    1557       20006 :         memset(&tm, 0, sizeof(tm));
    1558       20006 :         if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
    1559             :                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1560             :                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1561           0 :                 return 0;
    1562             :         }
    1563       20006 :         tm.tm_year -= 1900;
    1564       20006 :         tm.tm_mon -= 1;
    1565             : 
    1566       20006 :         return timegm(&tm);
    1567             : }
    1568             : 
    1569             : /*
    1570             :   convert a LDAP GeneralizedTime string in ldb_val format to a
    1571             :   time_t.
    1572             : */
    1573     4038098 : int ldb_val_to_time(const struct ldb_val *v, time_t *t)
    1574             : {
    1575     4038098 :         char val[15] = {0};
    1576     4038098 :         struct tm tm = {
    1577             :                 .tm_year = 0,
    1578             :         };
    1579             : 
    1580     4038098 :         if (v == NULL) {
    1581           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1582             :         }
    1583             : 
    1584     4038098 :         if (v->data == NULL) {
    1585           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1586             :         }
    1587             : 
    1588     4038098 :         if (v->length < 16 && v->length != 13) {
    1589           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1590             :         }
    1591             : 
    1592     4038098 :         if (v->data[v->length - 1] != 'Z') {
    1593           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1594             :         }
    1595             : 
    1596     4038098 :         if (v->length == 13) {
    1597         410 :                 memcpy(val, v->data, 12);
    1598             : 
    1599         410 :                 if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
    1600             :                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1601             :                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1602           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1603             :                 }
    1604         410 :                 if (tm.tm_year < 50) {
    1605         410 :                         tm.tm_year += 100;
    1606             :                 }
    1607             :         } else {
    1608             : 
    1609             :                 /*
    1610             :                  * anything between '.' and 'Z' is silently ignored.
    1611             :                  */
    1612     4037688 :                 if (v->data[14] != '.') {
    1613           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1614             :                 }
    1615             : 
    1616     4037688 :                 memcpy(val, v->data, 14);
    1617             : 
    1618     4037688 :                 if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
    1619             :                         &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1620             :                         &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1621           0 :                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1622             :                 }
    1623     4037688 :                 tm.tm_year -= 1900;
    1624             :         }
    1625     4038098 :         tm.tm_mon -= 1;
    1626             : 
    1627     4038098 :         *t = timegm(&tm);
    1628             : 
    1629     4038098 :         return LDB_SUCCESS;
    1630             : }
    1631             : 
    1632             : /*
    1633             :   return a LDAP formatted UTCTime string
    1634             : */
    1635          49 : char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
    1636             : {
    1637          49 :         struct tm *tm = gmtime(&t);
    1638             :         char *ts;
    1639             :         int r;
    1640             : 
    1641          49 :         if (!tm) {
    1642           0 :                 return NULL;
    1643             :         }
    1644             : 
    1645             :         /* we now excatly how long this string will be */
    1646          49 :         ts = talloc_array(mem_ctx, char, 14);
    1647             : 
    1648             :         /* formatted like: 20040408072012.0Z => 040408072012Z */
    1649         123 :         r = snprintf(ts, 14,
    1650             :                         "%02u%02u%02u%02u%02u%02uZ",
    1651          86 :                         (tm->tm_year+1900)%100, tm->tm_mon+1,
    1652             :                         tm->tm_mday, tm->tm_hour, tm->tm_min,
    1653             :                         tm->tm_sec);
    1654             : 
    1655          49 :         if (r != 13) {
    1656           0 :                 talloc_free(ts);
    1657           0 :                 return NULL;
    1658             :         }
    1659             : 
    1660          49 :         return ts;
    1661             : }
    1662             : 
    1663             : /*
    1664             :   convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
    1665             : */
    1666           0 : time_t ldb_string_utc_to_time(const char *s)
    1667             : {
    1668             :         struct tm tm;
    1669             : 
    1670           0 :         if (s == NULL) return 0;
    1671             : 
    1672           0 :         memset(&tm, 0, sizeof(tm));
    1673           0 :         if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
    1674             :                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
    1675             :                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
    1676           0 :                 return 0;
    1677             :         }
    1678           0 :         if (tm.tm_year < 50) {
    1679           0 :                 tm.tm_year += 100;
    1680             :         }
    1681           0 :         tm.tm_mon -= 1;
    1682             : 
    1683           0 :         return timegm(&tm);
    1684             : }
    1685             : 
    1686             : 
    1687             : /*
    1688             :   dump a set of results to a file. Useful from within gdb
    1689             : */
    1690           0 : void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
    1691             : {
    1692             :         unsigned int i;
    1693             : 
    1694           0 :         for (i = 0; i < result->count; i++) {
    1695             :                 struct ldb_ldif ldif;
    1696           0 :                 fprintf(f, "# record %d\n", i+1);
    1697           0 :                 ldif.changetype = LDB_CHANGETYPE_NONE;
    1698           0 :                 ldif.msg = result->msgs[i];
    1699           0 :                 ldb_ldif_write_file(ldb, f, &ldif);
    1700             :         }
    1701           0 : }
    1702             : 
    1703             : /*
    1704             :   checks for a string attribute. Returns "1" on match and otherwise "0".
    1705             : */
    1706     2511232 : int ldb_msg_check_string_attribute(const struct ldb_message *msg,
    1707             :                                    const char *name, const char *value)
    1708             : {
    1709             :         struct ldb_message_element *el;
    1710             :         struct ldb_val val;
    1711             : 
    1712     2511232 :         el = ldb_msg_find_element(msg, name);
    1713     2511232 :         if (el == NULL) {
    1714     1300544 :                 return 0;
    1715             :         }
    1716             : 
    1717     1210688 :         val.data = discard_const_p(uint8_t, value);
    1718     1210688 :         val.length = strlen(value);
    1719             : 
    1720     1210688 :         if (ldb_msg_find_val(el, &val)) {
    1721     1209958 :                 return 1;
    1722             :         }
    1723             : 
    1724         730 :         return 0;
    1725             : }
    1726             : 
    1727             : 
    1728             : /*
    1729             :   compare a ldb_val to a string
    1730             : */
    1731     2789388 : int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
    1732             : {
    1733     2789388 :         size_t len = strlen(str);
    1734     2789388 :         if (len != v->length) {
    1735           0 :                 return len - v->length;
    1736             :         }
    1737     2789388 :         return strncmp((const char *)v->data, str, len);
    1738             : }

Generated by: LCOV version 1.13