summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/common/ldb_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb/common/ldb_msg.c')
-rw-r--r--source4/lib/ldb/common/ldb_msg.c1187
1 files changed, 0 insertions, 1187 deletions
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c
deleted file mode 100644
index 28c414e6b2..0000000000
--- a/source4/lib/ldb/common/ldb_msg.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2004
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
- * Name: ldb
- *
- * Component: ldb message component utility functions
- *
- * Description: functions for manipulating ldb_message structures
- *
- * Author: Andrew Tridgell
- */
-
-#include "ldb_private.h"
-
-/*
- create a new ldb_message in a given memory context (NULL for top level)
-*/
-struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
-{
- return talloc_zero(mem_ctx, struct ldb_message);
-}
-
-/*
- find an element in a message by attribute name
-*/
-struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
- const char *attr_name)
-{
- unsigned int i;
- for (i=0;i<msg->num_elements;i++) {
- if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
- return &msg->elements[i];
- }
- }
- return NULL;
-}
-
-/*
- see if two ldb_val structures contain exactly the same data
- return 1 for a match, 0 for a mis-match
-*/
-int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
-{
- if (v1->length != v2->length) return 0;
- if (v1->data == v2->data) return 1;
- if (v1->length == 0) return 1;
-
- if (memcmp(v1->data, v2->data, v1->length) == 0) {
- return 1;
- }
-
- return 0;
-}
-
-/*
- find a value in an element
- assumes case sensitive comparison
-*/
-struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
- struct ldb_val *val)
-{
- unsigned int i;
- for (i=0;i<el->num_values;i++) {
- if (ldb_val_equal_exact(val, &el->values[i])) {
- return &el->values[i];
- }
- }
- return NULL;
-}
-
-/*
- duplicate a ldb_val structure
-*/
-struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
-{
- struct ldb_val v2;
- v2.length = v->length;
- if (v->data == NULL) {
- v2.data = NULL;
- return v2;
- }
-
- /* the +1 is to cope with buggy C library routines like strndup
- that look one byte beyond */
- v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
- if (!v2.data) {
- v2.length = 0;
- return v2;
- }
-
- memcpy(v2.data, v->data, v->length);
- ((char *)v2.data)[v->length] = 0;
- return v2;
-}
-
-/**
- * Adds new empty element to msg->elements
- */
-static int _ldb_msg_add_el(struct ldb_message *msg,
- struct ldb_message_element **return_el)
-{
- struct ldb_message_element *els;
-
- /*
- * TODO: Find out a way to assert on input parameters.
- * msg and return_el must be valid
- */
-
- els = talloc_realloc(msg, msg->elements,
- struct ldb_message_element, msg->num_elements + 1);
- if (!els) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ZERO_STRUCT(els[msg->num_elements]);
-
- msg->elements = els;
- msg->num_elements++;
-
- *return_el = &els[msg->num_elements-1];
-
- return LDB_SUCCESS;
-}
-
-/**
- * Add an empty element with a given name to a message
- */
-int ldb_msg_add_empty(struct ldb_message *msg,
- const char *attr_name,
- int flags,
- struct ldb_message_element **return_el)
-{
- int ret;
- struct ldb_message_element *el;
-
- ret = _ldb_msg_add_el(msg, &el);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- /* initialize newly added element */
- el->flags = flags;
- el->name = talloc_strdup(msg->elements, attr_name);
- if (!el->name) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if (return_el) {
- *return_el = el;
- }
-
- return LDB_SUCCESS;
-}
-
-/**
- * Adds an element to a message.
- *
- * NOTE: Ownership of ldb_message_element fields
- * is NOT transferred. Thus, if *el pointer
- * is invalidated for some reason, this will
- * corrupt *msg contents also
- */
-int ldb_msg_add(struct ldb_message *msg,
- const struct ldb_message_element *el,
- int flags)
-{
- int ret;
- struct ldb_message_element *el_new;
- /* We have to copy this, just in case *el is a pointer into
- * what ldb_msg_add_empty() is about to realloc() */
- struct ldb_message_element el_copy = *el;
-
- ret = _ldb_msg_add_el(msg, &el_new);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- el_new->flags = flags;
- el_new->name = el_copy.name;
- el_new->num_values = el_copy.num_values;
- el_new->values = el_copy.values;
-
- return LDB_SUCCESS;
-}
-
-/*
- add a value to a message
-*/
-int ldb_msg_add_value(struct ldb_message *msg,
- const char *attr_name,
- const struct ldb_val *val,
- struct ldb_message_element **return_el)
-{
- struct ldb_message_element *el;
- struct ldb_val *vals;
- int ret;
-
- el = ldb_msg_find_element(msg, attr_name);
- if (!el) {
- ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
- el->num_values+1);
- if (!vals) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- el->values = vals;
- el->values[el->num_values] = *val;
- el->num_values++;
-
- if (return_el) {
- *return_el = el;
- }
-
- return LDB_SUCCESS;
-}
-
-
-/*
- add a value to a message, stealing it into the 'right' place
-*/
-int ldb_msg_add_steal_value(struct ldb_message *msg,
- const char *attr_name,
- struct ldb_val *val)
-{
- int ret;
- struct ldb_message_element *el;
-
- ret = ldb_msg_add_value(msg, attr_name, val, &el);
- if (ret == LDB_SUCCESS) {
- talloc_steal(el->values, val->data);
- }
- return ret;
-}
-
-
-/*
- add a string element to a message
-*/
-int ldb_msg_add_string(struct ldb_message *msg,
- const char *attr_name, const char *str)
-{
- struct ldb_val val;
-
- val.data = discard_const_p(uint8_t, str);
- val.length = strlen(str);
-
- if (val.length == 0) {
- /* allow empty strings as non-existent attributes */
- return LDB_SUCCESS;
- }
-
- return ldb_msg_add_value(msg, attr_name, &val, NULL);
-}
-
-/*
- add a string element to a message, stealing it into the 'right' place
-*/
-int ldb_msg_add_steal_string(struct ldb_message *msg,
- const char *attr_name, char *str)
-{
- struct ldb_val val;
-
- val.data = (uint8_t *)str;
- val.length = strlen(str);
-
- if (val.length == 0) {
- /* allow empty strings as non-existent attributes */
- return LDB_SUCCESS;
- }
-
- return ldb_msg_add_steal_value(msg, attr_name, &val);
-}
-
-/*
- add a DN element to a message
- WARNING: this uses the linearized string from the dn, and does not
- copy the string.
-*/
-int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
- struct ldb_dn *dn)
-{
- char *str = ldb_dn_alloc_linearized(msg, dn);
-
- if (str == NULL) {
- /* we don't want to have unknown DNs added */
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- return ldb_msg_add_steal_string(msg, attr_name, str);
-}
-
-/*
- add a printf formatted element to a message
-*/
-int ldb_msg_add_fmt(struct ldb_message *msg,
- const char *attr_name, const char *fmt, ...)
-{
- struct ldb_val val;
- va_list ap;
- char *str;
-
- va_start(ap, fmt);
- str = talloc_vasprintf(msg, fmt, ap);
- va_end(ap);
-
- if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
-
- val.data = (uint8_t *)str;
- val.length = strlen(str);
-
- return ldb_msg_add_steal_value(msg, attr_name, &val);
-}
-
-/*
- compare two ldb_message_element structures
- assumes case sensitive comparison
-*/
-int ldb_msg_element_compare(struct ldb_message_element *el1,
- struct ldb_message_element *el2)
-{
- unsigned int i;
-
- if (el1->num_values != el2->num_values) {
- return el1->num_values - el2->num_values;
- }
-
- for (i=0;i<el1->num_values;i++) {
- if (!ldb_msg_find_val(el2, &el1->values[i])) {
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- compare two ldb_message_element structures
- comparing by element name
-*/
-int ldb_msg_element_compare_name(struct ldb_message_element *el1,
- struct ldb_message_element *el2)
-{
- return ldb_attr_cmp(el1->name, el2->name);
-}
-
-/*
- convenience functions to return common types from a message
- these return the first value if the attribute is multi-valued
-*/
-const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
- const char *attr_name)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
- if (!el || el->num_values == 0) {
- return NULL;
- }
- return &el->values[0];
-}
-
-int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
- const char *attr_name,
- int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- char buf[sizeof("-2147483648")];
- char *end = NULL;
- int ret;
-
- if (!v || !v->data) {
- return default_value;
- }
-
- ZERO_STRUCT(buf);
- if (v->length >= sizeof(buf)) {
- return default_value;
- }
-
- memcpy(buf, v->data, v->length);
- errno = 0;
- ret = (int) strtoll(buf, &end, 10);
- if (errno != 0) {
- return default_value;
- }
- if (end && end[0] != '\0') {
- return default_value;
- }
- return ret;
-}
-
-unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
- const char *attr_name,
- unsigned int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- char buf[sizeof("-2147483648")];
- char *end = NULL;
- unsigned int ret;
-
- if (!v || !v->data) {
- return default_value;
- }
-
- ZERO_STRUCT(buf);
- if (v->length >= sizeof(buf)) {
- return default_value;
- }
-
- memcpy(buf, v->data, v->length);
- errno = 0;
- ret = (unsigned int) strtoll(buf, &end, 10);
- if (errno != 0) {
- errno = 0;
- ret = (unsigned int) strtoull(buf, &end, 10);
- if (errno != 0) {
- return default_value;
- }
- }
- if (end && end[0] != '\0') {
- return default_value;
- }
- return ret;
-}
-
-int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
- const char *attr_name,
- int64_t default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- char buf[sizeof("-9223372036854775808")];
- char *end = NULL;
- int64_t ret;
-
- if (!v || !v->data) {
- return default_value;
- }
-
- ZERO_STRUCT(buf);
- if (v->length >= sizeof(buf)) {
- return default_value;
- }
-
- memcpy(buf, v->data, v->length);
- errno = 0;
- ret = (int64_t) strtoll(buf, &end, 10);
- if (errno != 0) {
- return default_value;
- }
- if (end && end[0] != '\0') {
- return default_value;
- }
- return ret;
-}
-
-uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
- const char *attr_name,
- uint64_t default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- char buf[sizeof("-9223372036854775808")];
- char *end = NULL;
- uint64_t ret;
-
- if (!v || !v->data) {
- return default_value;
- }
-
- ZERO_STRUCT(buf);
- if (v->length >= sizeof(buf)) {
- return default_value;
- }
-
- memcpy(buf, v->data, v->length);
- errno = 0;
- ret = (uint64_t) strtoll(buf, &end, 10);
- if (errno != 0) {
- errno = 0;
- ret = (uint64_t) strtoull(buf, &end, 10);
- if (errno != 0) {
- return default_value;
- }
- }
- if (end && end[0] != '\0') {
- return default_value;
- }
- return ret;
-}
-
-double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
- const char *attr_name,
- double default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- char *buf;
- char *end = NULL;
- double ret;
-
- if (!v || !v->data) {
- return default_value;
- }
- buf = talloc_strndup(msg, (const char *)v->data, v->length);
- if (buf == NULL) {
- return default_value;
- }
-
- errno = 0;
- ret = strtod(buf, &end);
- talloc_free(buf);
- if (errno != 0) {
- return default_value;
- }
- if (end && end[0] != '\0') {
- return default_value;
- }
- return ret;
-}
-
-int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
- const char *attr_name,
- int default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
- return 0;
- }
- if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
- return 1;
- }
- return default_value;
-}
-
-const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
- const char *attr_name,
- const char *default_value)
-{
- const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return default_value;
- }
- if (v->data[v->length] != '\0') {
- return default_value;
- }
- return (const char *)v->data;
-}
-
-struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
- TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg,
- const char *attr_name)
-{
- struct ldb_dn *res_dn;
- const struct ldb_val *v;
-
- v = ldb_msg_find_ldb_val(msg, attr_name);
- if (!v || !v->data) {
- return NULL;
- }
- res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
- if ( ! ldb_dn_validate(res_dn)) {
- talloc_free(res_dn);
- return NULL;
- }
- return res_dn;
-}
-
-/*
- sort the elements of a message by name
-*/
-void ldb_msg_sort_elements(struct ldb_message *msg)
-{
- TYPESAFE_QSORT(msg->elements, msg->num_elements,
- ldb_msg_element_compare_name);
-}
-
-/*
- shallow copy a message - copying only the elements array so that the caller
- can safely add new elements without changing the message
-*/
-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg)
-{
- struct ldb_message *msg2;
- unsigned int i;
-
- msg2 = talloc(mem_ctx, struct ldb_message);
- if (msg2 == NULL) return NULL;
-
- *msg2 = *msg;
-
- msg2->elements = talloc_array(msg2, struct ldb_message_element,
- msg2->num_elements);
- if (msg2->elements == NULL) goto failed;
-
- for (i=0;i<msg2->num_elements;i++) {
- msg2->elements[i] = msg->elements[i];
- }
-
- return msg2;
-
-failed:
- talloc_free(msg2);
- return NULL;
-}
-
-
-/*
- copy a message, allocating new memory for all parts
-*/
-struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg)
-{
- struct ldb_message *msg2;
- unsigned int i, j;
-
- msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
- if (msg2 == NULL) return NULL;
-
- msg2->dn = ldb_dn_copy(msg2, msg2->dn);
- if (msg2->dn == NULL) goto failed;
-
- for (i=0;i<msg2->num_elements;i++) {
- struct ldb_message_element *el = &msg2->elements[i];
- struct ldb_val *values = el->values;
- el->name = talloc_strdup(msg2->elements, el->name);
- if (el->name == NULL) goto failed;
- el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
- for (j=0;j<el->num_values;j++) {
- el->values[j] = ldb_val_dup(el->values, &values[j]);
- if (el->values[j].data == NULL && values[j].length != 0) {
- goto failed;
- }
- }
- }
-
- return msg2;
-
-failed:
- talloc_free(msg2);
- return NULL;
-}
-
-
-/**
- * Canonicalize a message, merging elements of the same name
- */
-struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
- const struct ldb_message *msg)
-{
- int ret;
- struct ldb_message *msg2;
-
- /*
- * Preserve previous behavior and allocate
- * *msg2 into *ldb context
- */
- ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
- if (ret != LDB_SUCCESS) {
- return NULL;
- }
-
- return msg2;
-}
-
-/**
- * Canonicalize a message, merging elements of the same name
- */
-int ldb_msg_normalize(struct ldb_context *ldb,
- TALLOC_CTX *mem_ctx,
- const struct ldb_message *msg,
- struct ldb_message **_msg_out)
-{
- unsigned int i;
- struct ldb_message *msg2;
-
- msg2 = ldb_msg_copy(mem_ctx, msg);
- if (msg2 == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ldb_msg_sort_elements(msg2);
-
- for (i=1; i < msg2->num_elements; i++) {
- struct ldb_message_element *el1 = &msg2->elements[i-1];
- struct ldb_message_element *el2 = &msg2->elements[i];
-
- if (ldb_msg_element_compare_name(el1, el2) == 0) {
- el1->values = talloc_realloc(msg2->elements,
- el1->values, struct ldb_val,
- el1->num_values + el2->num_values);
- if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
- talloc_free(msg2);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- memcpy(el1->values + el1->num_values,
- el2->values,
- sizeof(struct ldb_val) * el2->num_values);
- el1->num_values += el2->num_values;
- talloc_free(discard_const_p(char, el2->name));
- if ((i+1) < msg2->num_elements) {
- memmove(el2, el2+1, sizeof(struct ldb_message_element) *
- (msg2->num_elements - (i+1)));
- }
- msg2->num_elements--;
- i--;
- }
- }
-
- *_msg_out = msg2;
- return LDB_SUCCESS;
-}
-
-
-/**
- * return a ldb_message representing the differences between msg1 and msg2.
- * If you then use this in a ldb_modify() call,
- * it can be used to save edits to a message
- */
-struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
- struct ldb_message *msg1,
- struct ldb_message *msg2)
-{
- int ldb_ret;
- struct ldb_message *mod;
-
- ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
- if (ldb_ret != LDB_SUCCESS) {
- return NULL;
- }
-
- return mod;
-}
-
-/**
- * return a ldb_message representing the differences between msg1 and msg2.
- * If you then use this in a ldb_modify() call it can be used to save edits to a message
- *
- * Result message is constructed as follows:
- * - LDB_FLAG_MOD_ADD - elements found only in msg2
- * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
- * Value for msg2 element is used
- * - LDB_FLAG_MOD_DELETE - elements found only in msg2
- *
- * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
- */
-int ldb_msg_difference(struct ldb_context *ldb,
- TALLOC_CTX *mem_ctx,
- struct ldb_message *msg1,
- struct ldb_message *msg2,
- struct ldb_message **_msg_out)
-{
- int ldb_res;
- unsigned int i;
- struct ldb_message *mod;
- struct ldb_message_element *el;
- TALLOC_CTX *temp_ctx;
-
- temp_ctx = talloc_new(mem_ctx);
- if (!temp_ctx) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- mod = ldb_msg_new(temp_ctx);
- if (mod == NULL) {
- goto failed;
- }
-
- mod->dn = msg1->dn;
- mod->num_elements = 0;
- mod->elements = NULL;
-
- /*
- * Canonicalize *msg2 so we have no repeated elements
- * Resulting message is allocated in *mod's mem context,
- * as we are going to move some elements from *msg2 to
- * *mod object later
- */
- ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
- if (ldb_res != LDB_SUCCESS) {
- goto failed;
- }
-
- /* look in msg2 to find elements that need to be added or modified */
- for (i=0;i<msg2->num_elements;i++) {
- el = ldb_msg_find_element(msg1, msg2->elements[i].name);
-
- if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
- continue;
- }
-
- ldb_res = ldb_msg_add(mod,
- &msg2->elements[i],
- el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
- if (ldb_res != LDB_SUCCESS) {
- goto failed;
- }
- }
-
- /* look in msg1 to find elements that need to be deleted */
- for (i=0;i<msg1->num_elements;i++) {
- el = ldb_msg_find_element(msg2, msg1->elements[i].name);
- if (el == NULL) {
- ldb_res = ldb_msg_add_empty(mod,
- msg1->elements[i].name,
- LDB_FLAG_MOD_DELETE, NULL);
- if (ldb_res != LDB_SUCCESS) {
- goto failed;
- }
- }
- }
-
- /* steal resulting message into supplied context */
- talloc_steal(mem_ctx, mod);
- *_msg_out = mod;
-
- talloc_free(temp_ctx);
- return LDB_SUCCESS;
-
-failed:
- talloc_free(temp_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
-}
-
-
-int ldb_msg_sanity_check(struct ldb_context *ldb,
- const struct ldb_message *msg)
-{
- unsigned int i, j;
-
- /* basic check on DN */
- if (msg->dn == NULL) {
- ldb_set_errstring(ldb, "ldb message lacks a DN!");
- return LDB_ERR_INVALID_DN_SYNTAX;
- }
-
- /* basic syntax checks */
- for (i = 0; i < msg->num_elements; i++) {
- for (j = 0; j < msg->elements[i].num_values; j++) {
- if (msg->elements[i].values[j].length == 0) {
- /* an attribute cannot be empty */
- ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
- msg->elements[i].name,
- ldb_dn_get_linearized(msg->dn));
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
- }
- }
- }
-
- return LDB_SUCCESS;
-}
-
-
-
-
-/*
- copy an attribute list. This only copies the array, not the elements
- (ie. the elements are left as the same pointers)
-*/
-const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
-{
- const char **ret;
- unsigned int i;
-
- for (i=0;attrs && attrs[i];i++) /* noop */ ;
- ret = talloc_array(mem_ctx, const char *, i+1);
- if (ret == NULL) {
- return NULL;
- }
- for (i=0;attrs && attrs[i];i++) {
- ret[i] = attrs[i];
- }
- ret[i] = attrs[i];
- return ret;
-}
-
-
-/*
- copy an attribute list. This only copies the array, not the elements
- (ie. the elements are left as the same pointers). The new attribute is added to the list.
-*/
-const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
-{
- const char **ret;
- unsigned int i;
- bool found = false;
-
- for (i=0;attrs && attrs[i];i++) {
- if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
- found = true;
- }
- }
- if (found) {
- return ldb_attr_list_copy(mem_ctx, attrs);
- }
- ret = talloc_array(mem_ctx, const char *, i+2);
- if (ret == NULL) {
- return NULL;
- }
- for (i=0;attrs && attrs[i];i++) {
- ret[i] = attrs[i];
- }
- ret[i] = new_attr;
- ret[i+1] = NULL;
- return ret;
-}
-
-
-/*
- return 1 if an attribute is in a list of attributes, or 0 otherwise
-*/
-int ldb_attr_in_list(const char * const *attrs, const char *attr)
-{
- unsigned int i;
- for (i=0;attrs && attrs[i];i++) {
- if (ldb_attr_cmp(attrs[i], attr) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-
-/*
- rename the specified attribute in a search result
-*/
-int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
- if (el == NULL) {
- return LDB_SUCCESS;
- }
- el->name = talloc_strdup(msg->elements, replace);
- if (el->name == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- return LDB_SUCCESS;
-}
-
-
-/*
- copy the specified attribute in a search result to a new attribute
-*/
-int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
-{
- struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
- int ret;
-
- if (el == NULL) {
- return LDB_SUCCESS;
- }
- ret = ldb_msg_add(msg, el, 0);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- return ldb_msg_rename_attr(msg, attr, replace);
-}
-
-/*
- remove the specified element in a search result
-*/
-void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
-{
- ptrdiff_t n = (el - msg->elements);
- if (n >= msg->num_elements) {
- /* should we abort() here? */
- return;
- }
- if (n != msg->num_elements-1) {
- memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
- }
- msg->num_elements--;
-}
-
-
-/*
- remove the specified attribute in a search result
-*/
-void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
-{
- struct ldb_message_element *el;
-
- while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
- ldb_msg_remove_element(msg, el);
- }
-}
-
-/*
- return a LDAP formatted GeneralizedTime string
-*/
-char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
-{
- struct tm *tm = gmtime(&t);
- char *ts;
- int r;
-
- if (!tm) {
- return NULL;
- }
-
- /* we now excatly how long this string will be */
- ts = talloc_array(mem_ctx, char, 18);
-
- /* formatted like: 20040408072012.0Z */
- r = snprintf(ts, 18,
- "%04u%02u%02u%02u%02u%02u.0Z",
- tm->tm_year+1900, tm->tm_mon+1,
- tm->tm_mday, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
-
- if (r != 17) {
- talloc_free(ts);
- return NULL;
- }
-
- return ts;
-}
-
-/*
- convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
-*/
-time_t ldb_string_to_time(const char *s)
-{
- struct tm tm;
-
- if (s == NULL) return 0;
-
- memset(&tm, 0, sizeof(tm));
- if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- return 0;
- }
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- return timegm(&tm);
-}
-
-/*
- convert a LDAP GeneralizedTime string in ldb_val format to a
- time_t.
-*/
-int ldb_val_to_time(const struct ldb_val *v, time_t *t)
-{
- struct tm tm;
-
- if (v == NULL || !v->data || v->length < 17) {
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
- }
-
- memset(&tm, 0, sizeof(tm));
-
- if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
- }
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
-
- *t = timegm(&tm);
-
- return LDB_SUCCESS;
-}
-
-/*
- return a LDAP formatted UTCTime string
-*/
-char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
-{
- struct tm *tm = gmtime(&t);
- char *ts;
- int r;
-
- if (!tm) {
- return NULL;
- }
-
- /* we now excatly how long this string will be */
- ts = talloc_array(mem_ctx, char, 14);
-
- /* formatted like: 20040408072012.0Z => 040408072012Z */
- r = snprintf(ts, 14,
- "%02u%02u%02u%02u%02u%02uZ",
- (tm->tm_year+1900)%100, tm->tm_mon+1,
- tm->tm_mday, tm->tm_hour, tm->tm_min,
- tm->tm_sec);
-
- if (r != 13) {
- talloc_free(ts);
- return NULL;
- }
-
- return ts;
-}
-
-/*
- convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
-*/
-time_t ldb_string_utc_to_time(const char *s)
-{
- struct tm tm;
-
- if (s == NULL) return 0;
-
- memset(&tm, 0, sizeof(tm));
- if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
- return 0;
- }
- if (tm.tm_year < 50) {
- tm.tm_year += 100;
- }
- tm.tm_mon -= 1;
-
- return timegm(&tm);
-}
-
-
-/*
- dump a set of results to a file. Useful from within gdb
-*/
-void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
-{
- unsigned int i;
-
- for (i = 0; i < result->count; i++) {
- struct ldb_ldif ldif;
- fprintf(f, "# record %d\n", i+1);
- ldif.changetype = LDB_CHANGETYPE_NONE;
- ldif.msg = result->msgs[i];
- ldb_ldif_write_file(ldb, f, &ldif);
- }
-}
-
-/*
- checks for a string attribute. Returns "1" on match and otherwise "0".
-*/
-int ldb_msg_check_string_attribute(const struct ldb_message *msg,
- const char *name, const char *value)
-{
- struct ldb_message_element *el;
- struct ldb_val val;
-
- el = ldb_msg_find_element(msg, name);
- if (el == NULL) {
- return 0;
- }
-
- val.data = discard_const_p(uint8_t, value);
- val.length = strlen(value);
-
- if (ldb_msg_find_val(el, &val)) {
- return 1;
- }
-
- return 0;
-}
-