2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2003 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
16 * This work was initially developed by Pierangelo Masarati for
17 * inclusion in OpenLDAP Software.
22 #include "rewrite-int.h"
25 * Compiles a substitution pattern
27 struct rewrite_subst *
28 rewrite_subst_compile(
29 struct rewrite_info *info,
34 struct berval *subs = NULL, *tmps;
35 struct rewrite_submatch *submatch = NULL;
37 struct rewrite_subst *s = NULL;
39 const char *begin, *p;
42 assert( info != NULL );
43 assert( result != NULL );
46 * Take care of substitution string
48 for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) {
51 * Keep only single escapes '%'
53 if ( p[ 0 ] != REWRITE_SUBMATCH_ESCAPE ) {
57 if ( p[ 1 ] == REWRITE_SUBMATCH_ESCAPE ) {
58 /* Pull &p[1] over p, including the trailing '\0' */
59 AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) );
63 tmps = ( struct berval * )realloc( subs,
64 sizeof( struct berval )*( nsub + 1 ) );
72 * I think an `if l > 0' at runtime is better outside than
73 * inside a function call ...
78 subs[ nsub ].bv_len = l;
79 subs[ nsub ].bv_val = malloc( l + 1 );
80 if ( subs[ nsub ].bv_val == NULL ) {
83 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
84 subs[ nsub ].bv_val[ l ] = '\0';
86 subs[ nsub ].bv_val = NULL;
87 subs[ nsub ].bv_len = 0;
91 * Substitution pattern
93 if ( isdigit( (unsigned char) p[ 1 ] ) ) {
94 struct rewrite_submatch *tmpsm;
98 * Add a new value substitution scheme
101 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
102 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
103 if ( tmpsm == NULL ) {
108 submatch[ nsub ].ls_submatch = d;
111 * If there is no argument, use default
112 * (substitute substring as is)
114 if ( p[ 2 ] != '{' ) {
115 submatch[ nsub ].ls_type =
116 REWRITE_SUBMATCH_ASIS;
117 submatch[ nsub ].ls_map = NULL;
121 struct rewrite_map *map;
123 submatch[ nsub ].ls_type =
124 REWRITE_SUBMATCH_XMAP;
126 map = rewrite_xmap_parse( info,
132 submatch[ nsub ].ls_map = map;
139 } else if ( p[ 1 ] == '{' ) {
140 struct rewrite_map *map;
141 struct rewrite_submatch *tmpsm;
143 map = rewrite_map_parse( info, p + 2, &begin );
151 * Add a new value substitution scheme
153 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
154 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
155 if ( tmpsm == NULL ) {
160 submatch[ nsub ].ls_type =
161 REWRITE_SUBMATCH_MAP_W_ARG;
162 submatch[ nsub ].ls_map = map;
169 * Last part of string
171 tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
172 if ( tmps == NULL ) {
174 * XXX need to free the value subst stuff!
183 subs[ nsub ].bv_len = l;
184 subs[ nsub ].bv_val = malloc( l + 1 );
185 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
186 subs[ nsub ].bv_val[ l ] = '\0';
188 subs[ nsub ].bv_val = NULL;
189 subs[ nsub ].bv_len = 0;
192 s = calloc( sizeof( struct rewrite_subst ), 1 );
198 s->lt_subs_len = subs_len;
200 s->lt_num_submatch = nsub;
201 s->lt_submatch = submatch;
207 * Copies the match referred to by submatch and fetched in string by match.
208 * Helper for rewrite_rule_apply.
212 struct rewrite_submatch *submatch,
214 const regmatch_t *match,
221 assert( submatch != NULL );
222 assert( submatch->ls_type == REWRITE_SUBMATCH_ASIS
223 || submatch->ls_type == REWRITE_SUBMATCH_XMAP );
224 assert( string != NULL );
225 assert( match != NULL );
226 assert( val != NULL );
227 assert( val->bv_val == NULL );
229 c = submatch->ls_submatch;
230 s = string + match[ c ].rm_so;
231 l = match[ c ].rm_eo - match[ c ].rm_so;
234 val->bv_val = malloc( l + 1 );
235 if ( val->bv_val == NULL ) {
239 AC_MEMCPY( val->bv_val, s, l );
240 val->bv_val[ l ] = '\0';
242 return REWRITE_SUCCESS;
246 * Substitutes a portion of rewritten string according to substitution
247 * pattern using submatches
251 struct rewrite_info *info,
252 struct rewrite_op *op,
253 struct rewrite_subst *subst,
255 const regmatch_t *match,
259 struct berval *submatch = NULL;
262 int rc = REWRITE_REGEXEC_OK;
264 assert( info != NULL );
265 assert( op != NULL );
266 assert( subst != NULL );
267 assert( string != NULL );
268 assert( match != NULL );
269 assert( val != NULL );
271 assert( val->bv_val == NULL );
277 * Prepare room for submatch expansion
279 if ( subst->lt_num_submatch > 0 ) {
280 submatch = calloc( sizeof( struct berval ),
281 subst->lt_num_submatch );
282 if ( submatch == NULL ) {
283 return REWRITE_REGEXEC_ERR;
288 * Resolve submatches (simple subst, map expansion and so).
290 for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
291 struct berval key = { 0, NULL };
293 submatch[ n ].bv_val = NULL;
298 switch ( subst->lt_submatch[ n ].ls_type ) {
299 case REWRITE_SUBMATCH_ASIS:
300 case REWRITE_SUBMATCH_XMAP:
301 rc = submatch_copy( &subst->lt_submatch[ n ],
302 string, match, &key );
303 if ( rc != REWRITE_SUCCESS ) {
304 rc = REWRITE_REGEXEC_ERR;
309 case REWRITE_SUBMATCH_MAP_W_ARG:
310 switch ( subst->lt_submatch[ n ].ls_map->lm_type ) {
311 case REWRITE_MAP_GET_OP_VAR:
312 case REWRITE_MAP_GET_SESN_VAR:
313 case REWRITE_MAP_GET_PARAM:
314 rc = REWRITE_SUCCESS;
318 rc = rewrite_subst_apply( info, op,
319 subst->lt_submatch[ n ].ls_map->lm_subst,
320 string, match, &key);
323 if ( rc != REWRITE_SUCCESS ) {
324 rc = REWRITE_REGEXEC_ERR;
330 Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 );
335 if ( rc != REWRITE_SUCCESS ) {
336 rc = REWRITE_REGEXEC_ERR;
343 switch ( subst->lt_submatch[ n ].ls_type ) {
344 case REWRITE_SUBMATCH_ASIS:
346 rc = REWRITE_SUCCESS;
349 case REWRITE_SUBMATCH_XMAP:
350 rc = rewrite_xmap_apply( info, op,
351 subst->lt_submatch[ n ].ls_map,
352 &key, &submatch[ n ] );
357 case REWRITE_SUBMATCH_MAP_W_ARG:
358 rc = rewrite_map_apply( info, op,
359 subst->lt_submatch[ n ].ls_map,
360 &key, &submatch[ n ] );
367 * When implemented, this might return the
368 * exit status of a rewrite context,
369 * which may include a stop, or an
370 * unwilling to perform
376 if ( rc != REWRITE_SUCCESS ) {
377 rc = REWRITE_REGEXEC_ERR;
381 * Increment the length of the resulting string
383 l += submatch[ n ].bv_len;
387 * Alloc result buffer
389 l += subst->lt_subs_len;
390 res = malloc( l + 1 );
392 rc = REWRITE_REGEXEC_ERR;
397 * Apply submatches (possibly resolved thru maps)
399 for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
400 if ( subst->lt_subs[ n ].bv_val != NULL ) {
401 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
402 subst->lt_subs[ n ].bv_len );
403 cl += subst->lt_subs[ n ].bv_len;
405 AC_MEMCPY( res + cl, submatch[ n ].bv_val,
406 submatch[ n ].bv_len );
407 cl += submatch[ n ].bv_len;
409 if ( subst->lt_subs[ n ].bv_val != NULL ) {
410 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
411 subst->lt_subs[ n ].bv_len );
412 cl += subst->lt_subs[ n ].bv_len;
421 for ( ; --n >= 0; ) {
422 if ( submatch[ n ].bv_val ) {
423 free( submatch[ n ].bv_val );
436 rewrite_subst_destroy(
437 struct rewrite_subst **psubst
441 struct rewrite_subst *subst;
448 for ( n = 0; n < subst->lt_num_submatch; n++ ) {
449 if ( subst->lt_subs[ n ].bv_val ) {
450 free( subst->lt_subs[ n ].bv_val );
451 subst->lt_subs[ n ].bv_val = NULL;
454 switch ( subst->lt_submatch[ n ].ls_type ) {
455 case REWRITE_SUBMATCH_ASIS:
458 case REWRITE_SUBMATCH_XMAP:
459 rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map );
462 case REWRITE_SUBMATCH_MAP_W_ARG:
463 rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map );
471 free( subst->lt_submatch );
472 subst->lt_submatch = NULL;
475 if ( subst->lt_subs[ n ].bv_val ) {
476 free( subst->lt_subs[ n ].bv_val );
477 subst->lt_subs[ n ].bv_val = NULL;
480 free( subst->lt_subs );
481 subst->lt_subs = NULL;