1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/subst.c,v 1.22.2.3 2008/02/11 23:26:42 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2008 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
) {
161 submatch
[ nsub
].ls_type
=
162 REWRITE_SUBMATCH_MAP_W_ARG
;
163 submatch
[ nsub
].ls_map
= map
;
168 } else if ( p
[ 1 ] == '%' ) {
169 AC_MEMCPY( &p
[ 1 ], &p
[ 2 ], strlen( &p
[ 1 ] ) );
180 * Last part of string
182 tmps
= (struct berval
* )realloc( subs
, sizeof( struct berval
)*( nsub
+ 1 ) );
183 if ( tmps
== NULL
) {
185 * XXX need to free the value subst stuff!
194 subs
[ nsub
].bv_len
= l
;
195 subs
[ nsub
].bv_val
= malloc( l
+ 1 );
196 AC_MEMCPY( subs
[ nsub
].bv_val
, begin
, l
);
197 subs
[ nsub
].bv_val
[ l
] = '\0';
199 subs
[ nsub
].bv_val
= NULL
;
200 subs
[ nsub
].bv_len
= 0;
203 s
= calloc( sizeof( struct rewrite_subst
), 1 );
208 s
->lt_subs_len
= subs_len
;
210 s
->lt_num_submatch
= nsub
;
211 s
->lt_submatch
= submatch
;
220 * Copies the match referred to by submatch and fetched in string by match.
221 * Helper for rewrite_rule_apply.
225 struct rewrite_submatch
*submatch
,
227 const regmatch_t
*match
,
234 assert( submatch
!= NULL
);
235 assert( submatch
->ls_type
== REWRITE_SUBMATCH_ASIS
236 || submatch
->ls_type
== REWRITE_SUBMATCH_XMAP
);
237 assert( string
!= NULL
);
238 assert( match
!= NULL
);
239 assert( val
!= NULL
);
240 assert( val
->bv_val
== NULL
);
242 c
= submatch
->ls_submatch
;
243 s
= string
+ match
[ c
].rm_so
;
244 l
= match
[ c
].rm_eo
- match
[ c
].rm_so
;
247 val
->bv_val
= malloc( l
+ 1 );
248 if ( val
->bv_val
== NULL
) {
252 AC_MEMCPY( val
->bv_val
, s
, l
);
253 val
->bv_val
[ l
] = '\0';
255 return REWRITE_SUCCESS
;
259 * Substitutes a portion of rewritten string according to substitution
260 * pattern using submatches
264 struct rewrite_info
*info
,
265 struct rewrite_op
*op
,
266 struct rewrite_subst
*subst
,
268 const regmatch_t
*match
,
272 struct berval
*submatch
= NULL
;
275 int rc
= REWRITE_REGEXEC_OK
;
277 assert( info
!= NULL
);
278 assert( op
!= NULL
);
279 assert( subst
!= NULL
);
280 assert( string
!= NULL
);
281 assert( match
!= NULL
);
282 assert( val
!= NULL
);
284 assert( val
->bv_val
== NULL
);
290 * Prepare room for submatch expansion
292 if ( subst
->lt_num_submatch
> 0 ) {
293 submatch
= calloc( sizeof( struct berval
),
294 subst
->lt_num_submatch
);
295 if ( submatch
== NULL
) {
296 return REWRITE_REGEXEC_ERR
;
301 * Resolve submatches (simple subst, map expansion and so).
303 for ( n
= 0, l
= 0; n
< subst
->lt_num_submatch
; n
++ ) {
304 struct berval key
= { 0, NULL
};
306 submatch
[ n
].bv_val
= NULL
;
311 switch ( subst
->lt_submatch
[ n
].ls_type
) {
312 case REWRITE_SUBMATCH_ASIS
:
313 case REWRITE_SUBMATCH_XMAP
:
314 rc
= submatch_copy( &subst
->lt_submatch
[ n
],
315 string
, match
, &key
);
316 if ( rc
!= REWRITE_SUCCESS
) {
317 rc
= REWRITE_REGEXEC_ERR
;
322 case REWRITE_SUBMATCH_MAP_W_ARG
:
323 switch ( subst
->lt_submatch
[ n
].ls_map
->lm_type
) {
324 case REWRITE_MAP_GET_OP_VAR
:
325 case REWRITE_MAP_GET_SESN_VAR
:
326 case REWRITE_MAP_GET_PARAM
:
327 rc
= REWRITE_SUCCESS
;
331 rc
= rewrite_subst_apply( info
, op
,
332 subst
->lt_submatch
[ n
].ls_map
->lm_subst
,
333 string
, match
, &key
);
336 if ( rc
!= REWRITE_SUCCESS
) {
342 Debug( LDAP_DEBUG_ANY
, "Not Implemented\n", 0, 0, 0 );
347 if ( rc
!= REWRITE_SUCCESS
) {
348 rc
= REWRITE_REGEXEC_ERR
;
355 switch ( subst
->lt_submatch
[ n
].ls_type
) {
356 case REWRITE_SUBMATCH_ASIS
:
358 rc
= REWRITE_SUCCESS
;
361 case REWRITE_SUBMATCH_XMAP
:
362 rc
= rewrite_xmap_apply( info
, op
,
363 subst
->lt_submatch
[ n
].ls_map
,
364 &key
, &submatch
[ n
] );
369 case REWRITE_SUBMATCH_MAP_W_ARG
:
370 rc
= rewrite_map_apply( info
, op
,
371 subst
->lt_submatch
[ n
].ls_map
,
372 &key
, &submatch
[ n
] );
379 * When implemented, this might return the
380 * exit status of a rewrite context,
381 * which may include a stop, or an
382 * unwilling to perform
388 if ( rc
!= REWRITE_SUCCESS
) {
389 rc
= REWRITE_REGEXEC_ERR
;
394 * Increment the length of the resulting string
396 l
+= submatch
[ n
].bv_len
;
400 * Alloc result buffer
402 l
+= subst
->lt_subs_len
;
403 res
= malloc( l
+ 1 );
405 rc
= REWRITE_REGEXEC_ERR
;
410 * Apply submatches (possibly resolved thru maps)
412 for ( n
= 0, cl
= 0; n
< subst
->lt_num_submatch
; n
++ ) {
413 if ( subst
->lt_subs
[ n
].bv_val
!= NULL
) {
414 AC_MEMCPY( res
+ cl
, subst
->lt_subs
[ n
].bv_val
,
415 subst
->lt_subs
[ n
].bv_len
);
416 cl
+= subst
->lt_subs
[ n
].bv_len
;
418 AC_MEMCPY( res
+ cl
, submatch
[ n
].bv_val
,
419 submatch
[ n
].bv_len
);
420 cl
+= submatch
[ n
].bv_len
;
422 if ( subst
->lt_subs
[ n
].bv_val
!= NULL
) {
423 AC_MEMCPY( res
+ cl
, subst
->lt_subs
[ n
].bv_val
,
424 subst
->lt_subs
[ n
].bv_len
);
425 cl
+= subst
->lt_subs
[ n
].bv_len
;
434 for ( ; --n
>= 0; ) {
435 if ( submatch
[ n
].bv_val
) {
436 free( submatch
[ n
].bv_val
);
449 rewrite_subst_destroy(
450 struct rewrite_subst
**psubst
454 struct rewrite_subst
*subst
;
456 assert( psubst
!= NULL
);
457 assert( *psubst
!= NULL
);
461 for ( n
= 0; n
< subst
->lt_num_submatch
; n
++ ) {
462 if ( subst
->lt_subs
[ n
].bv_val
) {
463 free( subst
->lt_subs
[ n
].bv_val
);
464 subst
->lt_subs
[ n
].bv_val
= NULL
;
467 switch ( subst
->lt_submatch
[ n
].ls_type
) {
468 case REWRITE_SUBMATCH_ASIS
:
471 case REWRITE_SUBMATCH_XMAP
:
472 rewrite_xmap_destroy( &subst
->lt_submatch
[ n
].ls_map
);
475 case REWRITE_SUBMATCH_MAP_W_ARG
:
476 rewrite_map_destroy( &subst
->lt_submatch
[ n
].ls_map
);
484 free( subst
->lt_submatch
);
485 subst
->lt_submatch
= NULL
;
488 if ( subst
->lt_subs
[ n
].bv_val
) {
489 free( subst
->lt_subs
[ n
].bv_val
);
490 subst
->lt_subs
[ n
].bv_val
= NULL
;
493 free( subst
->lt_subs
);
494 subst
->lt_subs
= NULL
;