2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2018 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 char *result, *begin, *p;
42 assert( info != NULL );
43 assert( str != NULL );
45 result = strdup( str );
46 if ( 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 ( !IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
62 if ( IS_REWRITE_SUBMATCH_ESCAPE( p[ 1 ] ) ) {
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 ) );
76 * I think an `if l > 0' at runtime is better outside than
77 * inside a function call ...
82 subs[ nsub ].bv_len = l;
83 subs[ nsub ].bv_val = malloc( l + 1 );
84 if ( subs[ nsub ].bv_val == NULL ) {
87 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
88 subs[ nsub ].bv_val[ l ] = '\0';
90 subs[ nsub ].bv_val = NULL;
91 subs[ nsub ].bv_len = 0;
95 * Substitution pattern
97 if ( isdigit( (unsigned char) p[ 1 ] ) ) {
98 struct rewrite_submatch *tmpsm;
102 * Add a new value substitution scheme
105 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
106 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
107 if ( tmpsm == NULL ) {
111 submatch[ nsub ].ls_submatch = d;
114 * If there is no argument, use default
115 * (substitute substring as is)
117 if ( p[ 2 ] != '{' ) {
118 submatch[ nsub ].ls_type =
119 REWRITE_SUBMATCH_ASIS;
120 submatch[ nsub ].ls_map = NULL;
124 struct rewrite_map *map;
126 submatch[ nsub ].ls_type =
127 REWRITE_SUBMATCH_XMAP;
129 map = rewrite_xmap_parse( info,
130 p + 3, (const char **)&begin );
134 submatch[ nsub ].ls_map = map;
141 } else if ( p[ 1 ] == '{' ) {
142 struct rewrite_map *map;
143 struct rewrite_submatch *tmpsm;
145 map = rewrite_map_parse( info, p + 2,
146 (const char **)&begin );
153 * Add a new value substitution scheme
155 tmpsm = ( struct rewrite_submatch * )realloc( submatch,
156 sizeof( struct rewrite_submatch )*( nsub + 1 ) );
157 if ( tmpsm == NULL ) {
158 rewrite_map_destroy( &map );
162 submatch[ nsub ].ls_type =
163 REWRITE_SUBMATCH_MAP_W_ARG;
164 submatch[ nsub ].ls_map = map;
169 } else if ( p[ 1 ] == '%' ) {
170 AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) );
181 * Last part of string
183 tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
184 if ( tmps == NULL ) {
186 * XXX need to free the value subst stuff!
195 subs[ nsub ].bv_len = l;
196 subs[ nsub ].bv_val = malloc( l + 1 );
197 if ( subs[ nsub ].bv_val == NULL ) {
200 AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
201 subs[ nsub ].bv_val[ l ] = '\0';
203 subs[ nsub ].bv_val = NULL;
204 subs[ nsub ].bv_len = 0;
207 s = calloc( sizeof( struct rewrite_subst ), 1 );
212 s->lt_subs_len = subs_len;
214 s->lt_num_submatch = nsub;
215 s->lt_submatch = submatch;
221 for ( l=0; l<nsub; l++ ) {
222 free( subs[nsub].bv_val );
227 for ( l=0; l<nsub; l++ ) {
228 free( submatch[nsub].ls_map );
238 * Copies the match referred to by submatch and fetched in string by match.
239 * Helper for rewrite_rule_apply.
243 struct rewrite_submatch *submatch,
245 const regmatch_t *match,
252 assert( submatch != NULL );
253 assert( submatch->ls_type == REWRITE_SUBMATCH_ASIS
254 || submatch->ls_type == REWRITE_SUBMATCH_XMAP );
255 assert( string != NULL );
256 assert( match != NULL );
257 assert( val != NULL );
258 assert( val->bv_val == NULL );
260 c = submatch->ls_submatch;
261 s = string + match[ c ].rm_so;
262 l = match[ c ].rm_eo - match[ c ].rm_so;
265 val->bv_val = malloc( l + 1 );
266 if ( val->bv_val == NULL ) {
270 AC_MEMCPY( val->bv_val, s, l );
271 val->bv_val[ l ] = '\0';
273 return REWRITE_SUCCESS;
277 * Substitutes a portion of rewritten string according to substitution
278 * pattern using submatches
282 struct rewrite_info *info,
283 struct rewrite_op *op,
284 struct rewrite_subst *subst,
286 const regmatch_t *match,
290 struct berval *submatch = NULL;
293 int rc = REWRITE_REGEXEC_OK;
295 assert( info != NULL );
296 assert( op != NULL );
297 assert( subst != NULL );
298 assert( string != NULL );
299 assert( match != NULL );
300 assert( val != NULL );
302 assert( val->bv_val == NULL );
308 * Prepare room for submatch expansion
310 if ( subst->lt_num_submatch > 0 ) {
311 submatch = calloc( sizeof( struct berval ),
312 subst->lt_num_submatch );
313 if ( submatch == NULL ) {
314 return REWRITE_REGEXEC_ERR;
319 * Resolve submatches (simple subst, map expansion and so).
321 for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) {
322 struct berval key = { 0, NULL };
324 submatch[ n ].bv_val = NULL;
329 switch ( subst->lt_submatch[ n ].ls_type ) {
330 case REWRITE_SUBMATCH_ASIS:
331 case REWRITE_SUBMATCH_XMAP:
332 rc = submatch_copy( &subst->lt_submatch[ n ],
333 string, match, &key );
334 if ( rc != REWRITE_SUCCESS ) {
335 rc = REWRITE_REGEXEC_ERR;
340 case REWRITE_SUBMATCH_MAP_W_ARG:
341 switch ( subst->lt_submatch[ n ].ls_map->lm_type ) {
342 case REWRITE_MAP_GET_OP_VAR:
343 case REWRITE_MAP_GET_SESN_VAR:
344 case REWRITE_MAP_GET_PARAM:
345 rc = REWRITE_SUCCESS;
349 rc = rewrite_subst_apply( info, op,
350 subst->lt_submatch[ n ].ls_map->lm_subst,
351 string, match, &key);
354 if ( rc != REWRITE_SUCCESS ) {
360 Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 );
365 if ( rc != REWRITE_SUCCESS ) {
366 rc = REWRITE_REGEXEC_ERR;
373 switch ( subst->lt_submatch[ n ].ls_type ) {
374 case REWRITE_SUBMATCH_ASIS:
376 rc = REWRITE_SUCCESS;
379 case REWRITE_SUBMATCH_XMAP:
380 rc = rewrite_xmap_apply( info, op,
381 subst->lt_submatch[ n ].ls_map,
382 &key, &submatch[ n ] );
387 case REWRITE_SUBMATCH_MAP_W_ARG:
388 rc = rewrite_map_apply( info, op,
389 subst->lt_submatch[ n ].ls_map,
390 &key, &submatch[ n ] );
397 * When implemented, this might return the
398 * exit status of a rewrite context,
399 * which may include a stop, or an
400 * unwilling to perform
406 if ( rc != REWRITE_SUCCESS ) {
407 rc = REWRITE_REGEXEC_ERR;
412 * Increment the length of the resulting string
414 l += submatch[ n ].bv_len;
418 * Alloc result buffer
420 l += subst->lt_subs_len;
421 res = malloc( l + 1 );
423 rc = REWRITE_REGEXEC_ERR;
428 * Apply submatches (possibly resolved thru maps)
430 for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
431 if ( subst->lt_subs[ n ].bv_val != NULL ) {
432 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
433 subst->lt_subs[ n ].bv_len );
434 cl += subst->lt_subs[ n ].bv_len;
436 AC_MEMCPY( res + cl, submatch[ n ].bv_val,
437 submatch[ n ].bv_len );
438 cl += submatch[ n ].bv_len;
440 if ( subst->lt_subs[ n ].bv_val != NULL ) {
441 AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
442 subst->lt_subs[ n ].bv_len );
443 cl += subst->lt_subs[ n ].bv_len;
452 for ( ; --n >= 0; ) {
453 if ( submatch[ n ].bv_val ) {
454 free( submatch[ n ].bv_val );
467 rewrite_subst_destroy(
468 struct rewrite_subst **psubst
472 struct rewrite_subst *subst;
474 assert( psubst != NULL );
475 assert( *psubst != NULL );
479 for ( n = 0; n < subst->lt_num_submatch; n++ ) {
480 if ( subst->lt_subs[ n ].bv_val ) {
481 free( subst->lt_subs[ n ].bv_val );
482 subst->lt_subs[ n ].bv_val = NULL;
485 switch ( subst->lt_submatch[ n ].ls_type ) {
486 case REWRITE_SUBMATCH_ASIS:
489 case REWRITE_SUBMATCH_XMAP:
490 rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map );
493 case REWRITE_SUBMATCH_MAP_W_ARG:
494 rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map );
502 free( subst->lt_submatch );
503 subst->lt_submatch = NULL;
506 if ( subst->lt_subs[ n ].bv_val ) {
507 free( subst->lt_subs[ n ].bv_val );
508 subst->lt_subs[ n ].bv_val = NULL;
511 free( subst->lt_subs );
512 subst->lt_subs = NULL;