]> git.sur5r.net Git - openldap/commitdiff
add more versatile private API for filter escaping
authorPierangelo Masarati <ando@openldap.org>
Fri, 25 Nov 2005 10:41:33 +0000 (10:41 +0000)
committerPierangelo Masarati <ando@openldap.org>
Fri, 25 Nov 2005 10:41:33 +0000 (10:41 +0000)
include/ldap_pvt.h
libraries/libldap/search.c
servers/slapd/overlays/unique.c

index 54246b402fc1a84002e7b5563446a5c09d0a9644..384f9f3f2d695377b336b9b1e8db570e4b390a50 100644 (file)
@@ -212,6 +212,13 @@ ldap_pvt_find_wildcard LDAP_P((    const char *s ));
 LDAP_F( ber_slen_t )
 ldap_pvt_filter_value_unescape LDAP_P(( char *filter ));
 
+LDAP_F( ber_len_t )
+ldap_bv2escaped_filter_value_len LDAP_P(( struct berval *in ));
+
+LDAP_F( int )
+ldap_bv2escaped_filter_value_x LDAP_P(( struct berval *in, struct berval *out,
+       int inplace, void *ctx ));
+
 /* string.c */
 LDAP_F( char * )
 ldap_pvt_str2upper LDAP_P(( char *str ));
index afa63ef9aed16fb2356d2fca64ebb9cd6a7cc3b8..0d4fe706b18c45db79ed0fa624fabcb582bef5d5 100644 (file)
@@ -365,53 +365,106 @@ ldap_search_s(
        return( ldap_result2error( ld, *res, 0 ) );
 }
 
+static char escape[128] = {
+       1, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+
+       0, 0, 0, 0, 0, 0, 0, 0,
+       1, 1, 1, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 1, 0, 0, 0,
+
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0
+};
+#define        NEEDFLTESCAPE(c)        ((c) & 0x80 || escape[ (unsigned)(c) ])
+
+/*
+ * compute the length of the escaped value;
+ * returns ((ber_len_t)(-1)) if no escaping is required.
+ */
+ber_len_t
+ldap_bv2escaped_filter_value_len( struct berval *in )
+{
+       ber_len_t       i, l;
+
+       assert( in != NULL );
+
+       if ( in->bv_len == 0 ) {
+               return 0;
+       }
+
+       /* assume we'll escape everything */
+       for( l = 0, i = 0; i < in->bv_len; l++, i++ ) {
+               char c = in->bv_val[ i ];
+               if ( NEEDFLTESCAPE( c ) ) {
+                       l += 2;
+               }
+       }
+
+       return l;
+}
+
 int
 ldap_bv2escaped_filter_value( struct berval *in, struct berval *out )
 {
-       ber_len_t i;
-       static char escape[128] = {
-               1, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-
-               0, 0, 0, 0, 0, 0, 0, 0,
-               1, 1, 1, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 1, 0, 0, 0,
-
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0, 0, 0, 0, 0, 0, 0
-       };
-
-       out->bv_len = 0;
-       out->bv_val = NULL;
-
-       if( in->bv_len == 0 ) return 0;
+       return ldap_bv2escaped_filter_value_x( in, out, 0, NULL );
+}
+
+int
+ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx )
+{
+       ber_len_t       i, l;
+
+       assert( in != NULL );
+       assert( out != NULL );
+
+       BER_BVZERO( out );
+
+       if ( in->bv_len == 0 ) {
+               return 0;
+       }
 
        /* assume we'll escape everything */
-       out->bv_val = LDAP_MALLOC( 3 * in->bv_len + 1 );
-       if( out->bv_val == NULL ) return -1;
+       l = ldap_bv2escaped_filter_value_len( in );
+       if ( l == in->bv_len ) {
+               if ( inplace ) {
+                       *out = *in;
+               } else {
+                       ber_dupbv( out, in );
+               }
+               return 0;
+       }
+       out->bv_val = LDAP_MALLOCX( l + 1, ctx );
+       if ( out->bv_val == NULL ) {
+               return -1;
+       }
 
-       for( i=0; i<in->bv_len; i++ ) {
+       for ( i = 0; i < in->bv_len; i++ ) {
                char c = in->bv_val[ i ];
-               if (c & 0x80 || escape[ (unsigned)c ]) {
+               if ( NEEDFLTESCAPE( c ) ) {
+                       assert( out->bv_len < l - 2 );
                        out->bv_val[out->bv_len++] = '\\';
                        out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)];
                        out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c];
+
                } else {
+                       assert( out->bv_len < l );
                        out->bv_val[out->bv_len++] = c;
                }
        }
 
        out->bv_val[out->bv_len] = '\0';
+
        return 0;
 }
 
index 7120b1f69ba3c2a6cded1c2e7877d94296dc7ddd..38ada8877af2c5d8bbb935b6df3556875dbb8eb1 100644 (file)
@@ -301,7 +301,8 @@ static char *build_filter(
        unique_data *ud,
        AttributeDescription *ad,
        BerVarray b,
-       char *kp
+       char *kp,
+       void *ctx
 )
 {
        unique_attrs *up;
@@ -332,9 +333,11 @@ static char *build_filter(
                        for ( i = 0; b[i].bv_val; i++ ) {
                                struct berval   bv;
 
-                               ldap_bv2escaped_filter_value( &b[i], &bv );
+                               ldap_bv2escaped_filter_value_x( &b[i], &bv, 1, ctx );
                                kp += sprintf( kp, "(%s=%s)", ad->ad_cname.bv_val, bv.bv_val );
-                               ldap_memfree( bv.bv_val );
+                               if ( bv.bv_val != b[i].bv_val ) {
+                                       ber_memfree_x( bv.bv_val, ctx );
+                               }
                        }
                } else if ( ud->strict ) {
                        kp += sprintf( kp, "(%s=*)", ad->ad_cname.bv_val );
@@ -440,7 +443,7 @@ static int unique_add(
        kp = key + sprintf(key, "(|");
 
        for(a = op->ora_e->e_attrs; a; a = a->a_next) {
-               kp = build_filter(ud, a->a_desc, a->a_vals, kp);
+               kp = build_filter(ud, a->a_desc, a->a_vals, kp, op->o_tmpmemctx);
        }
 
        sprintf(kp, ")");
@@ -492,7 +495,7 @@ static int unique_modify(
 
        for(m = op->orm_modlist; m; m = m->sml_next) {
                if ((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) continue;
-               kp = build_filter(ud, m->sml_desc, m->sml_values, kp);
+               kp = build_filter(ud, m->sml_desc, m->sml_values, kp, op->o_tmpmemctx);
        }
 
        sprintf(kp, ")");
@@ -555,7 +558,7 @@ static int unique_modrdn(
 
        for(i = 0; newrdn[i]; i++) {
                bv[0] = newrdn[i]->la_value;
-               kp = build_filter(ud, newrdn[i]->la_private, bv, kp);
+               kp = build_filter(ud, newrdn[i]->la_private, bv, kp, op->o_tmpmemctx);
        }
 
        sprintf(kp, ")");