r7418: work in progress
authorDerrell Lipman <derrell@samba.org>
Thu, 9 Jun 2005 02:47:26 +0000 (02:47 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:51 +0000 (13:17 -0500)
(This used to be commit 2a13e7655b1bce88694ddbb6a4d9349008ba42f0)

source4/lib/ldb/common/ldb_explode_dn.c
source4/lib/ldb/common/ldb_utf8.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_explode_dn.h
source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c

index 4e71bc70d144735a771b08295210539629c5b55c..d3f278c776c54b63ab2f81310a46cd0853755d23 100644 (file)
 } while(0)
 
 
+/*
+ * Forward declarations
+ */
 
 static char
 octet_from_hex(char * p,
-               char * ret)
-{
-        unsigned char   low_char;
-        unsigned char   high_char;
-        
-       unsigned char   low_binary;
-        unsigned char   high_binary;
-
-        if (p[0] == '\0' || p[1] == '\0') {
-                return -1;
-        }
-
-        high_char = p[0];
-        low_char = p[1];
-
-       if (high_char >= '0'  && high_char <= '9') {
-               high_binary = high_char - '0';
-       } else if (high_char >= 'A'  && high_char <= 'F') {
-               high_binary = 10 + (high_char - 'A');
-       } else if (high_char >= 'a' && high_char <= 'f') {
-               high_binary = 10 + (high_char - 'a');
-       } else {
-               return -1;
-       }
-
-       if (low_char >= '0' && low_char <= '9') {
-               low_binary = low_char - '0';
-       } else if (low_char >= 'A' && low_char <= 'F') {
-               low_binary = 10 + (low_char - 'A');
-       } else if (low_char >= 'a' && low_char <= 'f') {
-               low_binary = 10 + (low_char - 'a');
-       } else {
-               return -1;
-       }
-
-       *ret = (char) ((high_binary << 4) | low_binary);
-        return 0;
-}
+               char * ret);
 
 static char *
 parse_slash(char *p,
-            char *end)
-{
-       switch (*(p + 1)) {
-       case ',':
-       case '=':
-       case '\n':
-       case '+':
-       case '<':
-       case '>':
-       case '#':
-       case ';':
-       case '\\':
-       case '"':
-               memmove(p, p + 1, end - (p + 1));
-               return (end - 1);
-
-       default:
-                if (*(p + 1) != '\0' && *(p + 2) != '\0') {
-                        if (octet_from_hex(p + 1, p) < 0) {
-                                return NULL;
-                        }
-                        memmove(p + 1, p + 3, end - (p + 3));
-                        return (end - 2);
-                } else {
-                        return NULL;
-                }
-       }
-}
-
+            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)
+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;
@@ -222,6 +207,14 @@ ldb_explode_dn(void *mem_ctx,
                                 goto failed;
                         }
 
+                        /* attribute names are always case-folded */
+                        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);
@@ -314,6 +307,19 @@ ldb_explode_dn(void *mem_ctx,
                                 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);
@@ -460,3 +466,77 @@ failed:
         ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "Failed to parse %s\n", orig_dn);
         return NULL;
 }
+
+
+static char
+octet_from_hex(char * p,
+               char * ret)
+{
+        unsigned char   low_char;
+        unsigned char   high_char;
+        
+       unsigned char   low_binary;
+        unsigned char   high_binary;
+
+        if (p[0] == '\0' || p[1] == '\0') {
+                return -1;
+        }
+
+        high_char = p[0];
+        low_char = p[1];
+
+       if (high_char >= '0'  && high_char <= '9') {
+               high_binary = high_char - '0';
+       } else if (high_char >= 'A'  && high_char <= 'F') {
+               high_binary = 10 + (high_char - 'A');
+       } else if (high_char >= 'a' && high_char <= 'f') {
+               high_binary = 10 + (high_char - 'a');
+       } else {
+               return -1;
+       }
+
+       if (low_char >= '0' && low_char <= '9') {
+               low_binary = low_char - '0';
+       } else if (low_char >= 'A' && low_char <= 'F') {
+               low_binary = 10 + (low_char - 'A');
+       } else if (low_char >= 'a' && low_char <= 'f') {
+               low_binary = 10 + (low_char - 'a');
+       } else {
+               return -1;
+       }
+
+       *ret = (char) ((high_binary << 4) | low_binary);
+        return 0;
+}
+
+static char *
+parse_slash(char *p,
+            char *end)
+{
+       switch (*(p + 1)) {
+       case ',':
+       case '=':
+       case '\n':
+       case '+':
+       case '<':
+       case '>':
+       case '#':
+       case ';':
+       case '\\':
+       case '"':
+               memmove(p, p + 1, end - (p + 1));
+               return (end - 1);
+
+       default:
+                if (*(p + 1) != '\0' && *(p + 2) != '\0') {
+                        if (octet_from_hex(p + 1, p) < 0) {
+                                return NULL;
+                        }
+                        memmove(p + 1, p + 3, end - (p + 3));
+                        return (end - 2);
+                } else {
+                        return NULL;
+                }
+       }
+}
+
index 9cbb5646ddfc15226e9690d75a874e244903781c..dc25d6cf13e6763fee0548d0f56b839f05688fe9 100644 (file)
   TODO:
   a simple case folding function - will be replaced by a UTF8 aware function later
 */
-char *ldb_casefold(struct ldb_context *ldb, const char *s)
+char *ldb_casefold(void *mem_ctx, const char *s)
 {
        int i;
-       char *ret = talloc_strdup(ldb, s);
+       char *ret = talloc_strdup(mem_ctx, s);
        if (!s) {
                errno = ENOMEM;
                return NULL;
index 8ccf8967cba5055101c1fa097a8fd310635fc02e..91a826447a2aef8e32dccd4bdf1b29fbc970750c 100644 (file)
@@ -203,7 +203,7 @@ const char *ldb_errstring(struct ldb_context *ldb);
 /*
   casefold a string (should be UTF8, but at the moment it isn't)
 */
-char *ldb_casefold(struct ldb_context *ldb, const char *s);
+char *ldb_casefold(void *mem_ctx, const char *s);
 
 /*
   ldif manipulation functions
index 78768ebb80d1b868c4f4d4106e457cf53c734b5b..af9829ba40b9aa8c9e25fc6860f3e20762029ff2 100644 (file)
@@ -39,5 +39,8 @@ struct ldb_dn {
 
 
 extern struct ldb_dn *
-ldb_explode_dn(void *mem_ctx,
-               const char *orig_dn);
+ldb_explode_dn(void * mem_ctx,
+               const char * orig_dn,
+               void * hUserData,
+               int (*case_fold_attr_fn)(void * hUserData,
+                                        char * attr));
index 147ee599a95e4484f0564108a8dc419b13ccc139..4f774efbaea984f552937410d7e6fc205cee09c2 100644 (file)
@@ -37,6 +37,7 @@
 #include "ldb/include/ldb.h"
 #include "ldb/include/ldb_private.h"
 #include "ldb/include/ldb_parse.h"
+#include "ldb/include/ldb_explode_dn.h"
 #include "ldb/ldb_sqlite3/ldb_sqlite3.h"
 
 #ifndef FALSE
@@ -172,9 +173,11 @@ lsqlite3_option_find(const struct lsqlite3_private *lsqlite3,
   callback function used in call to ldb_dn_fold() for determining whether an
   attribute type requires case folding.
 */
-static int lsqlite3_case_fold_attr_required(struct ldb_module *module,
-                                           char *attr)
+static int lsqlite3_case_fold_attr_required(void * hUserData,
+                                            char *attr)
 {
+//        struct ldb_module * module = hUserData;
+        
 #warning "currently, all attributes require case folding"
         return TRUE;
 }
@@ -184,9 +187,9 @@ static int lsqlite3_case_fold_attr_required(struct ldb_module *module,
  * rename a record
  */
 static int
-lsqlite3_rename(struct ldb_module *module,
-                const char *olddn,
-                const char *newdn)
+lsqlite3_rename(struct ldb_module * module,
+                const char * olddn,
+                const char * newdn)
 {
        /* ignore ltdb specials */
        if (olddn[0] == '@' ||newdn[0] == '@') {
@@ -478,7 +481,7 @@ lsqlite3_search(struct ldb_module * module,
 {
        int                         ret;
         int                         bLoop;
-        long long                   eid;
+        long long                   eid = 0;
         char *                      sql;
        char *                      sql_constraints;
         char *                      table_list;
@@ -509,7 +512,7 @@ lsqlite3_search(struct ldb_module * module,
                                            pTail,
                                            -1,
                                            &pStmt,
-                                           &pTail)) != SQLITE_OK) {
+                                           NULL)) != SQLITE_OK) {
                         ret = -1;
                         break;
                 }
@@ -541,17 +544,24 @@ lsqlite3_search(struct ldb_module * module,
                  * Normal condition is only one time through loop.  Loop is
                  * rerun in error conditions, via "continue", above.
                  */
+                sqlite3_free(discard_const_p(char, pTail));
                 ret = 0;
                 bLoop = FALSE;
         }
 
+        if (ret != 0) {
+                sqlite3_free(discard_const_p(char, pTail));
+                return -1;
+        }
+
         /* Parse the filter expression into a tree we can work with */
        if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) {
+                sqlite3_free(discard_const_p(char, pTail));
                return -1;
        }
        
         /* Allocate a temporary talloc context */
-       hTalloc = talloc_new(module);
+       hTalloc = talloc_new(module->ldb);
 
         /* Move the parse tree to our temporary context */
        talloc_steal(hTalloc, pTree);
@@ -756,28 +766,20 @@ lsqlite3_new_dn(struct ldb_module * module,
                 char * pDN,
                 long long * pEID)
 {
-        char *          pName;
-        char *          pValue;
-
-        /* Normalize the distinguished name */
-        pDN = ldb_dn_fold(module, pDN, lsqlite3_case_fold_attr_required);
-
-        /* Parse the DN into its constituent components */
-#warning "this simple parse of DN ignores escaped '=' and ','.  fix it."
-        while (pDN != NULL) {
-                pName = strsep(&pValue, "=");
-
-                if (pDN == NULL) {
-                        /* Attribute name without value?  Should not occur. */
-                        return -1;
-                }
-
-                pValue = pName;
-                strsep(&pValue, "=");
-
-#warning "*** lsqlite3_new_dn() not yet fully implemented ***"
+        struct ldb_dn *             pExplodedDN;
+       struct ldb_context *        ldb = module->ldb;
+//     struct lsqlite3_private *   lsqlite3 = module->private_data;
+
+        /* Explode and normalize the DN */
+        if ((pExplodedDN =
+             ldb_explode_dn(ldb,
+                            pDN,
+                            ldb,
+                            lsqlite3_case_fold_attr_required)) == NULL) {
+                return -1;
         }
 
+#warning "*** lsqlite3_new_dn() not yet fully implemented ***"
         return -1;
 }