1 /******************************************************************************
3 * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
6 * Permission is granted to anyone to use this software for any purpose
7 * on any computer system, and to alter it and redistribute it, subject
8 * to the following restrictions:
10 * 1. The author is not responsible for the consequences of use of this
11 * software, no matter how awful, even if they arise from flaws in it.
13 * 2. The origin of this software must not be misrepresented, either by
14 * explicit claim or by omission. Since few users ever read sources,
15 * credits should appear in the documentation.
17 * 3. Altered versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software. Since few users
19 * ever read sources, credits should appear in the documentation.
21 * 4. This notice may not be removed or altered.
23 ******************************************************************************/
27 #include "rewrite-int.h"
30 * Compiles a substitution pattern
32 struct rewrite_subst *
33 rewrite_subst_compile(
34 struct rewrite_info *info,
39 struct berval *subs = NULL, *tmps;
40 struct rewrite_submatch *submatch = NULL;
42 struct rewrite_subst *s = NULL;
44 const char *begin, *p;
47 assert( info != NULL );
48 assert( result != NULL );
51 * Take care of substitution string
53 for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) {
56 * Keep only single escapes '%'
58 if ( p[ 0 ] != REWRITE_SUBMATCH_ESCAPE ) {
62 if ( p[ 1 ] == REWRITE_SUBMATCH_ESCAPE ) {
63 /* Pull &p[1] over p, including the trailing '\0' */
64 AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) );
68 tmps = ( struct berval * )realloc( subs,
69 sizeof( struct berval )*( nsub + 1 ) );
77 * I think an `if l > 0' at runtime is better outside than
78 * inside a function call ...
83 subs[ nsub ].bv_len = l;
84 subs[ nsub ].bv_val = malloc( l + 1 );
85 if ( subs[ nsub ].bv_val == NULL ) {
88 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
89 subs[ nsub ].bv_val[ l ] = '\0';
91 subs[ nsub ].bv_val = NULL;
92 subs[ nsub ].bv_len = 0;
96 * Substitution pattern
98 if ( isdigit( (unsigned char) p[ 1 ] ) ) {
99 struct rewrite_submatch *tmpsm;
100 int d = p[ 1 ] - '0';
103 * Add a new value substitution scheme
106 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
107 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
108 if ( tmpsm == NULL ) {
113 submatch[ nsub ].ls_submatch = d;
116 * If there is no argument, use default
117 * (substitute substring as is)
119 if ( p[ 2 ] != '{' ) {
120 submatch[ nsub ].ls_type =
121 REWRITE_SUBMATCH_ASIS;
122 submatch[ nsub ].ls_map = NULL;
126 struct rewrite_map *map;
128 submatch[ nsub ].ls_type =
129 REWRITE_SUBMATCH_XMAP;
131 map = rewrite_xmap_parse( info,
137 submatch[ nsub ].ls_map = map;
144 } else if ( p[ 1 ] == '{' ) {
145 struct rewrite_map *map;
146 struct rewrite_submatch *tmpsm;
148 map = rewrite_map_parse( info, p + 2, &begin );
156 * Add a new value substitution scheme
158 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
159 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
160 if ( tmpsm == NULL ) {
165 submatch[ nsub ].ls_type =
166 REWRITE_SUBMATCH_MAP_W_ARG;
167 submatch[ nsub ].ls_map = map;
174 * Last part of string
176 tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
177 if ( tmps == NULL ) {
179 * XXX need to free the value subst stuff!
188 subs[ nsub ].bv_len = l;
189 subs[ nsub ].bv_val = malloc( l + 1 );
190 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
191 subs[ nsub ].bv_val[ l ] = '\0';
193 subs[ nsub ].bv_val = NULL;
194 subs[ nsub ].bv_len = 0;
197 s = calloc( sizeof( struct rewrite_subst ), 1 );
203 s->lt_subs_len = subs_len;
205 s->lt_num_submatch = nsub;
206 s->lt_submatch = submatch;
212 * Copies the match referred to by submatch and fetched in string by match.
213 * Helper for rewrite_rule_apply.
217 struct rewrite_submatch *submatch,
219 const regmatch_t *match,
226 assert( submatch != NULL );
227 assert( submatch->ls_type == REWRITE_SUBMATCH_ASIS
228 || submatch->ls_type == REWRITE_SUBMATCH_XMAP );
229 assert( string != NULL );
230 assert( match != NULL );
231 assert( val != NULL );
232 assert( val->bv_val == NULL );
234 c = submatch->ls_submatch;
235 s = string + match[ c ].rm_so;
236 l = match[ c ].rm_eo - match[ c ].rm_so;
239 val->bv_val = malloc( l + 1 );
240 if ( val->bv_val == NULL ) {
244 AC_MEMCPY( val->bv_val, s, l );
245 val->bv_val[ l ] = '\0';
247 return REWRITE_SUCCESS;
251 * Substitutes a portion of rewritten string according to substitution
252 * pattern using submatches
256 struct rewrite_info *info,
257 struct rewrite_op *op,
258 struct rewrite_subst *subst,
260 const regmatch_t *match,
264 struct berval *submatch = NULL;
267 int rc = REWRITE_REGEXEC_OK;
269 assert( info != NULL );
270 assert( op != NULL );
271 assert( subst != NULL );
272 assert( string != NULL );
273 assert( match != NULL );
274 assert( val != NULL );
276 assert( val->bv_val == NULL );
282 * Prepare room for submatch expansion
284 if ( subst->lt_num_submatch > 0 ) {
285 submatch = calloc( sizeof( struct berval ),
286 subst->lt_num_submatch );
287 if ( submatch == NULL ) {
288 return REWRITE_REGEXEC_ERR;
293 * Resolve submatches (simple subst, map expansion and so).
295 for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
296 struct berval key = { 0, NULL };
298 submatch[ n ].bv_val = NULL;
303 switch ( subst->lt_submatch[ n ].ls_type ) {
304 case REWRITE_SUBMATCH_ASIS:
305 case REWRITE_SUBMATCH_XMAP:
306 rc = submatch_copy( &subst->lt_submatch[ n ],
307 string, match, &key );
308 if ( rc != REWRITE_SUCCESS ) {
309 rc = REWRITE_REGEXEC_ERR;
314 case REWRITE_SUBMATCH_MAP_W_ARG:
315 switch ( subst->lt_submatch[ n ].ls_map->lm_type ) {
316 case REWRITE_MAP_GET_OP_VAR:
317 case REWRITE_MAP_GET_SESN_VAR:
318 case REWRITE_MAP_GET_PARAM:
319 rc = REWRITE_SUCCESS;
323 rc = rewrite_subst_apply( info, op,
324 subst->lt_submatch[ n ].ls_map->lm_subst,
325 string, match, &key);
328 if ( rc != REWRITE_SUCCESS ) {
329 rc = REWRITE_REGEXEC_ERR;
335 Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 );
340 if ( rc != REWRITE_SUCCESS ) {
341 rc = REWRITE_REGEXEC_ERR;
348 switch ( subst->lt_submatch[ n ].ls_type ) {
349 case REWRITE_SUBMATCH_ASIS:
351 rc = REWRITE_SUCCESS;
354 case REWRITE_SUBMATCH_XMAP:
355 rc = rewrite_xmap_apply( info, op,
356 subst->lt_submatch[ n ].ls_map,
357 &key, &submatch[ n ] );
362 case REWRITE_SUBMATCH_MAP_W_ARG:
363 rc = rewrite_map_apply( info, op,
364 subst->lt_submatch[ n ].ls_map,
365 &key, &submatch[ n ] );
372 * When implemented, this might return the
373 * exit status of a rewrite context,
374 * which may include a stop, or an
375 * unwilling to perform
381 if ( rc != REWRITE_SUCCESS ) {
382 rc = REWRITE_REGEXEC_ERR;
386 * Increment the length of the resulting string
388 l += submatch[ n ].bv_len;
392 * Alloc result buffer as big as the constant part
393 * of the subst pattern and initialize it
395 l += subst->lt_subs_len;
396 res = malloc( l + 1 );
398 rc = REWRITE_REGEXEC_ERR;
403 * Apply submatches (possibly resolved thru maps
405 for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
406 if ( subst->lt_subs[ n ].bv_val != NULL ) {
407 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
408 subst->lt_subs[ n ].bv_len );
409 cl += subst->lt_subs[ n ].bv_len;
411 AC_MEMCPY( res + cl, submatch[ n ].bv_val,
412 submatch[ n ].bv_len );
413 cl += submatch[ n ].bv_len;
415 if ( subst->lt_subs[ n ].bv_val != NULL ) {
416 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
417 subst->lt_subs[ n ].bv_len );
418 cl += subst->lt_subs[ n ].bv_len;
427 for ( ; --n >= 0; ) {
428 if ( submatch[ n ].bv_val ) {
429 free( submatch[ n ].bv_val );
442 rewrite_subst_destroy(
443 struct rewrite_subst **psubst
447 struct rewrite_subst *subst;
454 for ( n = 0; n < subst->lt_num_submatch; n++ ) {
455 if ( subst->lt_subs[ n ].bv_val ) {
456 free( subst->lt_subs[ n ].bv_val );
457 subst->lt_subs[ n ].bv_val = NULL;
460 switch ( subst->lt_submatch[ n ].ls_type ) {
461 case REWRITE_SUBMATCH_ASIS:
464 case REWRITE_SUBMATCH_XMAP:
465 rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map );
468 case REWRITE_SUBMATCH_MAP_W_ARG:
469 rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map );
477 free( subst->lt_submatch );
478 subst->lt_submatch = NULL;
481 if ( subst->lt_subs[ n ].bv_val ) {
482 free( subst->lt_subs[ n ].bv_val );
483 subst->lt_subs[ n ].bv_val = NULL;
486 free( subst->lt_subs );
487 subst->lt_subs = NULL;