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.
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 );
94 AC_MEMCPY( s, string, l );
98 * Isolate the map name (except for variable deref)
101 case REWRITE_OPERATOR_VARIABLE_GET:
102 case REWRITE_OPERATOR_PARAM_GET:
106 begin = strchr( s, '(' );
107 if ( begin == NULL ) {
117 * Check for special map types
121 case REWRITE_OPERATOR_SUBCONTEXT:
122 case REWRITE_OPERATOR_COMMAND:
123 case REWRITE_OPERATOR_VARIABLE_SET:
124 case REWRITE_OPERATOR_VARIABLE_GET:
125 case REWRITE_OPERATOR_PARAM_GET:
131 * Variable set and get may be repeated to indicate session-wide
132 * instead of operation-wide variables
135 case REWRITE_OPERATOR_VARIABLE_SET:
136 case REWRITE_OPERATOR_VARIABLE_GET:
142 * Variable get token can be appended to variable set to mean store
145 if ( p[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
150 * Check the syntax of the variable name
152 if ( !isalpha( (unsigned char) p[ 0 ] ) ) {
156 for ( p++; p[ 0 ] != '\0'; p++ ) {
157 if ( !isalnum( (unsigned char) p[ 0 ] ) ) {
164 * Isolate the argument of the map (except for variable deref)
167 case REWRITE_OPERATOR_VARIABLE_GET:
168 case REWRITE_OPERATOR_PARAM_GET:
172 end = strrchr( begin, ')' );
180 * Compile the substitution pattern of the map argument
182 subst = rewrite_subst_compile( info, begin );
183 if ( subst == NULL ) {
193 map = calloc( sizeof( struct rewrite_map ), 1 );
198 memset( map, 0, sizeof( struct rewrite_map ) );
200 #ifdef USE_REWRITE_LDAP_PVT_THREADS
201 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
206 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
209 * No subst for variable deref
212 case REWRITE_OPERATOR_VARIABLE_GET:
213 case REWRITE_OPERATOR_PARAM_GET:
217 map->lm_subst = subst;
222 * Parses special map types
229 case REWRITE_OPERATOR_SUBCONTEXT: /* '>' */
232 * Fetch the rewrite context
233 * it MUST have been defined previously
235 map->lm_type = REWRITE_MAP_SUBCONTEXT;
236 map->lm_name = strdup( s + 1 );
237 if ( map->lm_name == NULL ) {
241 map->lm_data = rewrite_context_find( info, s + 1 );
242 if ( map->lm_data == NULL ) {
249 * External command (not implemented yet)
251 case REWRITE_OPERATOR_COMMAND: /* '|' */
258 case REWRITE_OPERATOR_VARIABLE_SET: /* '&' */
259 if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_SET ) {
260 if ( s[ 2 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
261 map->lm_type = REWRITE_MAP_SETW_SESN_VAR;
262 map->lm_name = strdup( s + 3 );
264 map->lm_type = REWRITE_MAP_SET_SESN_VAR;
265 map->lm_name = strdup( s + 2 );
268 if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
269 map->lm_type = REWRITE_MAP_SETW_OP_VAR;
270 map->lm_name = strdup( s + 2 );
272 map->lm_type = REWRITE_MAP_SET_OP_VAR;
273 map->lm_name = strdup( s + 1 );
276 if ( map->lm_name == NULL ) {
283 * Variable dereference
285 case REWRITE_OPERATOR_VARIABLE_GET: /* '*' */
286 if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
287 map->lm_type = REWRITE_MAP_GET_SESN_VAR;
288 map->lm_name = strdup( s + 2 );
290 map->lm_type = REWRITE_MAP_GET_OP_VAR;
291 map->lm_name = strdup( s + 1 );
293 if ( map->lm_name == NULL ) {
302 case REWRITE_OPERATOR_PARAM_GET: /* '$' */
303 map->lm_type = REWRITE_MAP_GET_PARAM;
304 map->lm_name = strdup( s + 1 );
305 if ( map->lm_name == NULL ) {
315 map->lm_type = REWRITE_MAP_BUILTIN;
316 map->lm_name = strdup( s );
317 if ( map->lm_name == NULL ) {
321 map->lm_data = rewrite_builtin_map_find( info, s );
322 if ( map->lm_data == NULL ) {
333 if ( subst != NULL ) {
337 #ifdef USE_REWRITE_LDAP_PVT_THREADS
339 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
341 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
343 if ( map->lm_name ) {
344 free( map->lm_name );
356 * Applies the new map type
360 struct rewrite_info *info,
361 struct rewrite_op *op,
362 struct rewrite_map *map,
367 int rc = REWRITE_SUCCESS;
369 assert( info != NULL );
370 assert( op != NULL );
371 assert( map != NULL );
372 assert( key != NULL );
373 assert( val != NULL );
378 switch ( map->lm_type ) {
379 case REWRITE_MAP_SUBCONTEXT:
380 rc = rewrite_context_apply( info, op,
381 ( struct rewrite_context * )map->lm_data,
382 key->bv_val, &val->bv_val );
383 if ( val->bv_val != NULL ) {
384 if ( val->bv_val == key->bv_val ) {
385 val->bv_len = key->bv_len;
388 val->bv_len = strlen( val->bv_val );
393 case REWRITE_MAP_SET_OP_VAR:
394 case REWRITE_MAP_SETW_OP_VAR:
395 rc = rewrite_var_set( &op->lo_vars, map->lm_name,
397 ? REWRITE_SUCCESS : REWRITE_ERR;
398 if ( rc == REWRITE_SUCCESS ) {
399 if ( map->lm_type == REWRITE_MAP_SET_OP_VAR ) {
400 val->bv_val = strdup( "" );
402 val->bv_val = strdup( key->bv_val );
403 val->bv_len = key->bv_len;
405 if ( val->bv_val == NULL ) {
411 case REWRITE_MAP_GET_OP_VAR: {
412 struct rewrite_var *var;
414 var = rewrite_var_find( op->lo_vars, map->lm_name );
418 val->bv_val = strdup( var->lv_value.bv_val );
419 val->bv_len = var->lv_value.bv_len;
420 if ( val->bv_val == NULL ) {
427 case REWRITE_MAP_SET_SESN_VAR:
428 case REWRITE_MAP_SETW_SESN_VAR:
429 if ( op->lo_cookie == NULL ) {
433 rc = rewrite_session_var_set( info, op->lo_cookie,
434 map->lm_name, key->bv_val );
435 if ( rc == REWRITE_SUCCESS ) {
436 if ( map->lm_type == REWRITE_MAP_SET_SESN_VAR ) {
437 val->bv_val = strdup( "" );
439 val->bv_val = strdup( key->bv_val );
440 val->bv_len = key->bv_len;
442 if ( val->bv_val == NULL ) {
448 case REWRITE_MAP_GET_SESN_VAR:
449 rc = rewrite_session_var_get( info, op->lo_cookie,
453 case REWRITE_MAP_GET_PARAM:
454 rc = rewrite_param_get( info, map->lm_name, val );
457 case REWRITE_MAP_BUILTIN: {
458 struct rewrite_builtin_map *bmap = map->lm_data;
460 if ( bmap->lb_mapper && bmap->lb_mapper->rm_apply )
461 rc = bmap->lb_mapper->rm_apply( bmap->lb_private, key->bv_val,
478 rewrite_builtin_map_free(
482 struct rewrite_builtin_map *map = ( struct rewrite_builtin_map * )tmp;
484 assert( map != NULL );
486 if ( map->lb_mapper && map->lb_mapper->rm_destroy )
487 map->lb_mapper->rm_destroy( map->lb_private );
489 free( map->lb_name );
495 struct rewrite_map **pmap
498 struct rewrite_map *map;
500 assert( pmap != NULL );
501 assert( *pmap != NULL );
505 #ifdef USE_REWRITE_LDAP_PVT_THREADS
506 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
507 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
509 if ( map->lm_name ) {
510 free( map->lm_name );
514 if ( map->lm_subst ) {
515 rewrite_subst_destroy( &map->lm_subst );
518 #ifdef USE_REWRITE_LDAP_PVT_THREADS
519 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
520 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
521 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
530 extern const rewrite_mapper rewrite_ldap_mapper;
532 const rewrite_mapper *
539 if ( !strcasecmp( name, "ldap" ))
540 return &rewrite_ldap_mapper;
542 for (i=0; i<num_mappers; i++)
543 if ( !strcasecmp( name, mappers[i]->rm_name ))
549 rewrite_mapper_register(
550 const rewrite_mapper *map
553 if ( num_mappers % MAPPER_ALLOC == 0 ) {
554 const rewrite_mapper **mnew;
555 mnew = realloc( mappers, (num_mappers + MAPPER_ALLOC) *
556 sizeof( rewrite_mapper * ));
562 mappers[num_mappers++] = map;
567 rewrite_mapper_unregister(
568 const rewrite_mapper *map
573 for (i = 0; i<num_mappers; i++) {
574 if ( mappers[i] == map ) {
576 mappers[i] = mappers[num_mappers];
577 mappers[num_mappers] = NULL;