+ for( supp=suplang ; supp; supp=supdelimp ) {
+ supdelimp = strchrlen( supp, ';', &suplen );
+ if( supdelimp ) supdelimp++;
+
+ for( subp=sublang ; subp; subp=subdelimp ) {
+ subdelimp = strchrlen( subp, ';', &sublen );
+ if( subdelimp ) subdelimp++;
+
+ if ((( suplen < sublen && supp[suplen-1] == '-' ) ||
+ suplen == sublen ) && strncmp( supp, subp, suplen ) == 0 )
+ {
+ goto match;
+ }
+ }
+
+ return 0;
+match:;
+ }
+ return 1;
+}
+
+int is_ad_subtype(
+ AttributeDescription *sub,
+ AttributeDescription *super
+)
+{
+ int lr;
+
+ if( !is_at_subtype( sub->ad_type, super->ad_type ) ) {
+ return 0;
+ }
+
+ /* ensure sub does support all flags of super */
+ lr = sub->ad_lang.bv_len ? SLAP_DESC_LANG_RANGE : 0;
+ if(( super->ad_flags & ( sub->ad_flags | lr )) != super->ad_flags ) {
+ return 0;
+ }
+
+ /* check for language tags */
+ if ( !is_ad_sublang( &sub->ad_lang, &super->ad_lang )) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int ad_inlist(
+ AttributeDescription *desc,
+ AttributeName *attrs )
+{
+ if (! attrs ) return 0;
+
+ for( ; attrs->an_name.bv_val; attrs++ ) {
+ ObjectClass *oc;
+ int rc;
+
+ if ( attrs->an_desc ) {
+ if ( desc == attrs->an_desc ) {
+ return 1;
+ }
+
+ /*
+ * EXTENSION: if requested description is preceeded by an
+ * a '-' character, do not match on subtypes.
+ */
+ if ( attrs->an_name.bv_val[0] != '-' &&
+ is_ad_subtype( desc, attrs->an_desc ))
+ {
+ return 1;
+ }
+
+ continue;
+ }
+
+ /*
+ * EXTENSION: see if requested description is +objectClass
+ * if so, return attributes which the class requires/allows
+ */
+ oc = attrs->an_oc;
+ if( oc == NULL && attrs->an_name.bv_val ) {
+ switch( attrs->an_name.bv_val[0] ) {
+ case '+': { /* new way */
+ 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 );
+ } break;
+ default: /* old (deprecated) way */
+ oc = oc_bvfind( &attrs->an_name );
+ }
+ attrs->an_oc = oc;
+ }
+ if( oc != NULL ) {
+ if ( oc == slap_schema.si_oc_extensibleObject ) {
+ /* extensibleObject allows the return of anything */
+ return 1;
+ }
+
+ 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;
+ }
+ }
+
+ if( oc->soc_allowed ) {
+ /* 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;
+ }
+ }
+
+ } else {
+ /* short-circuit this search next time around */
+ if (!slap_schema.si_at_undefined->sat_ad) {
+ const char *text;
+ slap_bv2undef_ad(&attrs->an_name,
+ &attrs->an_desc, &text);
+ } else {
+ attrs->an_desc =
+ slap_schema.si_at_undefined->sat_ad;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+int slap_str2undef_ad(
+ const char *str,
+ AttributeDescription **ad,
+ const char **text )
+{
+ struct berval bv;
+ bv.bv_val = (char *) str;
+ bv.bv_len = strlen( str );
+
+ return slap_bv2undef_ad( &bv, ad, text );