]> git.sur5r.net Git - openldap/commitdiff
added rdn_attrs: parses a rdn and returns types and values in two arrays (honors...
authorPierangelo Masarati <ando@openldap.org>
Fri, 6 Jul 2001 12:22:01 +0000 (12:22 +0000)
committerPierangelo Masarati <ando@openldap.org>
Fri, 6 Jul 2001 12:22:01 +0000 (12:22 +0000)
servers/slapd/dn.c

index b180ae1b45911b8fa259348bd74b566ef7fc8a0b..920b5d3d5e6eb79b4033ff4b6551f92a200e2722 100644 (file)
@@ -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;