From 38ce12a6f630036df21d9d82a337288f1c1028fc Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Fri, 6 Jul 2001 12:22:01 +0000 Subject: [PATCH] added rdn_attrs: parses a rdn and returns types and values in two arrays (honors '+' separator according to RFC 2253) --- servers/slapd/dn.c | 208 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c index b180ae1b45..920b5d3d5e 100644 --- a/servers/slapd/dn.c +++ b/servers/slapd/dn.c @@ -486,6 +486,214 @@ rdn_attr_value( const char * rdn ) } +/* rdn_attrs: + * + * Given a string (i.e. an rdn) of the form: + * "attribute_type=attribute_value[+attribute_type=attribute_value[...]]" + * this function stores the types of the attributes in ptypes, that is the + * array of strings "attribute_type" which is placed in newly allocated + * memory, and the values of the attributes in pvalues, that is the + * array of strings "attribute_value" which is placed in newly allocated + * memory. Returns 1 on success, 0 on failure. + * + * note: got part of the code from dn_validate + */ +int +rdn_attrs( const char * rdn_in, char ***ptypes, char ***pvalues) +{ + char *start, *end, *s; + int state, gotesc, t = 0, v = 0; + char *dn = ch_strdup( rdn_in ); + + *ptypes = NULL; + *pvalues = NULL; + + gotesc = 0; + state = B4LEADTYPE; + for ( start = end = s = dn; *s; s++ ) { + switch ( state ) { + case B4LEADTYPE: + case B4TYPE: + if ( OID_LEADCHAR(*s) ) { + state = INOIDTYPE; + start = end; + *end++ = *s; + } else if ( ATTR_LEADCHAR(*s) ) { + state = INKEYTYPE; + start = end; + *end++ = *s; + } else if ( ! ASCII_SPACE( *s ) ) { + goto failure; + state = INKEYTYPE; + *end++ = *s; + } + break; + + case INOIDTYPE: + if ( OID_CHAR(*s) ) { + *end++ = *s; + } else if ( *s == '=' ) { + state = B4VALUE; + charray_add_n( ptypes, start, ( end - start ) ); + t++; + *end++ = *s; + } else if ( ASCII_SPACE( *s ) ) { + state = B4EQUAL; + charray_add_n( ptypes, start, ( end - start ) ); + t++; + } else { + *end++ = *s; + goto failure; + } + break; + + case INKEYTYPE: + if ( ATTR_CHAR(*s) ) { + *end++ = *s; + } else if ( *s == '=' ) { + state = B4VALUE; + charray_add_n( ptypes, start, ( end - start ) ); + t++; + *end++ = *s; + } else if ( ASCII_SPACE( *s ) ) { + state = B4EQUAL; + charray_add_n( ptypes, start, ( end - start ) ); + t++; + } else { + *end++ = *s; + goto failure; + } + break; + + case B4EQUAL: + if ( *s == '=' ) { + state = B4VALUE; + *end++ = *s; + } else if ( ! ASCII_SPACE( *s ) ) { + /* not a valid dn - but what can we do here? */ + *end++ = *s; + goto failure; + } + break; + + case B4VALUE: + if ( *s == '"' ) { + state = INQUOTEDVALUE; + start = end; + *end++ = *s; + } else if ( ! ASCII_SPACE( *s ) ) { + state = INVALUE; + start = end; + *end++ = *s; + } + break; + + case INVALUE: + if ( !gotesc && RDN_SEPARATOR( *s ) ) { + while ( ASCII_SPACE( *(end - 1) ) ) + end--; + state = B4TYPE; + if ( RDN_ATTRTYPEANDVALUE_SEPARATOR( *s ) ) { + if ( ++v != t ) { + goto failure; + } + charray_add_n( pvalues, start, ( end - start ) ); + *end++ = *s; + } else { + /* not a rdn! */ + goto failure; + } + } else if ( gotesc && !RDN_NEEDSESCAPE( *s ) && + !RDN_SEPARATOR( *s ) ) { + *--end = *s; + end++; + } else if( !ASCII_SPACE( *s ) || !ASCII_SPACE( *(end - 1) ) ) { + *end++ = *s; + } + break; + + case INQUOTEDVALUE: + if ( !gotesc && *s == '"' ) { + state = B4SEPARATOR; + *end++ = *s; + } else if ( gotesc && !RDN_NEEDSESCAPE( *s ) ) { + *--end = *s; + end++; + } else if( !ASCII_SPACE( *s ) || !ASCII_SPACE( *(end - 1) ) ) { + *end++ = *s; + } + break; + + case B4SEPARATOR: + if ( RDN_SEPARATOR( *s ) ) { + state = B4TYPE; + if ( RDN_ATTRTYPEANDVALUE_SEPARATOR( *s ) ) { + if ( ++v != t ) { + goto failure; + } + charray_add_n( pvalues, start, ( end - start ) ); + *end++ = *s; + } else { + /* not a rdn! */ + goto failure; + } + } else if ( !ASCII_SPACE( *s ) ) { + goto failure; + } + break; + + default: +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "rdn_attrs: unknown state %d for rdn \"%s\".\n", + state, dn_in )); +#else + Debug( LDAP_DEBUG_ANY, + "rdn_attrs - unknown state %d\n", state, 0, 0 ); +#endif + goto failure; + } + + if ( *s == '\\' ) { + gotesc = 1; + } else { + gotesc = 0; + } + } + + if( gotesc ) { + /* shouldn't be left in escape */ + goto failure; + } + + /* check end state */ + switch( state ) { + case B4LEADTYPE: /* looking for first type */ + case B4SEPARATOR: /* looking for separator */ + case INVALUE: /* inside value */ + if ( ++v != t ) { + goto failure; + } + charray_add_n( pvalues, start, ( end - start ) ); + break; + default: + goto failure; + } + ch_free( dn ); + + return( 1 ); + +failure: + ch_free( dn ); + charray_free( *ptypes ); + *ptypes = NULL; + charray_free( *pvalues ); + *pvalues = NULL; + + return( 0 ); +} + + /* rdn_validate: * * 1 if rdn is a legal rdn; -- 2.39.5