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;