+ if ( ber_printf( ber, /*"{{"*/ "N}N}" ) == -1 ) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+put_vrFilter( BerElement *ber, const char *str_in )
+{
+ int rc;
+ char *freeme;
+ char *str;
+ char *next;
+ int parens, balance, escape;
+
+ /*
+ * A ValuesReturnFilter looks like this:
+ *
+ * ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
+ * SimpleFilterItem ::= CHOICE {
+ * equalityMatch [3] AttributeValueAssertion,
+ * substrings [4] SubstringFilter,
+ * greaterOrEqual [5] AttributeValueAssertion,
+ * lessOrEqual [6] AttributeValueAssertion,
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion,
+ * extensibleMatch [9] SimpleMatchingAssertion -- LDAPv3
+ * }
+ *
+ * SubstringFilter ::= SEQUENCE {
+ * type AttributeType,
+ * SEQUENCE OF CHOICE {
+ * initial [0] IA5String,
+ * any [1] IA5String,
+ * final [2] IA5String
+ * }
+ * }
+ *
+ * SimpleMatchingAssertion ::= SEQUENCE { -- LDAPv3
+ * matchingRule [1] MatchingRuleId OPTIONAL,
+ * type [2] AttributeDescription OPTIONAL,
+ * matchValue [3] AssertionValue }
+ */
+
+#ifdef NEW_LOGGING
+ LDAP_LOG ( FILTER, ARGS, "ldap_pvt_put_vrFilter: \"%s\"\n",
+ str_in, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: \"%s\"\n", str_in, 0, 0 );
+#endif
+
+ freeme = LDAP_STRDUP( str_in );
+ if( freeme == NULL ) return LDAP_NO_MEMORY;
+ str = freeme;
+
+ parens = 0;
+ while ( *str ) {
+ switch ( *str ) {
+ case '(': /*')'*/
+ str++;
+ parens++;
+
+ /* skip spaces */
+ while( LDAP_SPACE( *str ) ) str++;
+
+ switch ( *str ) {
+ case '(':
+ if ( (next = find_right_paren( str )) == NULL ) {
+ rc = -1;
+ goto done;
+ }
+
+ *next = '\0';
+
+ if ( put_vrFilter_list( ber, str ) == -1 ) {
+ rc = -1;
+ goto done;
+ }
+
+ /* close the '(' */
+ *next++ = ')';
+
+ str = next;
+
+ parens--;
+ break;
+
+
+ default:
+#ifdef NEW_LOGGING
+ LDAP_LOG ( FILTER, DETAIL1,
+ "put_vrFilter: simple\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: simple\n",
+ 0, 0, 0 );
+#endif
+
+ balance = 1;
+ escape = 0;
+ next = str;
+
+ while ( *next && balance ) {
+ if ( escape == 0 ) {
+ if ( *next == '(' ) {
+ balance++;
+ } else if ( *next == ')' ) {
+ balance--;
+ }
+ }
+
+ if ( *next == '\\' && ! escape ) {
+ escape = 1;
+ } else {
+ escape = 0;
+ }
+
+ if ( balance ) next++;
+ }
+
+ if ( balance != 0 ) {
+ rc = -1;
+ goto done;
+ }
+
+ *next = '\0';
+
+ if ( put_simple_vrFilter( ber, str ) == -1 ) {
+ rc = -1;
+ goto done;
+ }
+
+ *next++ = /*'('*/ ')';
+
+ str = next;
+ parens--;
+ break;
+ }
+ break;
+
+ case /*'('*/ ')':
+#ifdef NEW_LOGGING
+ LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: end\n", 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
+ 0, 0, 0 );
+#endif
+ if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
+ rc = -1;
+ goto done;
+ }
+ str++;
+ parens--;
+ break;
+
+ case ' ':
+ str++;
+ break;
+
+ default: /* assume it's a simple type=value filter */
+#ifdef NEW_LOGGING
+ LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: default\n",
+ 0, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
+ 0, 0, 0 );
+#endif
+ next = strchr( str, '\0' );
+ if ( put_simple_filter( ber, str ) == -1 ) {
+ rc = -1;
+ goto done;
+ }
+ str = next;
+ break;
+ }
+ }
+
+ rc = parens ? -1 : 0;
+
+done:
+ LDAP_FREE( freeme );
+ return rc;
+}
+
+int
+ldap_put_vrFilter( BerElement *ber, const char *str_in )
+{
+ int rc =0;
+
+ if ( ber_printf( ber, "{" /*"}"*/ ) == -1 ) {
+ rc = -1;
+ }
+
+ rc = put_vrFilter( ber, str_in );
+
+ if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) {
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static int
+put_vrFilter_list( BerElement *ber, char *str )
+{
+ char *next = NULL;
+ char save;
+
+#ifdef NEW_LOGGING
+ LDAP_LOG ( FILTER, ARGS, "put_vrFilter_list \"%s\"\n", str, 0, 0 );
+#else
+ Debug( LDAP_DEBUG_TRACE, "put_vrFilter_list \"%s\"\n",
+ str, 0, 0 );
+#endif
+
+ while ( *str ) {
+ while ( *str && LDAP_SPACE( (unsigned char) *str ) ) {
+ str++;
+ }
+ if ( *str == '\0' ) break;
+
+ if ( (next = find_right_paren( str + 1 )) == NULL ) {
+ return -1;
+ }
+ save = *++next;
+
+ /* now we have "(filter)" with str pointing to it */
+ *next = '\0';
+ if ( put_vrFilter( ber, str ) == -1 ) return -1;
+ *next = save;
+ str = next;
+ }