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 ) {
61 if ( p[ 1 ] == REWRITE_SUBMATCH_ESCAPE ) {
62 AC_MEMCPY((char *)p, p + 1, strlen( p ) );
68 tmps = (struct berval **)realloc( subs,
69 sizeof( struct berval * )*( nsub + 1 ) );
78 * I think an `if l > 0' at runtime is better outside than
79 * inside a function call ...
85 calloc( sizeof( struct berval ), 1 );
86 if ( subs[ nsub - 1 ] == NULL ) {
90 subs[ nsub - 1 ]->bv_len = l;
91 subs[ nsub - 1 ]->bv_val = malloc( l + 1 );
92 if ( subs[ nsub - 1 ]->bv_val == NULL ) {
95 AC_MEMCPY( subs[ nsub - 1 ]->bv_val, begin, l );
96 subs[ nsub - 1 ]->bv_val[ l ] = '\0';
98 subs[ nsub - 1 ] = NULL;
102 * Substitution pattern
104 if ( isdigit( (unsigned char) p[ 1 ] ) ) {
105 int d = p[ 1 ] - '0';
106 struct rewrite_submatch **tmpsm;
109 * Add a new value substitution scheme
111 tmpsm = realloc( submatch,
112 sizeof( struct rewrite_submatch * )*( nsub + 1 ) );
113 if ( tmpsm == NULL ) {
118 submatch[ nsub ] = NULL;
120 submatch[ nsub - 1 ] =
121 calloc( sizeof( struct rewrite_submatch ), 1 );
122 if ( submatch[ nsub - 1 ] == NULL ) {
126 submatch[ nsub - 1 ]->ls_submatch = d;
129 * If there is no argument, use default
130 * (substitute substring as is)
132 if ( p[ 2 ] != '{' ) {
133 submatch[ nsub - 1 ]->ls_type =
134 REWRITE_SUBMATCH_ASIS;
137 struct rewrite_map *map;
139 submatch[ nsub - 1 ]->ls_type =
140 REWRITE_SUBMATCH_XMAP;
142 map = rewrite_xmap_parse( info,
150 submatch[ nsub - 1 ]->ls_map = map;
156 } else if ( p[ 1 ] == '{' ) {
157 struct rewrite_map *map;
158 struct rewrite_submatch **tmpsm;
160 map = rewrite_map_parse( info, p + 2, &begin );
168 * Add a new value substitution scheme
170 tmpsm = realloc( submatch,
171 sizeof( struct rewrite_submatch * )*( nsub + 1 ) );
172 if ( tmpsm == NULL ) {
177 submatch[ nsub ] = NULL;
178 submatch[ nsub - 1 ] =
179 calloc( sizeof( struct rewrite_submatch ), 1 );
180 if ( submatch[ nsub - 1 ] == NULL ) {
185 submatch[ nsub - 1 ]->ls_type =
186 REWRITE_SUBMATCH_MAP_W_ARG;
188 submatch[ nsub - 1 ]->ls_map = map;
193 * Last part of string
195 tmps = realloc( subs, sizeof( struct berval *)*( nsub + 2 ) );
196 if ( tmps == NULL ) {
198 * XXX need to free the value subst stuff!
205 subs[ nsub + 1 ] = NULL;
208 subs[ nsub ] = calloc( sizeof( struct berval ), 1 );
210 subs[ nsub ]->bv_len = l;
211 subs[ nsub ]->bv_val = malloc( l + 1 );
212 AC_MEMCPY( subs[ nsub ]->bv_val, begin, l );
213 subs[ nsub ]->bv_val[ l ] = '\0';
218 s = calloc( sizeof( struct rewrite_subst ), 1 );
224 s->lt_subs_len = subs_len;
226 s->lt_num_submatch = nsub;
227 s->lt_submatch = submatch;
233 * Copies the match referred to by submatch and fetched in string by match.
234 * Helper for rewrite_rule_apply.
238 struct rewrite_submatch *submatch,
240 const regmatch_t *match,
247 assert( submatch != NULL );
248 assert( submatch->ls_type == REWRITE_SUBMATCH_ASIS
249 || submatch->ls_type == REWRITE_SUBMATCH_XMAP );
250 assert( string != NULL );
251 assert( match != NULL );
252 assert( val != NULL );
254 c = submatch->ls_submatch;
255 s = string + match[ c ].rm_so;
256 l = match[ c ].rm_eo - match[ c ].rm_so;
260 val->bv_val = calloc( sizeof( char ), l + 1 );
261 if ( val->bv_val == NULL ) {
265 AC_MEMCPY( val->bv_val, s, l );
266 val->bv_val[ l ] = '\0';
268 return REWRITE_SUCCESS;
272 * Substitutes a portion of rewritten string according to substitution
273 * pattern using submatches
277 struct rewrite_info *info,
278 struct rewrite_op *op,
279 struct rewrite_subst *subst,
281 const regmatch_t *match,
285 struct berval *submatch = NULL;
288 int rc = REWRITE_REGEXEC_OK;
290 assert( info != NULL );
291 assert( op != NULL );
292 assert( subst != NULL );
293 assert( string != NULL );
294 assert( match != NULL );
295 assert( val != NULL );
301 * Prepare room for submatch expansion
303 if ( subst->lt_num_submatch > 0 ) {
304 submatch = calloc( sizeof( struct berval ),
305 subst->lt_num_submatch );
306 if ( submatch == NULL ) {
307 return REWRITE_REGEXEC_ERR;
312 * Resolve submatches (simple subst, map expansion and so).
314 for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
321 switch( subst->lt_submatch[ n ]->ls_type ) {
322 case REWRITE_SUBMATCH_ASIS:
323 case REWRITE_SUBMATCH_XMAP:
324 rc = submatch_copy( subst->lt_submatch[ n ],
325 string, match, &key );
326 if ( rc != REWRITE_SUCCESS ) {
328 return REWRITE_REGEXEC_ERR;
332 case REWRITE_SUBMATCH_MAP_W_ARG:
333 switch ( subst->lt_submatch[ n ]->ls_map->lm_type ) {
334 case REWRITE_MAP_GET_OP_VAR:
335 case REWRITE_MAP_GET_SESN_VAR:
336 case REWRITE_MAP_GET_PARAM:
337 rc = REWRITE_SUCCESS;
340 rc = rewrite_subst_apply( info, op,
341 subst->lt_submatch[ n ]->ls_map->lm_subst,
342 string, match, &key);
345 if ( rc != REWRITE_SUCCESS ) {
347 return REWRITE_REGEXEC_ERR;
352 Debug( LDAP_DEBUG_ANY, "Not Implemented\n%s%s%s",
358 if ( rc != REWRITE_SUCCESS ) {
360 return REWRITE_REGEXEC_ERR;
366 switch ( subst->lt_submatch[ n ]->ls_type ) {
367 case REWRITE_SUBMATCH_ASIS:
369 rc = REWRITE_SUCCESS;
372 case REWRITE_SUBMATCH_XMAP:
373 rc = rewrite_xmap_apply( info, op,
374 subst->lt_submatch[ n ]->ls_map,
375 &key, &submatch[ n ] );
378 case REWRITE_SUBMATCH_MAP_W_ARG:
379 rc = rewrite_map_apply( info, op,
380 subst->lt_submatch[ n ]->ls_map,
381 &key, &submatch[ n ] );
386 * When implemented, this might return the
387 * exit status of a rewrite context,
388 * which may include a stop, or an
389 * unwilling to perform
395 if ( rc != REWRITE_SUCCESS ) {
397 return REWRITE_REGEXEC_ERR;
401 * Increment the length of the resulting string
403 l += submatch[ n ].bv_len;
407 * Alloc result buffer as big as the constant part
408 * of the subst pattern and initialize it
410 l += subst->lt_subs_len;
411 res = calloc( sizeof( char ), l + 1 );
413 rc = REWRITE_REGEXEC_ERR;
418 * Apply submatches (possibly resolved thru maps
420 for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
421 if ( subst->lt_subs[ n ] != NULL ) {
422 AC_MEMCPY( res + cl, subst->lt_subs[ n ]->bv_val,
423 subst->lt_subs[ n ]->bv_len );
424 cl += subst->lt_subs[ n ]->bv_len;
426 AC_MEMCPY( res + cl, submatch[ n ].bv_val,
427 submatch[ n ].bv_len );
428 cl += submatch[ n ].bv_len;
429 free( submatch[ n ].bv_val );
431 if ( subst->lt_subs[ n ] != NULL ) {
432 AC_MEMCPY( res + cl, subst->lt_subs[ n ]->bv_val,
433 subst->lt_subs[ n ]->bv_len );