Back to index

openldap  2.4.31
Functions
rule.c File Reference
#include <portable.h>
#include "rewrite-int.h"

Go to the source code of this file.

Functions

static int append_rule (struct rewrite_context *context, struct rewrite_rule *rule)
static int append_action (struct rewrite_action **pbase, struct rewrite_action *action)
static int destroy_action (struct rewrite_action **paction)
static void destroy_actions (struct rewrite_action *paction)
int rewrite_rule_compile (struct rewrite_info *info, struct rewrite_context *context, const char *pattern, const char *result, const char *flagstring)
int rewrite_rule_apply (struct rewrite_info *info, struct rewrite_op *op, struct rewrite_rule *rule, const char *arg, char **result)
int rewrite_rule_destroy (struct rewrite_rule **prule)

Function Documentation

static int append_action ( struct rewrite_action **  pbase,
struct rewrite_action action 
) [static]

Definition at line 52 of file rule.c.

{
       struct rewrite_action **pa;

       assert( pbase != NULL );
       assert( action != NULL );
       
       for ( pa = pbase; *pa != NULL; pa = &(*pa)->la_next );
       *pa = action;
       
       return REWRITE_SUCCESS;
}

Here is the caller graph for this function:

static int append_rule ( struct rewrite_context context,
struct rewrite_rule rule 
) [static]

Definition at line 29 of file rule.c.

{
       struct rewrite_rule *r;

       assert( context != NULL );
       assert( context->lc_rule != NULL );
       assert( rule != NULL );

       for ( r = context->lc_rule; r->lr_next != NULL; r = r->lr_next );
       r->lr_next = rule;
       rule->lr_prev = r;
       
       return REWRITE_SUCCESS;
}

Here is the caller graph for this function:

static int destroy_action ( struct rewrite_action **  paction) [static]

Definition at line 69 of file rule.c.

{
       struct rewrite_action       *action;

       assert( paction != NULL );
       assert( *paction != NULL );

       action = *paction;

       /* do something */
       switch ( action->la_type ) {
       case REWRITE_FLAG_GOTO:
       case REWRITE_FLAG_USER: {
              int *pi = (int *)action->la_args;

              if ( pi ) {
                     free( pi );
              }
              break;
       }

       default:
              break;
       }
       
       free( action );
       *paction = NULL;
       
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void destroy_actions ( struct rewrite_action paction) [static]

Definition at line 103 of file rule.c.

{
       struct rewrite_action *next;

       for (; paction; paction = next) {
              next = paction->la_next;
              destroy_action( &paction );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rewrite_rule_apply ( struct rewrite_info info,
struct rewrite_op op,
struct rewrite_rule rule,
const char *  arg,
char **  result 
)

Definition at line 395 of file rule.c.

{
       size_t nmatch = REWRITE_MAX_MATCH;
       regmatch_t match[ REWRITE_MAX_MATCH ];

       int rc = REWRITE_SUCCESS;

       char *string;
       int strcnt = 0;
       struct berval val = { 0, NULL };

       assert( info != NULL );
       assert( op != NULL );
       assert( rule != NULL );
       assert( arg != NULL );
       assert( result != NULL );

       *result = NULL;

       string = (char *)arg;
       
       /*
        * In case recursive match is required (default)
        */
recurse:;

       Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply"
                     " rule='%s' string='%s' [%d pass(es)]\n", 
                     rule->lr_pattern, string, strcnt + 1 );
       
       op->lo_num_passes++;

       rc = regexec( &rule->lr_regex, string, nmatch, match, 0 );
       if ( rc != 0 ) {
              if ( *result == NULL && string != arg ) {
                     free( string );
              }

              /*
               * No match is OK; *result = NULL means no match
               */
              return REWRITE_REGEXEC_OK;
       }

       rc = rewrite_subst_apply( info, op, rule->lr_subst, string,
                     match, &val );

       *result = val.bv_val;
       val.bv_val = NULL;
       if ( string != arg ) {
              free( string );
              string = NULL;
       }

       if ( rc != REWRITE_REGEXEC_OK ) {
              return rc;
       }

       if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE 
                     && op->lo_num_passes < info->li_max_passes
                     && ++strcnt < rule->lr_max_passes ) {
              string = *result;

              goto recurse;
       }

       return REWRITE_REGEXEC_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rewrite_rule_compile ( struct rewrite_info info,
struct rewrite_context context,
const char *  pattern,
const char *  result,
const char *  flagstring 
)

Definition at line 118 of file rule.c.

{
       int flags = REWRITE_REGEX_EXTENDED | REWRITE_REGEX_ICASE;
       int mode = REWRITE_RECURSE;
       int max_passes;

       struct rewrite_rule *rule = NULL;
       struct rewrite_subst *subst = NULL;
       struct rewrite_action *action = NULL, *first_action = NULL;

       const char *p;

       assert( info != NULL );
       assert( context != NULL );
       assert( pattern != NULL );
       assert( result != NULL );
       /*
        * A null flagstring should be allowed
        */

       max_passes = info->li_max_passes_per_rule;

       /*
        * Take care of substitution string
        */
       subst = rewrite_subst_compile( info, result );
       if ( subst == NULL ) {
              return REWRITE_ERR;
       }

       /*
        * Take care of flags
        */
       for ( p = flagstring; p[ 0 ] != '\0'; p++ ) {
              switch( p[ 0 ] ) {
                     
              /*
               * REGEX flags
               */
              case REWRITE_FLAG_HONORCASE:              /* 'C' */
                     /*
                      * Honor case (default is case insensitive)
                      */
                     flags &= ~REWRITE_REGEX_ICASE;
                     break;
                     
              case REWRITE_FLAG_BASICREGEX:             /* 'R' */
                     /*
                      * Use POSIX Basic Regular Expression syntax
                      * instead of POSIX Extended Regular Expression 
                      * syntax (default)
                      */
                     flags &= ~REWRITE_REGEX_EXTENDED;
                     break;
                     
              /*
               * Execution mode flags
               */
              case REWRITE_FLAG_EXECONCE:               /* ':' */
                     /*
                      * Apply rule once only
                      */
                     mode &= ~REWRITE_RECURSE;
                     mode |= REWRITE_EXEC_ONCE;
                     break;
              
              /*
               * Special action flags
               */
              case REWRITE_FLAG_STOP:                   /* '@' */
                     /*
                      * Bail out after applying rule
                      */
                     action = calloc( sizeof( struct rewrite_action ), 1 );
                     if ( action == NULL ) {
                            goto fail;
                     }

                     action->la_type = REWRITE_ACTION_STOP;
                     break;
                     
              case REWRITE_FLAG_UNWILLING:              /* '#' */
                     /*
                      * Matching objs will be marked as gone!
                      */
                     action = calloc( sizeof( struct rewrite_action ), 1 );
                     if ( action == NULL ) {
                            goto fail;
                     }
                     
                     mode &= ~REWRITE_RECURSE;
                     mode |= REWRITE_EXEC_ONCE;
                     action->la_type = REWRITE_ACTION_UNWILLING;
                     break;

              case REWRITE_FLAG_GOTO:                          /* 'G' */
                     /*
                      * After applying rule, jump N rules
                      */

              case REWRITE_FLAG_USER: {                 /* 'U' */
                     /*
                      * After applying rule, return user-defined
                      * error code
                      */
                     char *next = NULL;
                     int *d;
                     
                     if ( p[ 1 ] != '{' ) {
                            goto fail;
                     }

                     d = malloc( sizeof( int ) );
                     if ( d == NULL ) {
                            goto fail;
                     }

                     d[ 0 ] = strtol( &p[ 2 ], &next, 0 );
                     if ( next == &p[ 2 ] || next[0] != '}' ) {
                            free( d );
                            goto fail;
                     }

                     action = calloc( sizeof( struct rewrite_action ), 1 );
                     if ( action == NULL ) {
                            free( d );
                            goto fail;
                     }
                     switch ( p[ 0 ] ) {
                     case REWRITE_FLAG_GOTO:
                            action->la_type = REWRITE_ACTION_GOTO;
                            break;

                     case REWRITE_FLAG_USER:
                            action->la_type = REWRITE_ACTION_USER;
                            break;

                     default:
                            assert(0);
                     }

                     action->la_args = (void *)d;

                     p = next;     /* p is incremented by the for ... */
              
                     break;
              }

              case REWRITE_FLAG_MAX_PASSES: {                  /* 'U' */
                     /*
                      * Set the number of max passes per rule
                      */
                     char *next = NULL;
                     
                     if ( p[ 1 ] != '{' ) {
                            goto fail;
                     }

                     max_passes = strtol( &p[ 2 ], &next, 0 );
                     if ( next == &p[ 2 ] || next[0] != '}' ) {
                            goto fail;
                     }

                     if ( max_passes < 1 ) {
                            /* FIXME: nonsense ... */
                            max_passes = 1;
                     }

                     p = next;     /* p is incremented by the for ... */
              
                     break;
              }

              case REWRITE_FLAG_IGNORE_ERR:               /* 'I' */
                     /*
                      * Ignore errors!
                      */
                     action = calloc( sizeof( struct rewrite_action ), 1 );
                     if ( action == NULL ) {
                            goto fail;
                     }
                     
                     action->la_type = REWRITE_ACTION_IGNORE_ERR;
                     break;
                     
              /*
               * Other flags ...
               */
              default:
                     /*
                      * Unimplemented feature (complain only)
                      */
                     break;
              }
              
              /*
               * Stupid way to append to a list ...
               */
              if ( action != NULL ) {
                     append_action( &first_action, action );
                     action = NULL;
              }
       }
       
       /*
        * Finally, rule allocation
        */
       rule = calloc( sizeof( struct rewrite_rule ), 1 );
       if ( rule == NULL ) {
              goto fail;
       }
       
       /*
        * REGEX compilation (luckily I don't need to take care of this ...)
        */
       if ( regcomp( &rule->lr_regex, ( char * )pattern, flags ) != 0 ) {
              goto fail;
       }
       
       /*
        * Just to remember them ...
        */
       rule->lr_pattern = strdup( pattern );
       rule->lr_subststring = strdup( result );
       rule->lr_flagstring = strdup( flagstring );
       if ( rule->lr_pattern == NULL
              || rule->lr_subststring == NULL
              || rule->lr_flagstring == NULL )
       {
              goto fail;
       }
       
       /*
        * Load compiled data into rule
        */
       rule->lr_subst = subst;

       /*
        * Set various parameters
        */
       rule->lr_flags = flags;            /* don't really need any longer ... */
       rule->lr_mode = mode;
       rule->lr_max_passes = max_passes;
       rule->lr_action = first_action;
       
       /*
        * Append rule at the end of the rewrite context
        */
       append_rule( context, rule );

       return REWRITE_SUCCESS;

fail:
       if ( rule ) {
              if ( rule->lr_pattern ) free( rule->lr_pattern );
              if ( rule->lr_subststring ) free( rule->lr_subststring );
              if ( rule->lr_flagstring ) free( rule->lr_flagstring );
              free( rule );
       }
       destroy_actions( first_action );
       free( subst );
       return REWRITE_ERR;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int rewrite_rule_destroy ( struct rewrite_rule **  prule)

Definition at line 471 of file rule.c.

{
       struct rewrite_rule *rule;

       assert( prule != NULL );
       assert( *prule != NULL );

       rule = *prule;

       if ( rule->lr_pattern ) {
              free( rule->lr_pattern );
              rule->lr_pattern = NULL;
       }

       if ( rule->lr_subststring ) {
              free( rule->lr_subststring );
              rule->lr_subststring = NULL;
       }

       if ( rule->lr_flagstring ) {
              free( rule->lr_flagstring );
              rule->lr_flagstring = NULL;
       }

       if ( rule->lr_subst ) {
              rewrite_subst_destroy( &rule->lr_subst );
       }

       regfree( &rule->lr_regex );

       destroy_actions( rule->lr_action );

       free( rule );
       *prule = NULL;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: