]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/ad.c
honor '!' (objectClass negation) when checking attribute presence in list
[openldap] / servers / slapd / ad.c
index 407b091cadf503595b36517f36e21ed1e615c749..8543c9b2a4fb2041b32254e133a06ba48fa4f368 100644 (file)
@@ -1,9 +1,18 @@
+/* ad.c - routines for dealing with attribute descriptions */
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2003 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
  */
-/* ad.c - routines for dealing with attribute descriptions */
 
 #include "portable.h"
 
@@ -17,6 +26,7 @@
 
 #include "ldap_pvt.h"
 #include "slap.h"
+#include "lutil.h"
 
 typedef struct Attr_option {
        struct berval name;     /* option name or prefix */
@@ -221,10 +231,10 @@ int slap_bv2ad(
                                } else if ( rc > 0 ||
                                        ( rc == 0 && (unsigned)optlen > tags[i].bv_len ))
                                {
-                                       AC_MEMCPY( &tags[i+1], &tags[i],
-                                               (ntags-i)*sizeof(struct berval) );
-                                       tags[i].bv_val = opt;
-                                       tags[i].bv_len = optlen;
+                                       AC_MEMCPY( &tags[i+2], &tags[i+1],
+                                               (ntags-i-1)*sizeof(struct berval) );
+                                       tags[i+1].bv_val = opt;
+                                       tags[i+1].bv_len = optlen;
                                        goto done;
                                }
                        }
@@ -352,16 +362,13 @@ done:;
                                                j = (lp
                                                     ? lp - desc.ad_tags.bv_val - 1
                                                     : strlen( desc.ad_tags.bv_val ));
-                                               strncpy(cp, desc.ad_tags.bv_val, j);
-                                               cp += j;
+                                               cp = lutil_strncopy(cp, desc.ad_tags.bv_val, j);
                                        }
                                }
-                               strcpy(cp, ";binary");
-                               cp += sizeof(";binary")-1;
+                               cp = lutil_strcopy(cp, ";binary");
                                if( lp != NULL ) {
                                        *cp++ = ';';
-                                       strcpy(cp, lp);
-                                       cp += strlen( cp );
+                                       cp = lutil_strcopy(cp, lp);
                                }
                                d2->ad_cname.bv_len = cp - d2->ad_cname.bv_val;
                                if( desc.ad_tags.bv_len )
@@ -412,9 +419,6 @@ static int is_ad_subtags(
        const char *subtags, *subp, *subdelimp;
        int  suplen, sublen;
 
-       if( suptagsbv->bv_len == 0 ) return 1;
-       if( subtagsbv->bv_len == 0 ) return 0;
-
        subtags =subtagsbv->bv_val;
        suptags =suptagsbv->bv_val;
 
@@ -447,9 +451,13 @@ int is_ad_subtype(
        AttributeDescription *super
 )
 {
+       AttributeType *a;
        int lr;
 
-       if( !is_at_subtype( sub->ad_type, super->ad_type ) ) {
+       for ( a = sub->ad_type; a; a=a->sat_sup ) {
+               if ( a == super->ad_type ) break;
+       }
+       if( !a ) {
                return 0;
        }
 
@@ -460,11 +468,12 @@ int is_ad_subtype(
        }
 
        /* check for tagging options */
-       if ( !is_ad_subtags( &sub->ad_tags, &super->ad_tags )) {
+       if ( super->ad_tags.bv_len == 0 )
+               return 1;
+       if ( sub->ad_tags.bv_len == 0 )
                return 0;
-       }
 
-       return 1;
+       return is_ad_subtags( &sub->ad_tags, &super->ad_tags );
 }
 
 int ad_inlist(
@@ -474,24 +483,50 @@ int ad_inlist(
        if (! attrs ) return 0;
 
        for( ; attrs->an_name.bv_val; attrs++ ) {
+               AttributeType *a;
                ObjectClass *oc;
                int rc;
                
                if ( attrs->an_desc ) {
+                       int lr;
+
                        if ( desc == attrs->an_desc ) {
                                return 1;
                        }
 
                        /*
-                        * EXTENSION: if requested description is preceeded by an
+                        * EXTENSION: if requested description is preceeded by
                         * a '-' character, do not match on subtypes.
                         */
-                       if ( attrs->an_name.bv_val[0] != '-' &&
-                               is_ad_subtype( desc, attrs->an_desc ))
-                       {
+                       if ( attrs->an_name.bv_val[0] == '-' ) {
+                               continue;
+                       }
+                       
+                       /* Is this a subtype of the requested attr? */
+                       for (a = desc->ad_type; a; a=a->sat_sup) {
+                               if ( a == attrs->an_desc->ad_type )
+                                       break;
+                       }
+                       if ( !a ) {
+                               continue;
+                       }
+                       /* Does desc support all the requested flags? */
+                       lr = desc->ad_tags.bv_len ? SLAP_DESC_TAG_RANGE : 0;
+                       if(( attrs->an_desc->ad_flags & (desc->ad_flags | lr))
+                               != attrs->an_desc->ad_flags ) {
+                               continue;
+                       }
+                       /* Do the descs have compatible tags? */
+                       if ( attrs->an_desc->ad_tags.bv_len == 0 ) {
+                               return 1;
+                       }
+                       if ( desc->ad_tags.bv_len == 0) {
+                               continue;
+                       }
+                       if ( is_ad_subtags( &desc->ad_tags,
+                               &attrs->an_desc->ad_tags ) ) {
                                return 1;
                        }
-
                        continue;
                }
 
@@ -502,18 +537,60 @@ int ad_inlist(
                oc = attrs->an_oc;
                if( oc == NULL && attrs->an_name.bv_val ) {
                        switch( attrs->an_name.bv_val[0] ) {
-                       case '+': { /* new way */
+                       case '+': /* new way */
+                       case '!': { /* exclude */
                                        struct berval ocname;
                                        ocname.bv_len = attrs->an_name.bv_len - 1;
                                        ocname.bv_val = &attrs->an_name.bv_val[1];
                                        oc = oc_bvfind( &ocname );
+                                       attrs->an_oc_exclude = 0;
+                                       if ( oc && attrs->an_name.bv_val[0] == '!' ) {
+                                               attrs->an_oc_exclude = 1;
+                                       }
                                } break;
+
                        default: /* old (deprecated) way */
                                oc = oc_bvfind( &attrs->an_name );
                        }
                        attrs->an_oc = oc;
                }
                if( oc != NULL ) {
+                       if ( attrs->an_oc_exclude ) {
+                               int gotit = 0;
+
+                               if ( oc == slap_schema.si_oc_extensibleObject ) {
+                                       /* extensibleObject allows the return of anything */
+                                       return 0;
+                               }
+
+                               if( oc->soc_required ) {
+                                       /* allow return of required attributes */
+                                       int i;
+                               
+                                       for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
+                                               for (a = desc->ad_type; a; a=a->sat_sup) {
+                                                       if ( a == oc->soc_required[i] ) {
+                                                               return 0;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if( oc->soc_allowed ) {
+                                       /* allow return of allowed attributes */
+                                       int i;
+                                       for ( i = 0; oc->soc_allowed[i] != NULL; i++ ) {
+                                               for (a = desc->ad_type; a; a=a->sat_sup) {
+                                                       if ( a == oc->soc_allowed[i] ) {
+                                                               return 0;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               return 1;
+                       }
+                       
                        if ( oc == slap_schema.si_oc_extensibleObject ) {
                                /* extensibleObject allows the return of anything */
                                return 1;
@@ -522,10 +599,13 @@ int ad_inlist(
                        if( oc->soc_required ) {
                                /* allow return of required attributes */
                                int i;
+                               
                                for ( i = 0; oc->soc_required[i] != NULL; i++ ) {
-                                       rc = is_at_subtype( desc->ad_type,
-                                               oc->soc_required[i] );
-                                       if( rc ) return 1;
+                                       for (a = desc->ad_type; a; a=a->sat_sup) {
+                                               if ( a == oc->soc_required[i] ) {
+                                                       return 1;
+                                               }
+                                       }
                                }
                        }
 
@@ -533,9 +613,11 @@ int ad_inlist(
                                /* allow return of allowed attributes */
                                int i;
                                for ( i = 0; oc->soc_allowed[i] != NULL; i++ ) {
-                                       rc = is_at_subtype( desc->ad_type,
-                                               oc->soc_allowed[i] );
-                                       if( rc ) return 1;
+                                       for (a = desc->ad_type; a; a=a->sat_sup) {
+                                               if ( a == oc->soc_allowed[i] ) {
+                                                       return 1;
+                                               }
+                                       }
                                }
                        }
 
@@ -650,7 +732,8 @@ an_find(
  * add on to an existing list if it was given.  If the string
  * is not a valid attribute name, if a '-' is prepended it is 
  * skipped and the remaining name is tried again; if a '+' is
- * prepended, an objectclass name is searched instead.
+ * prepended, an objectclass name is searched instead; if a
+ * '!' is prepended, the objectclass name is negated.
  * 
  * NOTE: currently, if a valid attribute name is not found,
  * the same string is also checked as valid objectclass name;
@@ -688,6 +771,7 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
        {
                anew->an_desc = NULL;
                anew->an_oc = NULL;
+               anew->an_oc_exclude = 0;
                ber_str2bv(s, 0, 1, &anew->an_name);
                slap_bv2ad(&anew->an_name, &anew->an_desc, &text);
                if ( !anew->an_desc ) {
@@ -708,7 +792,8 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
                                        }
                                } break;
 
-                       case '+': {
+                       case '+':
+                       case '!': {
                                        struct berval ocname;
                                        ocname.bv_len = anew->an_name.bv_len - 1;
                                        ocname.bv_val = &anew->an_name.bv_val[1];
@@ -722,6 +807,10 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
                                                strcpy( in, s );
                                                return NULL;
                                        }
+
+                                       if ( anew->an_name.bv_val[0] == '!' ) {
+                                               anew->an_oc_exclude = 1;
+                                       }
                                } break;
 
                        default:
@@ -845,3 +934,25 @@ ad_find_option_definition( const char *opt, int optlen )
        }
        return NULL;
 }
+
+MatchingRule *ad_mr(
+       AttributeDescription *ad,
+       unsigned usage )
+{
+       switch( usage & SLAP_MR_TYPE_MASK ) {
+       case SLAP_MR_NONE:
+       case SLAP_MR_EQUALITY:
+               return ad->ad_type->sat_equality;
+               break;
+       case SLAP_MR_ORDERING:
+               return ad->ad_type->sat_ordering;
+               break;
+       case SLAP_MR_SUBSTR:
+               return ad->ad_type->sat_substr;
+               break;
+       case SLAP_MR_EXT:
+       default:
+               assert( 0 /* ad_mr: bad usage */);
+       }
+       return NULL;
+}