1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/map.c,v 1.21.2.4 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.
28 #include "rewrite-int.h"
29 #include "rewrite-map.h"
31 static int num_mappers
;
32 static const rewrite_mapper
**mappers
;
33 #define MAPPER_ALLOC 8
37 struct rewrite_info
*info
,
42 struct rewrite_map
*map
= NULL
;
43 struct rewrite_subst
*subst
= NULL
;
44 char *s
, *begin
= NULL
, *end
;
46 int l
, cnt
, mtx
= 0, rc
= 0;
48 assert( info
!= NULL
);
49 assert( string
!= NULL
);
50 assert( currpos
!= NULL
);
55 * Go to the end of the map invocation (the right closing brace)
57 for ( p
= string
, cnt
= 1; p
[ 0 ] != '\0' && cnt
> 0; p
++ ) {
58 if ( IS_REWRITE_SUBMATCH_ESCAPE( p
[ 0 ] ) ) {
60 * '%' marks the beginning of a new map
62 if ( p
[ 1 ] == '{' ) {
65 * '%' followed by a digit may mark the beginning
68 } else if ( isdigit( (unsigned char) p
[ 1 ] ) && p
[ 2 ] == '{' ) {
73 if ( p
[ 1 ] != '\0' ) {
77 } else if ( p
[ 0 ] == '}' ) {
87 * Copy the map invocation
90 s
= calloc( sizeof( char ), l
+ 1 );
91 AC_MEMCPY( s
, string
, l
);
95 * Isolate the map name (except for variable deref)
98 case REWRITE_OPERATOR_VARIABLE_GET
:
99 case REWRITE_OPERATOR_PARAM_GET
:
103 begin
= strchr( s
, '(' );
104 if ( begin
== NULL
) {
114 * Check for special map types
118 case REWRITE_OPERATOR_SUBCONTEXT
:
119 case REWRITE_OPERATOR_COMMAND
:
120 case REWRITE_OPERATOR_VARIABLE_SET
:
121 case REWRITE_OPERATOR_VARIABLE_GET
:
122 case REWRITE_OPERATOR_PARAM_GET
:
128 * Variable set and get may be repeated to indicate session-wide
129 * instead of operation-wide variables
132 case REWRITE_OPERATOR_VARIABLE_SET
:
133 case REWRITE_OPERATOR_VARIABLE_GET
:
139 * Variable get token can be appended to variable set to mean store
142 if ( p
[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET
) {
147 * Check the syntax of the variable name
149 if ( !isalpha( (unsigned char) p
[ 0 ] ) ) {
153 for ( p
++; p
[ 0 ] != '\0'; p
++ ) {
154 if ( !isalnum( (unsigned char) p
[ 0 ] ) ) {
161 * Isolate the argument of the map (except for variable deref)
164 case REWRITE_OPERATOR_VARIABLE_GET
:
165 case REWRITE_OPERATOR_PARAM_GET
:
169 end
= strrchr( begin
, ')' );
177 * Compile the substitution pattern of the map argument
179 subst
= rewrite_subst_compile( info
, begin
);
180 if ( subst
== NULL
) {
190 map
= calloc( sizeof( struct rewrite_map
), 1 );
195 memset( map
, 0, sizeof( struct rewrite_map
) );
197 #ifdef USE_REWRITE_LDAP_PVT_THREADS
198 if ( ldap_pvt_thread_mutex_init( &map
->lm_mutex
) ) {
203 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
206 * No subst for variable deref
209 case REWRITE_OPERATOR_VARIABLE_GET
:
210 case REWRITE_OPERATOR_PARAM_GET
:
214 map
->lm_subst
= subst
;
219 * Parses special map types
226 case REWRITE_OPERATOR_SUBCONTEXT
: /* '>' */
229 * Fetch the rewrite context
230 * it MUST have been defined previously
232 map
->lm_type
= REWRITE_MAP_SUBCONTEXT
;
233 map
->lm_name
= strdup( s
+ 1 );
234 map
->lm_data
= rewrite_context_find( info
, s
+ 1 );
235 if ( map
->lm_data
== NULL
) {
242 * External command (not implemented yet)
244 case REWRITE_OPERATOR_COMMAND
: /* '|' */
251 case REWRITE_OPERATOR_VARIABLE_SET
: /* '&' */
252 if ( s
[ 1 ] == REWRITE_OPERATOR_VARIABLE_SET
) {
253 if ( s
[ 2 ] == REWRITE_OPERATOR_VARIABLE_GET
) {
254 map
->lm_type
= REWRITE_MAP_SETW_SESN_VAR
;
255 map
->lm_name
= strdup( s
+ 3 );
257 map
->lm_type
= REWRITE_MAP_SET_SESN_VAR
;
258 map
->lm_name
= strdup( s
+ 2 );
261 if ( s
[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET
) {
262 map
->lm_type
= REWRITE_MAP_SETW_OP_VAR
;
263 map
->lm_name
= strdup( s
+ 2 );
265 map
->lm_type
= REWRITE_MAP_SET_OP_VAR
;
266 map
->lm_name
= strdup( s
+ 1 );
272 * Variable dereference
274 case REWRITE_OPERATOR_VARIABLE_GET
: /* '*' */
275 if ( s
[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET
) {
276 map
->lm_type
= REWRITE_MAP_GET_SESN_VAR
;
277 map
->lm_name
= strdup( s
+ 2 );
279 map
->lm_type
= REWRITE_MAP_GET_OP_VAR
;
280 map
->lm_name
= strdup( s
+ 1 );
287 case REWRITE_OPERATOR_PARAM_GET
: /* '$' */
288 map
->lm_type
= REWRITE_MAP_GET_PARAM
;
289 map
->lm_name
= strdup( s
+ 1 );
296 map
->lm_type
= REWRITE_MAP_BUILTIN
;
297 map
->lm_name
= strdup( s
);
298 map
->lm_data
= rewrite_builtin_map_find( info
, s
);
299 if ( map
->lm_data
== NULL
) {
310 if ( subst
!= NULL
) {
314 #ifdef USE_REWRITE_LDAP_PVT_THREADS
316 ldap_pvt_thread_mutex_destroy( &map
->lm_mutex
);
318 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
320 if ( map
->lm_name
) {
321 free( map
->lm_name
);
333 * Applies the new map type
337 struct rewrite_info
*info
,
338 struct rewrite_op
*op
,
339 struct rewrite_map
*map
,
344 int rc
= REWRITE_SUCCESS
;
346 assert( info
!= NULL
);
347 assert( op
!= NULL
);
348 assert( map
!= NULL
);
349 assert( key
!= NULL
);
350 assert( val
!= NULL
);
355 switch ( map
->lm_type
) {
356 case REWRITE_MAP_SUBCONTEXT
:
357 rc
= rewrite_context_apply( info
, op
,
358 ( struct rewrite_context
* )map
->lm_data
,
359 key
->bv_val
, &val
->bv_val
);
360 if ( val
->bv_val
!= NULL
) {
361 if ( val
->bv_val
== key
->bv_val
) {
362 val
->bv_len
= key
->bv_len
;
365 val
->bv_len
= strlen( val
->bv_val
);
370 case REWRITE_MAP_SET_OP_VAR
:
371 case REWRITE_MAP_SETW_OP_VAR
:
372 rc
= rewrite_var_set( &op
->lo_vars
, map
->lm_name
,
374 ? REWRITE_SUCCESS
: REWRITE_ERR
;
375 if ( map
->lm_type
== REWRITE_MAP_SET_OP_VAR
) {
376 val
->bv_val
= strdup( "" );
378 val
->bv_val
= strdup( key
->bv_val
);
379 val
->bv_len
= key
->bv_len
;
383 case REWRITE_MAP_GET_OP_VAR
: {
384 struct rewrite_var
*var
;
386 var
= rewrite_var_find( op
->lo_vars
, map
->lm_name
);
390 val
->bv_val
= strdup( var
->lv_value
.bv_val
);
391 val
->bv_len
= var
->lv_value
.bv_len
;
396 case REWRITE_MAP_SET_SESN_VAR
:
397 case REWRITE_MAP_SETW_SESN_VAR
:
398 if ( op
->lo_cookie
== NULL
) {
402 rc
= rewrite_session_var_set( info
, op
->lo_cookie
,
403 map
->lm_name
, key
->bv_val
);
404 if ( map
->lm_type
== REWRITE_MAP_SET_SESN_VAR
) {
405 val
->bv_val
= strdup( "" );
407 val
->bv_val
= strdup( key
->bv_val
);
408 val
->bv_len
= key
->bv_len
;
412 case REWRITE_MAP_GET_SESN_VAR
:
413 rc
= rewrite_session_var_get( info
, op
->lo_cookie
,
417 case REWRITE_MAP_GET_PARAM
:
418 rc
= rewrite_param_get( info
, map
->lm_name
, val
);
421 case REWRITE_MAP_BUILTIN
: {
422 struct rewrite_builtin_map
*bmap
= map
->lm_data
;
424 if ( bmap
->lb_mapper
&& bmap
->lb_mapper
->rm_apply
)
425 rc
= bmap
->lb_mapper
->rm_apply( bmap
->lb_private
, key
->bv_val
,
442 rewrite_builtin_map_free(
446 struct rewrite_builtin_map
*map
= ( struct rewrite_builtin_map
* )tmp
;
448 assert( map
!= NULL
);
450 if ( map
->lb_mapper
&& map
->lb_mapper
->rm_destroy
)
451 map
->lb_mapper
->rm_destroy( map
->lb_private
);
453 free( map
->lb_name
);
459 struct rewrite_map
**pmap
462 struct rewrite_map
*map
;
464 assert( pmap
!= NULL
);
465 assert( *pmap
!= NULL
);
469 #ifdef USE_REWRITE_LDAP_PVT_THREADS
470 ldap_pvt_thread_mutex_lock( &map
->lm_mutex
);
471 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
473 if ( map
->lm_name
) {
474 free( map
->lm_name
);
478 if ( map
->lm_subst
) {
479 rewrite_subst_destroy( &map
->lm_subst
);
482 #ifdef USE_REWRITE_LDAP_PVT_THREADS
483 ldap_pvt_thread_mutex_unlock( &map
->lm_mutex
);
484 ldap_pvt_thread_mutex_destroy( &map
->lm_mutex
);
485 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
494 extern const rewrite_mapper rewrite_ldap_mapper
;
496 const rewrite_mapper
*
503 if ( !strcasecmp( name
, "ldap" ))
504 return &rewrite_ldap_mapper
;
506 for (i
=0; i
<num_mappers
; i
++)
507 if ( !strcasecmp( name
, mappers
[i
]->rm_name
))
513 rewrite_mapper_register(
514 const rewrite_mapper
*map
517 if ( num_mappers
% MAPPER_ALLOC
== 0 ) {
518 const rewrite_mapper
**mnew
;
519 mnew
= realloc( mappers
, (num_mappers
+ MAPPER_ALLOC
) *
520 sizeof( rewrite_mapper
* ));
526 mappers
[num_mappers
++] = map
;
531 rewrite_mapper_unregister(
532 const rewrite_mapper
*map
537 for (i
= 0; i
<num_mappers
; i
++) {
538 if ( mappers
[i
] == map
) {
540 mappers
[i
] = mappers
[num_mappers
];
541 mappers
[num_mappers
] = NULL
;