Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / source4 / lib / ldb / common / ldb_parse.c
index 110361d2b712c64f9e1b6aa75fc0e6619383266c..654a635abf1d7edb016659d2de3b965b2f1063a7 100644 (file)
@@ -10,7 +10,7 @@
    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.
+   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
@@ -18,8 +18,7 @@
    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
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
 
 */
 
-#include "includes.h"
-#include "ldb/include/ldb.h"
-#include <ctype.h>
-
+#include "ldb_private.h"
+#include "system/locale.h"
 
 /*
 a filter is defined by:
@@ -68,7 +65,7 @@ struct ldb_val ldb_binary_decode(void *mem_ctx, const char *str)
        struct ldb_val ret;
        int slen = str?strlen(str):0;
 
-       ret.data = talloc_size(mem_ctx, slen+1);
+       ret.data = (uint8_t *)talloc_size(mem_ctx, slen+1);
        ret.length = 0;
        if (ret.data == NULL) return ret;
 
@@ -127,6 +124,19 @@ char *ldb_binary_encode(void *mem_ctx, struct ldb_val val)
        return ret;     
 }
 
+/*
+   encode a string as a RFC2254 binary string, escaping any
+   non-printable or '\' characters.  This routine is suitable for use
+   in escaping user data in ldap filters.
+*/
+char *ldb_binary_encode_string(void *mem_ctx, const char *string)
+{
+       struct ldb_val val;
+       val.data = discard_const_p(uint8_t, string);
+       val.length = strlen(string);
+       return ldb_binary_encode(mem_ctx, val);
+}
+
 /* find the first matching wildcard */
 static char *ldb_parse_find_wildcard(char *value)
 {
@@ -182,7 +192,9 @@ static struct ldb_val **ldb_wildcard_decode(void *mem_ctx, const char *string)
                val++;
        }
 
-       ret[val] = NULL;
+       if (ret != NULL) {
+               ret[val] = NULL;
+       }
 
        return ret;
 }
@@ -251,6 +263,10 @@ static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char *
        /* retrieve attributetype name */
        t = p;
 
+       if (*p == '@') { /* for internal attributes the first char can be @ */
+               p++;
+       }
+
        while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */
                p++;
        }
@@ -271,7 +287,7 @@ static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char *
        }
 
        /* save name */
-       name = talloc_memdup(mem_ctx, t, t1 - t + 1);
+       name = (char *)talloc_memdup(mem_ctx, t, t1 - t + 1);
        if (name == NULL) return 0;
        name[t1 - t] = '\0';
 
@@ -307,12 +323,12 @@ static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char *
 
        while (isspace((unsigned char)*p)) p++;
 
-       /* retieve value */
+       /* retrieve value */
        t = p;
 
        while (*p && ((*p != ')') || ((*p == ')') && (*(p - 1) == '\\')))) p++;
 
-       val = talloc_memdup(mem_ctx, t, p - t + 1);
+       val = (char *)talloc_memdup(mem_ctx, t, p - t + 1);
        if (val == NULL) {
                talloc_free(name);
                return 0;
@@ -621,7 +637,7 @@ static struct ldb_parse_tree *ldb_parse_filter(void *mem_ctx, const char **s)
 struct ldb_parse_tree *ldb_parse_tree(void *mem_ctx, const char *s)
 {
        if (s == NULL || *s == 0) {
-               s = "(|(objectClass=*)(dn=*))";
+               s = "(|(objectClass=*)(distinguishedName=*))";
        }
 
        while (isspace((unsigned char)*s)) s++;
@@ -695,16 +711,18 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree)
                                talloc_free(ret);
                                return NULL;
                        }
-                       s = talloc_asprintf_append(ret, "%s*", s2);
+                       if (tree->u.substring.chunks[i+1] ||
+                           tree->u.substring.end_with_wildcard) {
+                               s = talloc_asprintf_append(ret, "%s*", s2);
+                       } else {
+                               s = talloc_asprintf_append(ret, "%s", s2);
+                       }
                        if (s == NULL) {
                                talloc_free(ret);
                                return NULL;
                        }
                        ret = s;
                }
-               if ( ! tree->u.substring.end_with_wildcard ) {
-                       ret[strlen(ret) - 1] = '\0'; /* remove last wildcard */
-               }
                s = talloc_asprintf_append(ret, ")");
                if (s == NULL) {
                        talloc_free(ret);
@@ -751,3 +769,51 @@ char *ldb_filter_from_tree(void *mem_ctx, struct ldb_parse_tree *tree)
        
        return NULL;
 }
+
+
+/*
+  replace any occurances of an attribute name in the parse tree with a
+  new name
+*/
+void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree, 
+                                const char *attr, 
+                                const char *replace)
+{
+       int i;
+       switch (tree->operation) {
+       case LDB_OP_AND:
+       case LDB_OP_OR:
+               for (i=0;i<tree->u.list.num_elements;i++) {
+                       ldb_parse_tree_attr_replace(tree->u.list.elements[i],
+                                                   attr, replace);
+               }
+               break;
+       case LDB_OP_NOT:
+               ldb_parse_tree_attr_replace(tree->u.isnot.child, attr, replace);
+               break;
+       case LDB_OP_EQUALITY:
+       case LDB_OP_GREATER:
+       case LDB_OP_LESS:
+       case LDB_OP_APPROX:
+               if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
+                       tree->u.equality.attr = replace;
+               }
+               break;
+       case LDB_OP_SUBSTRING:
+               if (ldb_attr_cmp(tree->u.substring.attr, attr) == 0) {
+                       tree->u.substring.attr = replace;
+               }
+               break;
+       case LDB_OP_PRESENT:
+               if (ldb_attr_cmp(tree->u.present.attr, attr) == 0) {
+                       tree->u.present.attr = replace;
+               }
+               break;
+       case LDB_OP_EXTENDED:
+               if (tree->u.extended.attr &&
+                   ldb_attr_cmp(tree->u.extended.attr, attr) == 0) {
+                       tree->u.extended.attr = replace;
+               }
+               break;
+       }
+}