]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/ad.c
Fix prev commit
[openldap] / servers / slapd / ad.c
index 7d83de93303529d6380d7bb2070e3d15297f05a9..89f2c96b6f91db8547262fb2df314c3c7285b06b 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-2004 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"
 
@@ -222,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;
                                }
                        }
@@ -518,27 +527,73 @@ int ad_inlist(
                                &attrs->an_desc->ad_tags ) ) {
                                return 1;
                        }
+                       continue;
                }
 
                /*
-                * EXTENSION: see if requested description is +objectClass
+                * EXTENSION: see if requested description is @objectClass
                 * if so, return attributes which the class requires/allows
+                * else if requested description is !objectClass, return
+                * attributes which the class does not require/allow
                 */
                oc = attrs->an_oc;
                if( oc == NULL && attrs->an_name.bv_val ) {
                        switch( attrs->an_name.bv_val[0] ) {
-                       case '+': { /* new way */
+                       case '@': /* @objectClass */
+                       case '+': /* +objectClass (deprecated) */
+                       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;
@@ -547,6 +602,7 @@ int ad_inlist(
                        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] ) {
@@ -675,15 +731,16 @@ an_find(
 }
 
 /*
- * Convert a delimited string into a list of AttributeNames; 
- * 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.
+ * Convert a delimited string into a list of AttributeNames; 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 '@' (or '+') is
+ * 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;
- * however, this behavior is deprecated.
+ * NOTE: currently, if a valid attribute name is not found, the
+ * same string is also checked as valid objectclass name; however,
+ * this behavior is deprecated.
  */
 AttributeName *
 str2anlist( AttributeName *an, char *in, const char *brkstr )
@@ -717,6 +774,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 ) {
@@ -737,7 +795,9 @@ str2anlist( AttributeName *an, char *in, const char *brkstr )
                                        }
                                } break;
 
-                       case '+': {
+                       case '@':
+                       case '+': /* (deprecated) */
+                       case '!': {
                                        struct berval ocname;
                                        ocname.bv_len = anew->an_name.bv_len - 1;
                                        ocname.bv_val = &anew->an_name.bv_val[1];
@@ -751,6 +811,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: