r7937: main file was missing
authorSimo Sorce <idra@samba.org>
Mon, 27 Jun 2005 00:00:50 +0000 (00:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:53 +0000 (13:18 -0500)
(This used to be commit 3898cdb0dc4722a7eb60a61b54ef778dab475aed)

source4/lib/ldb/common/ldb_dn.c [new file with mode: 0644]
source4/lib/ldb/common/ldb_explode_dn.c [deleted file]
source4/lib/ldb/include/ldb_dn.h [moved from source4/lib/ldb/include/ldb_explode_dn.h with 61% similarity]

diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
new file mode 100644 (file)
index 0000000..7ae314e
--- /dev/null
@@ -0,0 +1,471 @@
+/* 
+   ldb database library
+
+   Copyright (C) Simo Sorce 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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+ *  Name: ldb
+ *
+ *  Component: ldb dn explode and utility functions
+ *
+ *  Description: - explode a dn into it's own basic elements
+ *                 and put them in a structure
+ *               - manipulate ldb_dn structures
+ *
+ *  Author: Simo Sorce
+ */
+
+#include "includes.h"
+#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_private.h"
+#include "ldb/include/ldb_dn.h"
+
+
+#define LDB_DN_NULL_RETURN(x) do { if (!x) return NULL; } while(0) 
+
+static char *escape_string(void *mem_ctx, const char *src)
+{
+       const char *p, *s;
+       char *d, *dst;
+
+       LDB_DN_NULL_RETURN(src);
+
+       /* allocate destination string, it will be at most 3 times the source */
+       dst = d = talloc_array(mem_ctx, char, strlen(src) * 3 + 1);
+       LDB_DN_NULL_RETURN(dst);
+
+       p = s = src;
+
+       while (p) {
+               p += strcspn(p, ",=\n+<>#;\\\"");
+               if (*p == '\0') /* no special s found, all ok */
+                       break;
+
+               if (*p) { /* copy part of the string and escape */
+                       memcpy(d, s, p - s);
+                       d += (p - s);
+                       *d++ = '\\';
+                       *d++ = *p++;
+                       s = p;
+               }
+       }
+
+       /* copy the last part (with zero) and return */
+       memcpy(d, s, &src[strlen(src)] - s + 1);
+
+       return dst;
+}
+
+static char *unescape_string(void *mem_ctx, const char *src)
+{
+       unsigned x;
+       char *p, *dst, *end;
+
+       LDB_DN_NULL_RETURN(src);
+
+       dst = p = talloc_strdup(mem_ctx, src);
+       LDB_DN_NULL_RETURN(dst);
+
+       end = &dst[strlen(dst)];
+
+       while (*p) {
+               p += strcspn(p, ",=\n+<>#;\\\"");
+               if (*p == '\0') /* no escapes or specials found, all ok */
+                       return dst;
+
+               if (*p == '\\') {
+                       if (strchr(",=\n+<>#;\\\"", p[1])) {
+                               memmove(p, p + 1, end - (p + 1) + 1);
+                               end--;
+                               p++;
+                               continue;
+                       }
+
+                       if (sscanf(p + 1, "%02x", &x) == 1) {
+                               *p = (unsigned char)x;
+                               memmove(p + 1, p + 3, end - (p + 3) + 1);
+                               end -= 2;
+                               p++;
+                               continue;
+                       }
+               }
+
+               /* a string with not escaped specials is invalid */     
+
+               return NULL;
+       }
+
+       return dst;
+}
+
+static char *seek_to_separator(char *string, const char *separator)
+{
+       char *p;
+
+       p = strchr(string, '=');
+
+       LDB_DN_NULL_RETURN(p);
+
+       p++;
+
+       /* check if there are quotes surrounding the value */
+       p += strspn(p, " \n"); /* skip white spaces after '=' */
+
+       if (*p == '\"') {
+               p++;
+               while (*p != '\"') {
+                       p = strchr(p, '\"');
+                       LDB_DN_NULL_RETURN(p);
+
+                       if (*(p - 1) == '\\')
+                               p++;
+               }
+       }
+
+       p += strcspn(p, separator);
+
+       return p;
+}
+
+static char *ldb_dn_trim_string(char *string, const char *edge)
+{
+       char *s, *p;
+
+       /* seek out edge from start of string */
+       s = string + strspn(string, edge);
+
+       /* backwards skip from end of string */
+       p = &s[strlen(s) - 1];
+       while (p > s && strchr(edge, *p)) {
+               *p = '\0';
+               p--;
+       }
+
+       return s;
+}
+
+static struct ldb_dn_attribute *ldb_dn_explode_attribute(void *mem_ctx, char *raw_attribute)
+{
+       struct ldb_dn_attribute *at;
+       char *p;
+
+       at = talloc(mem_ctx, struct ldb_dn_attribute);
+       LDB_DN_NULL_RETURN(at);
+
+       p = strchr(raw_attribute, '=');
+
+       LDB_DN_NULL_RETURN(p);
+
+       *p = '\0';
+
+       at->name = talloc_strdup(at, ldb_dn_trim_string(raw_attribute, " \n"));
+       LDB_DN_NULL_RETURN(at->name);
+
+       p++;
+
+       p = ldb_dn_trim_string(p, " \n");
+
+       if (*p == '\"') { /* quotes at start means there must be quotes at the end */
+               if (p[strlen(p) - 1] != '\"') /* malformed value */
+                       return NULL;
+       
+               p++;
+               p[strlen(p) - 1] = '\0';
+               at->value = talloc_strdup(at, p);
+
+               return at;
+       }
+       /* no quotes means we must unescape the string */
+       at->value = unescape_string(at, p);
+       LDB_DN_NULL_RETURN(at->value);
+
+       return at;
+}
+
+static struct ldb_dn_component *explode_component(void *mem_ctx, char *raw_component)
+{
+       struct ldb_dn_component *dc;
+       char *p;
+
+       dc = talloc(mem_ctx, struct ldb_dn_component);
+       LDB_DN_NULL_RETURN(dc);
+
+       dc->attr_num = 0;
+       dc->attributes = NULL;
+
+       p = raw_component;
+
+       /* get the components */
+       do {
+               char *t;
+
+               /* terminate the current attribute and return pointer to the next one */
+               t = seek_to_separator(p, "+");
+               LDB_DN_NULL_RETURN(t);
+
+               if (*t) { /* here there is a separator */
+                       *t = '\0'; /*terminate */
+                       t++; /* a separtor means there's another attribute that follows */
+               }
+
+               /* allocate attributes pointer */
+               dc->attributes = talloc_realloc(dc, dc->attributes,
+                                               struct ldb_dn_attribute *,
+                                               dc->attr_num + 1);
+               LDB_DN_NULL_RETURN(dc->attributes);
+
+               /* store the exploded attirbute in the main structure */
+               dc->attributes[dc->attr_num] = ldb_dn_explode_attribute(dc->attributes, p);
+               LDB_DN_NULL_RETURN(dc->attributes[dc->attr_num]);
+
+               dc->attr_num++;
+
+               /* jump to the next attribute if any */
+               p = t;
+
+       } while(*p);
+
+       return dc;
+}
+
+/* FIXME: currently consider a dn composed of only case insensitive attributes
+         this is not correct and need to be fixed soon */
+static void ldb_dn_sort_attributes(struct ldb_dn *edn)
+{
+       struct ldb_dn_attribute *at0, *at1;
+       int i, j, k, l;
+
+       for (i = 0; i < edn->comp_num; i++) {
+               if (edn->components[i]->attr_num > 1) {
+
+                       /* it is very unlikely that there is a multivalued RDN. In that
+                          unlikely case it is very unlikely you will find more than 2
+                          values. So the use of bubble sort here seem to be acceptable */
+                       for (j = 0; (j + 1) < edn->components[i]->attr_num; j++) {
+                               for (k = j; k >= 0; k--) {
+                                       at0 = edn->components[i]->attributes[k];
+                                       at1 = edn->components[i]->attributes[k + 1];
+                                       l = ldb_caseless_cmp(at0->name, at1->name);
+                                       if (l > 0) {
+                                               /* already sorted, so no bubbles to move exit inner loop */
+                                               break;
+                                       }
+                                       if (l == 0) {
+                                               if (ldb_caseless_cmp(at0->value, at1->value) >= 0) {
+                                                       /* already sorted, so no bubbles to move exit inner loop */
+                                                       break;
+                                               }
+                                       }
+                                       
+                                       edn->components[i]->attributes[k] = at1;
+                                       edn->components[i]->attributes[k + 1] = at0;
+                               }
+                       }
+               }
+       }
+}
+
+struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
+{
+       struct ldb_dn *edn; /* the exploded dn */
+       char *pdn, *p;
+
+       /* Allocate a structure to hold the exploded DN */
+       edn = talloc(mem_ctx, struct ldb_dn);
+       LDB_DN_NULL_RETURN(edn);
+
+       /* Initially there are no components */
+       edn->comp_num = 0;
+       edn->components = NULL;
+
+       pdn = p = talloc_strdup(edn, dn);
+       if (!pdn)
+               goto error;
+
+       /* get the components */
+       do {
+               char *t;
+
+               /* terminate the current component and return pointer to the next one */
+               t = seek_to_separator(p, ",;");
+               if (t == NULL)
+                       goto error;
+
+               if (*t) { /* here there is a separator */
+                       *t = '\0'; /*terminate */
+                       t++; /* a separtor means there's another component that follows */
+               }
+
+               /* allocate space to hold the dn component */
+               edn->components = talloc_realloc(edn, edn->components,
+                                                struct ldb_dn_component *,
+                                                edn->comp_num + 1);
+               if (edn->components == NULL)
+                       goto error;
+
+               /* store the exploded component in the main structure */
+               edn->components[edn->comp_num] = explode_component(edn->components, p);
+               if (edn->components[edn->comp_num] == NULL)
+                       goto error;
+
+               edn->comp_num++;
+
+               /* jump to the next component if any */
+               p = t;
+
+       } while(*p);
+
+       /* sort attributes if there's any multivalued component */
+       ldb_dn_sort_attributes(edn);
+
+       talloc_free(pdn);
+       return edn;
+
+error:
+       talloc_free(edn);
+       return NULL;
+}
+
+char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn)
+{
+       char *dn, *format, *ename, *evalue;
+       int i, j;
+
+       dn = talloc_strdup(mem_ctx, "");
+       LDB_DN_NULL_RETURN(dn);
+
+       for (i = 0; i < edn->comp_num; i++) {
+               if (i != 0) {
+                       dn = talloc_append_string(mem_ctx, dn, ",");
+               }
+               for (j = 0; j < edn->components[i]->attr_num; j++) {
+                       if (i != 0 && j == 0)
+                               format = ",%s=%s";
+                       else if (i == 0 && j == 0)
+                               format = "%s=%s";
+                       else
+                               format = "+%s=%s";
+
+                       ename = escape_string(mem_ctx, edn->components[i]->attributes[j]->name);
+                       LDB_DN_NULL_RETURN(ename);
+
+                       evalue = escape_string(mem_ctx, edn->components[i]->attributes[j]->value);
+                       LDB_DN_NULL_RETURN(evalue);
+
+                       dn = talloc_asprintf_append(dn, format, ename, evalue);
+                       LDB_DN_NULL_RETURN(dn);
+
+                       talloc_free(ename);
+                       talloc_free(evalue);
+               }
+       }
+
+       return dn;
+}
+
+/* FIXME: currently consider a dn composed of only case insensitive attributes
+         this is not correct and need to be fixed soon */
+int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1)
+{
+       struct ldb_dn_attribute *at0, *at1;
+       int i, j, k;
+
+       /* if the number of components doesn't match they differ */
+       if (edn0->comp_num != edn1->comp_num)
+               return (edn1->comp_num - edn0->comp_num);
+
+       for (i = 0; i < edn0->comp_num; i++) {
+
+               /* if the number of attributes per component doesn't match they differ */
+               if (edn0->components[i]->attr_num != edn1->components[i]->attr_num)
+                       return (edn1->components[i]->attr_num - edn0->components[i]->attr_num);
+
+               for (j = 0; j < edn0->components[i]->attr_num; j++) {
+                       at0 = edn0->components[i]->attributes[j];
+                       at1 = edn1->components[i]->attributes[j];
+
+                       /* compare names */
+                       k = ldb_caseless_cmp(at0->name, at1->name);
+                       if (k)
+                               return k;
+
+                       /* names match, compare values */
+                       k = ldb_caseless_cmp(at0->value, at1->value);
+                       if (k)
+                               return k;
+               }
+       }
+}
+
+/*
+  casefold a dn. We need to uppercase the attribute names, and the 
+  attribute values of case insensitive attributes. We also need to remove
+  extraneous spaces between elements
+*/
+struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data,
+                               int (* case_fold_attr_fn)(void * user_data, char * attr))
+{
+       struct ldb_dn *cedn;
+       int i, j;
+
+       cedn = talloc(mem_ctx, struct ldb_dn);
+       LDB_DN_NULL_RETURN(cedn);
+
+       cedn->comp_num = edn->comp_num;
+       cedn->components = talloc_array(cedn, struct ldb_dn_component *, edn->comp_num);
+       LDB_DN_NULL_RETURN(cedn->components);
+
+       for (i = 0; i < edn->comp_num; i++) {
+               struct ldb_dn_component *dc;
+
+               dc = talloc(cedn->components, struct ldb_dn_component);
+               LDB_DN_NULL_RETURN(dc);
+
+               dc->attr_num = edn->components[i]->attr_num;
+               dc->attributes = edn->components[i]->attributes;
+               LDB_DN_NULL_RETURN(dc->attributes);
+
+               for (j = 0; j < edn->components[i]->attr_num; j++) {
+                       struct ldb_dn_attribute *at;
+
+                       at = talloc(dc->attributes, struct ldb_dn_attribute);
+                       LDB_DN_NULL_RETURN(at);
+
+                       at->name = ldb_casefold(at, edn->components[i]->attributes[j]->name);
+                       LDB_DN_NULL_RETURN(at->name);
+
+                       if (case_fold_attr_fn(user_data, at->name)) {
+                               at->value = ldb_casefold(at, edn->components[i]->attributes[j]->value);
+                       } else {
+                               at->value = talloc_strdup(at, edn->components[i]->attributes[j]->value);
+                       }
+                       LDB_DN_NULL_RETURN(at->value);
+
+                       dc->attributes[j] = at;
+               }
+
+               cedn->components[i] = dc;
+       }
+
+       return cedn;
+}
+
diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c
deleted file mode 100644 (file)
index 0e2efa8..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/* 
-   ldb database library
-
-   Copyright (C) Simo Sorce 2004
-   Copyright (C) Derrell Lipman 2005
-
-     ** 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 2 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, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/*
- *  Name: ldb
- *
- *  Component: ldb dn parsing
- *
- *  Description: explode a dn into it's own basic elements
- *               and put them in a structure
- *
- *  Author: Simo Sorce
- *  Author: Derrell Lipman
- */
-
-#include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_private.h"
-#include "ldb/include/ldb_explode_dn.h"
-
-#define LDB_PARSE_DN_INVALID(x) do {            \
-       if (x) {                                \
-                goto failed;                    \
-       }                                       \
-} while(0)
-
-
-/*
- * Forward declarations
- */
-
-static char *
-parse_slash(char *p,
-            char *end);
-
-
-
-/*
- * Public functions
- */
-
-/*
- * ldb_explode_dn()
- *
- * Explode, normalize, and optionally case-fold a DN string.  The result is a
- * structure containing arrays of the constituent RDNs.
- *
- * Parameters:
- *   mem_ctx -
- *     talloc context on which all allocated memory is hung
- *
- *   orig_dn -
- *     The distinguished name, in string format, to be exploded
- *
- *   hUserData -
- *     Data handle provided by the caller, and passed back to the caller in
- *     the case_fold_attr_fn callback function.  This handle is not otherwise
- *     used within this function.
- *
- *   case_fold_attr_fn -
- *     Pointer to a callback function which will be called to determine if a
- *     particular attribute type (name) requires case-folding of its values.
- *     If this function pointer is non-null, then attribute names will always
- *     be case-folded.  Additionally, the function pointed to by
- *     case_fold_attr_fn will be called with the data handle (hUserData) and
- *     an attribute name as its parameters, and should return TRUE or FALSE to
- *     indicate whether values of that attribute type should be case-folded.
- *
- *     If case_fold_attr_fn is null, then neither attribute names nor
- *     attribute values will be case-folded.
- *
- * Returns:
- *   Upon success, an ldb_dn structure pointer is returned, containing the
- *   exploded DN.
- *
- *   If memory could not be allocated or if the DN was improperly formatted,
- *   NULL is returned.
- */
-struct ldb_dn *
-ldb_explode_dn(void * mem_ctx,
-               const char * orig_dn,
-               void * hUserData,
-               int (*case_fold_attr_fn)(void * hUserData,
-                                        char * attr))
-{
-       struct ldb_dn *             dn;
-       struct ldb_dn_component *   component;
-       struct ldb_dn_attribute *   attribute;
-       char *                      p;
-        char *                      start;
-        char *                      separator;
-        char *                      src;
-        char *                      dest;
-        char *                      dn_copy;
-        char *                      dn_end;
-       int                         i;
-        int                         size;
-        int                         orig_len;
-
-        /* Allocate a structure to hold the exploded DN */
-       if ((dn = talloc(mem_ctx, struct ldb_dn)) == NULL) {
-            return NULL;
-        }
-
-        /* Initially there are no components */
-       dn->comp_num = 0;
-
-        /* Allocate the component array, with space for one component */
-       if ((dn->components =
-             talloc_array(dn, struct ldb_dn_component *, 1)) == NULL) {
-
-                goto failed;
-        }
-
-        /* Allocate the first component */
-       if ((component = talloc(dn, struct ldb_dn_component)) == NULL) {
-                goto failed;
-        }
-
-        /* This component has no attributes yet */
-       component->attr_num = 0;
-
-        /* Get the length of the provided DN */
-       if ((orig_len = strlen(orig_dn)) == 0) {
-
-                /* We found a zero-length DN.  Return it. */
-               if ((dn->dn = talloc_strdup(dn, orig_dn)) == NULL) {
-                        goto failed;
-                }
-               return dn;
-       }
-
-        /* Copy the provided DN so we can manipulate it */
-        if ((dn_copy = talloc_strdup(mem_ctx, orig_dn)) == NULL) {
-                goto failed;
-        }
-
-        p = dn_copy;
-        
-        /* Our copy may end shorter than the original as we unescape chars */
-       dn_end = dn_copy + orig_len + 1;
-
-        /* For each attribute/value pair... */
-       do {
-                /* Allocate an array to hold the attributes, initially len 1 */
-               if ((component->attributes =
-                     talloc_array(component,
-                                  struct ldb_dn_attribute *, 1)) == NULL) {
-                        goto failed;
-                }
-                
-                /* Allocate this attribute */
-               if ((attribute =
-                     talloc(component, struct ldb_dn_attribute)) == NULL) {
-                        goto failed;
-                }
-
-               /* skip white space */
-               while (*p == ' ' || *p == '\n') {
-                       p++;
-               }
-
-               /* start parsing this component */
-               do {
-                        /* Save pointer to beginning of attribute name */
-                       start = p;
-
-                       /* find our attribute/value separator '=' */
-                       while (*p != '\0' && *p != '=') {
-                               if (*p == '\\') {
-                                       if ((dn_end =
-                                             parse_slash(p, dn_end)) == NULL) {
-                                                goto failed;
-                                        }
-                               }
-                               p++;
-                       }
-
-                        /* Ensure we found the attribute/value separator */
-                        if (*p != '=') {
-                                goto failed;
-                        }
-
-                        /* Save pointer to separator */
-                       separator = p;
-
-                       /* remove trailing white space from attribute name */
-                       while (p > start &&
-                               (*(p - 1) == ' ' || *(p - 1) == '\n')) {
-
-                               p--;
-                       }
-                       LDB_PARSE_DN_INVALID((p - start) < 1);
-
-                       /* save attribute name */
-                       if ((attribute->name =
-                             talloc_strndup(attribute,
-                                            start,
-                                            p - start)) == NULL) {
-                                goto failed;
-                        }
-
-                        /* see if this attribute name needs case folding */
-                        if (case_fold_attr_fn != NULL &&
-                            (* case_fold_attr_fn)(hUserData,
-                                                  attribute->name)) {
-                               p = attribute->name;
-                               if ((attribute->name =
-                                    ldb_casefold(attribute, p)) == NULL) {
-                                       goto failed;
-                               }
-                               talloc_free(p);
-                       }
-
-                       ldb_debug(mem_ctx,
-                                  LDB_DEBUG_TRACE,
-                                  "attribute name: [%s]\n", attribute->name);
-
-                        /* skip white space after the separator */
-                        p = separator + 1;
-                        p += strspn(p, " \n");
-                        
-                        /* ensure there's a value here */
-                        if (*p == '\0') {
-                                goto failed;
-                        }
-
-                       /* check if the value is enclosed in QUOTATION */
-                       if (*p == '"') {
-                                /* save pointer to beginning of attr value */
-                               start = p + 1;
-
-                                /* find the trailing QUOTE */
-                               while (*p != '\0' && *p != '"') {
-                                       if (*p == '\\') {
-                                               if ((dn_end =
-                                                     parse_slash(p, dn_end)) == NULL) {
-                                                        goto failed;
-                                                }
-                                       }
-
-                                       p++;
-                               }
-
-                                /* skip spaces until the separator */
-                                if (*p == '\0') {
-                                        /* We're already at end of string */
-                                        separator = p;
-                                } else {
-                                        /* Skip spaces */
-                                        separator = p + 1 + strspn(p+1, " \n");
-                                }
-
-                                /* must be end of string or a separator here */
-                               if (*separator != '\0' &&
-                                    *separator != ',' &&
-                                    *separator != ';' &&
-                                    *separator != '+') { 
-                                       /* Error Malformed DN */
-                                        goto failed;
-                               }
-                       } else {
-                                /*
-                                 * Value is not quouted.
-                                 */
-
-                                /* save pointer to beginning of value */
-                                start = p;
-
-                                /* find end of value */
-                               while (*p != '\0' &&
-                                       *p != ',' &&
-                                       *p != ';' &&
-                                       *p != '+') {
-
-                                       if (*p == '\\') {
-                                               if ((dn_end =
-                                                     parse_slash(p, dn_end)) == NULL) {
-                                                        goto failed;
-                                                }
-                                       }
-
-                                       p++;
-                               }
-
-                                /* save pointer to the terminating separator */
-                               separator = p;
-
-                               /* remove trailing whitespace */
-                               while (p > start &&
-                                       (*(p - 1) == ' ' ||
-                                        *(p - 1) == '\n')) {
-                                    
-                                       p--;
-                               }
-                       }
-                       LDB_PARSE_DN_INVALID((p - start) < 1);
-
-                       /* save the value */
-                       if ((attribute->value =
-                             talloc_strndup(attribute,
-                                            start,
-                                            p - start)) == NULL) {
-                                goto failed;
-                        }
-
-                        /* see if this attribute value needs case folding */
-                        if (case_fold_attr_fn != NULL &&
-                            (* case_fold_attr_fn)(hUserData,
-                                                  attribute->name)) {
-                                /* yup, case-fold it. */
-                                p = attribute->value;
-                                if ((attribute->value =
-                                     ldb_casefold(attribute, p)) == NULL) {
-                                        goto failed;
-                                }
-                                talloc_free(p);
-                        }
-
-                        ldb_debug(mem_ctx,
-                                  LDB_DEBUG_TRACE,
-                                  "attribute value: [%s]\n", attribute->value);
-
-                        /* save the entire RDN */
-                        if ((attribute->rdn =
-                             talloc_asprintf(attribute,
-                                             "%s=%s",
-                                             attribute->name,
-                                             attribute->value)) == NULL) {
-                                goto failed;
-                        }
-
-                        ldb_debug(mem_ctx,
-                                  LDB_DEBUG_TRACE,
-                                  "attribute: [%s]\n", attribute->rdn);
-
-                        /* add this attribute to the attribute list */
-                       component->attributes[component->attr_num] = attribute;
-                       component->attr_num++;
-
-                        /* is this a multi-valued attribute? */
-                       if (*separator == '+') {
-                                /* Yup.  prepare for the next value. */
-                                if ((component->attributes =
-                                     talloc_realloc(component,
-                                                    component->attributes,
-                                                    struct ldb_dn_attribute *,
-                                                    component->attr_num + 1)) == NULL) {
-                                        goto failed;
-                                }
-
-                               /* allocate new attribute structure */
-                               if ((attribute =
-                                     talloc(component,
-                                            struct ldb_dn_attribute)) == NULL) {
-                                        goto failed;
-                                }
-                       }
-
-                        /* if we're not at end of string, skip white space */
-                        if (*separator != '\0') {
-                                /* skip spaces past the separator */
-                                p = separator + 1;
-                                p += strspn(p, " \n");
-                        }
-
-               } while (*separator == '+');
-
-                /* find total length of all attributes */
-               for (i = 0, size = 0; i < component->attr_num; i++) {
-                       size += strlen(component->attributes[i]->rdn) + 1;
-               }
-
-               /*
-                 * rebuild the normalized component
-                 */
-
-                /* allocate space for the normalized component */
-               if ((dest = talloc_size(component, size)) == NULL) {
-
-                        goto failed;
-                }
-
-                /* Save the pointer to the beginning of the string */
-                component->component = dest;
-
-                /* copy each of the attributes to the normalized component */
-               for (i = 0; i < component->attr_num; i++) {
-                       if (i != 0) {
-                               *dest++ = '+';
-                       }
-                       src = component->attributes[i]->rdn;
-
-                        /* we are guaranteed to have enough space in dest */
-                        size = strlen(src);
-                        strncpy(dest, src, size + 1);
-                        dest += size;
-               }
-
-               ldb_debug(mem_ctx,
-                          LDB_DEBUG_TRACE,
-                          "component: [%s]\n", component->component);
-
-                /* insert the component into the component list */
-               dn->components[dn->comp_num] = component;
-               dn->comp_num++;
-
-                /* if there are additional components... */
-               if (*separator == ',' || *separator == ';') {
-                        /* ... then prepare to parse them */
-                        if ((dn->components =
-                             talloc_realloc(dn,
-                                            dn->components,
-                                            struct ldb_dn_component *,
-                                            dn->comp_num + 1)) == NULL ||
-                            (component =
-                             talloc(dn, struct ldb_dn_component)) == NULL) {
-
-                                goto failed;
-                        }
-
-                       component->attr_num = 0;
-               }
-
-                /* update pointer to after the separator */
-               p = separator + 1;
-
-       } while(*separator == ',' || *separator == ';');
-
-        /* find total length of all components */
-       for (i = 0, size = 0; i < dn->comp_num; i++) {
-               size = size + strlen(dn->components[i]->component) + 1;
-       }
-
-       /* rebuild the normalized DN */
-       if ((dest = talloc_size(dn, size)) == NULL) {
-                goto failed;
-        }
-
-        /* Save the pointer to the beginning of the */
-        dn->dn = dest;
-
-        /* copy the normalized components into the DN */
-       for (i = 0; i < dn->comp_num; i++) {
-
-                /* add a separator between DN components */
-               if (i != 0) {
-                       *dest++ = ',';
-               }
-
-                /* point to this component of the DN */
-               src = dn->components[i]->component;
-
-                /* we are guaranteed to have enough space in dest */
-                size = strlen(src);
-                strncpy(dest, src, size + 1);
-                dest += size;
-       }
-
-       ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn);
-
-        /* we don't need the copy of the DN any more */
-       talloc_free(dn_copy);
-
-        /* give 'em what they came for! */
-       return dn;
-
-failed:
-        /* something went wrong.  free memory and tell 'em it failed */
-        talloc_free(dn);
-        ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn);
-        return NULL;
-}
-
-
-static char *parse_slash(char *p, char *end)
-{
-       unsigned x;
-       if (strchr(",=\n+<>#;\\\"", p[1])) {
-               memmove(p, p + 1, end - (p + 1));
-               return (end - 1);
-       }
-       if (sscanf(p + 1, "%02x", &x) == 1) {
-               *p = (unsigned char)x;
-               memmove(p + 1, p + 3, end - (p + 3));
-               return (end - 2);
-       }
-       return NULL;
-}
-
similarity index 61%
rename from source4/lib/ldb/include/ldb_explode_dn.h
rename to source4/lib/ldb/include/ldb_dn.h
index af9829ba40b9aa8c9e25fc6860f3e20762029ff2..f355ee4879bb7303bca6684c50b2b751d542f3ad 100644 (file)
 */
 
 struct ldb_dn_attribute {
-       char *                      rdn;
-       char *                      name;
-       char *                      value;
+       char *name;
+       char *value;
 };
 
 struct ldb_dn_component {
-       char *                      component;
-       int                         attr_num;
-       struct ldb_dn_attribute **  attributes;
+       int attr_num;
+       struct ldb_dn_attribute **attributes;
 };
 
 struct ldb_dn {
-       char *                      dn;
-       int                         comp_num;
-       struct ldb_dn_component **  components;
+       int comp_num;
+       struct ldb_dn_component **components;
 };
 
 
-extern struct ldb_dn *
-ldb_explode_dn(void * mem_ctx,
-               const char * orig_dn,
-               void * hUserData,
-               int (*case_fold_attr_fn)(void * hUserData,
-                                        char * attr));
+struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn);
+char *ldb_dn_linearize(void *mem_ctx, struct ldb_dn *edn);
+int ldb_dn_compare(struct ldb_dn *edn0, struct ldb_dn *edn1);
+struct ldb_dn *ldb_dn_casefold(void *mem_ctx, struct ldb_dn *edn, void *user_data,
+                               int (* case_fold_attr_fn)(void * user_data, char * attr));