Пример #1
0
int
ldap_pvt_put_filter( BerElement *ber, const char *str_in )
{
	int rc;
	char	*freeme;
	char	*str;
	char	*next;
	int	parens, balance, escape;

	/*
	 * A Filter looks like this (RFC 4511 as extended by RFC 4526):
	 *     Filter ::= CHOICE {
	 *         and             [0]     SET SIZE (0..MAX) OF filter Filter,
	 *         or              [1]     SET SIZE (0..MAX) OF filter Filter,
	 *         not             [2]     Filter,
	 *         equalityMatch   [3]     AttributeValueAssertion,
	 *         substrings      [4]     SubstringFilter,
	 *         greaterOrEqual  [5]     AttributeValueAssertion,
	 *         lessOrEqual     [6]     AttributeValueAssertion,
	 *         present         [7]     AttributeDescription,
	 *         approxMatch     [8]     AttributeValueAssertion,
	 *         extensibleMatch [9]     MatchingRuleAssertion,
	 *         ... }
	 *
	 *     SubstringFilter ::= SEQUENCE {
	 *         type         AttributeDescription,
	 *         substrings   SEQUENCE SIZE (1..MAX) OF substring CHOICE {
	 *             initial          [0] AssertionValue, -- only once
	 *             any              [1] AssertionValue,
	 *             final            [2] AssertionValue  -- only once
	 *             }
	 *         }
	 *
	 *	   MatchingRuleAssertion ::= SEQUENCE {
	 *         matchingRule    [1] MatchingRuleId OPTIONAL,
	 *         type            [2] AttributeDescription OPTIONAL,
	 *         matchValue      [3] AssertionValue,
	 *         dnAttributes    [4] BOOLEAN DEFAULT FALSE }
	 *
	 * Note: tags in a CHOICE are always explicit
	 */

	Debug( LDAP_DEBUG_TRACE, "put_filter: \"%s\"\n", str_in, 0, 0 );

	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 '&':
				Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_AND, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '|':
				Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_OR, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '!':
				Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_NOT, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '(':
				rc = -1;
				goto done;

			default:
				Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
				    0, 0, 0 );

				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_filter( ber, str ) == -1 ) {
					rc = -1;
					goto done;
				}

				*next++ = /*'('*/ ')';

				str = next;
				parens--;
				break;
			}
			break;

		case /*'('*/ ')':
			Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
				0, 0, 0 );
			if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
				rc = -1;
				goto done;
			}
			str++;
			parens--;
			break;

		case ' ':
			str++;
			break;

		default:	/* assume it's a simple type=value filter */
			Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
				0, 0, 0 );
			next = strchr( str, '\0' );
			if ( put_simple_filter( ber, str ) == -1 ) {
				rc = -1;
				goto done;
			}
			str = next;
			break;
		}
		if ( !parens )
			break;
	}

	rc = ( parens || *str ) ? -1 : 0;

done:
	LDAP_FREE( freeme );
	return rc;
}
Пример #2
0
static int
put_filter( BerElement *ber, char *str )
{
	char	*next, *tmp, *s, *d;
	int	parens, balance, escape, gotescape;

	/*
	 * A Filter looks like this:
	 *      Filter ::= CHOICE {
	 *              and             [0]     SET OF Filter,
	 *              or              [1]     SET OF Filter,
	 *              not             [2]     Filter,
	 *              equalityMatch   [3]     AttributeValueAssertion,
	 *              substrings      [4]     SubstringFilter,
	 *              greaterOrEqual  [5]     AttributeValueAssertion,
	 *              lessOrEqual     [6]     AttributeValueAssertion,
	 *              present         [7]     AttributeType,,
	 *              approxMatch     [8]     AttributeValueAssertion
	 *      }
	 *
	 *      SubstringFilter ::= SEQUENCE {
	 *              type               AttributeType,
	 *              SEQUENCE OF CHOICE {
	 *                      initial          [0] IA5String,
	 *                      any              [1] IA5String,
	 *                      final            [2] IA5String
	 *              }
	 *      }
	 * Note: tags in a choice are always explicit
	 */

	Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );

	gotescape = parens = 0;
	while ( *str ) {
		switch ( *str ) {
		case '(':
			str++;
			parens++;
			switch ( *str ) {
			case '&':
				Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
				    0, 0, 0 );

				if ( (str = put_complex_filter( ber, str,
				    LDAP_FILTER_AND, 0 )) == NULL )
					return( -1 );

				parens--;
				break;

			case '|':
				Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
				    0, 0, 0 );

				if ( (str = put_complex_filter( ber, str,
				    LDAP_FILTER_OR, 0 )) == NULL )
					return( -1 );

				parens--;
				break;

			case '!':
				Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
				    0, 0, 0 );

				if ( (str = put_complex_filter( ber, str,
				    LDAP_FILTER_NOT, 1 )) == NULL )
					return( -1 );

				parens--;
				break;

			default:
				Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
				    0, 0, 0 );

				balance = 1;
				escape = 0;
				next = str;
				while ( *next && balance ) {
					if ( escape == 0 ) {
						if ( *next == '(' )
							balance++;
						else if ( *next == ')' )
							balance--;
					}
					if ( *next == '\\' && ! escape )
						gotescape = escape = 1;
					else
						escape = 0;
					if ( balance )
						next++;
				}
				if ( balance != 0 )
					return( -1 );

				*next = '\0';
				tmp = strdup( str );
				if ( gotescape ) {
					escape = 0;
					for ( s = d = tmp; *s; s++ ) {
						if ( *s != '\\' || escape ) {
							*d++ = *s;
							escape = 0;
						} else {
							escape = 1;
						}
					}
					*d = '\0';
				}
				if ( put_simple_filter( ber, tmp ) == -1 ) {
					free( tmp );
					return( -1 );
				}
				free( tmp );
				*next++ = ')';
				str = next;
				parens--;
				break;
			}
			break;

		case ')':
			Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
			    0 );
			if ( ber_printf( ber, "]" ) == -1 )
				return( -1 );
			str++;
			parens--;
			break;

		case ' ':
			str++;
			break;

		default:	/* assume it's a simple type=value filter */
			Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
			    0 );
			next = strchr( str, '\0' );
			tmp = strdup( str );
			if ( strchr( tmp, '\\' ) != NULL ) {
				escape = 0;
				for ( s = d = tmp; *s; s++ ) {
					if ( *s != '\\' || escape ) {
						*d++ = *s;
						escape = 0;
					} else {
						escape = 1;
					}
				}
				*d = '\0';
			}
			if ( put_simple_filter( ber, tmp ) == -1 ) {
				free( tmp );
				return( -1 );
			}
			free( tmp );
			str = next;
			break;
		}
	}

	return( parens ? -1 : 0 );
}