+ if ( bv.bv_val[ 0 ] == '/' ) {
+ group_oc.bv_val = &bv.bv_val[ 1 ];
+
+ member_at.bv_val = strchr( group_oc.bv_val, '/' );
+ if ( member_at.bv_val ) {
+ group_oc.bv_len = member_at.bv_val - group_oc.bv_val;
+ member_at.bv_val++;
+ member_at.bv_len = group_dn.bv_val - member_at.bv_val;
+
+ } else {
+ group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
+ BER_BVSTR( &member_at, "member" );
+ }
+
+ } else {
+ BER_BVSTR( &group_oc, "groupOfNames" );
+ }
+ group_dn.bv_val++;
+ group_dn.bv_len = uri->bv_len - ( group_dn.bv_val - uri->bv_val );
+
+ rc = dnNormalize( 0, NULL, NULL, &group_dn, nbase, op->o_tmpmemctx );
+ if ( rc != LDAP_SUCCESS ) {
+ *scope = -1;
+ return rc;
+ }
+ *scope = LDAP_X_SCOPE_GROUP;
+
+ /* FIXME: caller needs to add value of member attribute
+ * and close brackets twice */
+ fstr->bv_len = STRLENOF( "(&(objectClass=)(=" /* )) */ )
+ + group_oc.bv_len + member_at.bv_len;
+ fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
+
+ tmp = lutil_strncopy( fstr->bv_val, "(&(objectClass=" /* )) */ ,
+ STRLENOF( "(&(objectClass=" /* )) */ ) );
+ tmp = lutil_strncopy( tmp, group_oc.bv_val, group_oc.bv_len );
+ tmp = lutil_strncopy( tmp, /* ( */ ")(" /* ) */ ,
+ STRLENOF( /* ( */ ")(" /* ) */ ) );
+ tmp = lutil_strncopy( tmp, member_at.bv_val, member_at.bv_len );
+ tmp = lutil_strncopy( tmp, "=", STRLENOF( "=" ) );
+
+ return rc;
+ }
+
+ /*
+ * ldap:///<base>??<scope>?<filter>
+ * <scope> ::= {base|one|subtree}
+ *
+ * <scope> defaults to "base"
+ * <base> must pass DN normalization
+ * <filter> must pass str2filter()
+ */