No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / openldap / dist / libraries / librewrite / map.c
blobfb461fbe4bed1ab5dbef2c356228cd6009359cd7
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.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
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>.
15 /* ACKNOWLEDGEMENT:
16 * This work was initially developed by Pierangelo Masarati for
17 * inclusion in OpenLDAP Software.
20 #include <portable.h>
22 #include <stdio.h>
24 #ifdef HAVE_PWD_H
25 #include <pwd.h>
26 #endif
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
35 struct rewrite_map *
36 rewrite_map_parse(
37 struct rewrite_info *info,
38 const char *string,
39 const char **currpos
42 struct rewrite_map *map = NULL;
43 struct rewrite_subst *subst = NULL;
44 char *s, *begin = NULL, *end;
45 const char *p;
46 int l, cnt, mtx = 0, rc = 0;
48 assert( info != NULL );
49 assert( string != NULL );
50 assert( currpos != NULL );
52 *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 ] == '{' ) {
63 cnt++;
65 * '%' followed by a digit may mark the beginning
66 * of an old map
68 } else if ( isdigit( (unsigned char) p[ 1 ] ) && p[ 2 ] == '{' ) {
69 cnt++;
70 p++;
73 if ( p[ 1 ] != '\0' ) {
74 p++;
77 } else if ( p[ 0 ] == '}' ) {
78 cnt--;
81 if ( cnt != 0 ) {
82 return NULL;
84 *currpos = p;
87 * Copy the map invocation
89 l = p - string - 1;
90 s = calloc( sizeof( char ), l + 1 );
91 AC_MEMCPY( s, string, l );
92 s[ l ] = 0;
95 * Isolate the map name (except for variable deref)
97 switch ( s[ 0 ] ) {
98 case REWRITE_OPERATOR_VARIABLE_GET:
99 case REWRITE_OPERATOR_PARAM_GET:
100 break;
102 default:
103 begin = strchr( s, '(' );
104 if ( begin == NULL ) {
105 rc = -1;
106 goto cleanup;
108 begin[ 0 ] = '\0';
109 begin++;
110 break;
114 * Check for special map types
116 p = s;
117 switch ( p[ 0 ] ) {
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:
123 p++;
124 break;
128 * Variable set and get may be repeated to indicate session-wide
129 * instead of operation-wide variables
131 switch ( p[ 0 ] ) {
132 case REWRITE_OPERATOR_VARIABLE_SET:
133 case REWRITE_OPERATOR_VARIABLE_GET:
134 p++;
135 break;
139 * Variable get token can be appended to variable set to mean store
140 * AND rewrite
142 if ( p[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
143 p++;
147 * Check the syntax of the variable name
149 if ( !isalpha( (unsigned char) p[ 0 ] ) ) {
150 rc = -1;
151 goto cleanup;
153 for ( p++; p[ 0 ] != '\0'; p++ ) {
154 if ( !isalnum( (unsigned char) p[ 0 ] ) ) {
155 rc = -1;
156 goto cleanup;
161 * Isolate the argument of the map (except for variable deref)
163 switch ( s[ 0 ] ) {
164 case REWRITE_OPERATOR_VARIABLE_GET:
165 case REWRITE_OPERATOR_PARAM_GET:
166 break;
168 default:
169 end = strrchr( begin, ')' );
170 if ( end == NULL ) {
171 rc = -1;
172 goto cleanup;
174 end[ 0 ] = '\0';
177 * Compile the substitution pattern of the map argument
179 subst = rewrite_subst_compile( info, begin );
180 if ( subst == NULL ) {
181 rc = -1;
182 goto cleanup;
184 break;
188 * Create the map
190 map = calloc( sizeof( struct rewrite_map ), 1 );
191 if ( map == NULL ) {
192 rc = -1;
193 goto cleanup;
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 ) ) {
199 rc = -1;
200 goto cleanup;
202 ++mtx;
203 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
206 * No subst for variable deref
208 switch ( s[ 0 ] ) {
209 case REWRITE_OPERATOR_VARIABLE_GET:
210 case REWRITE_OPERATOR_PARAM_GET:
211 break;
213 default:
214 map->lm_subst = subst;
215 break;
219 * Parses special map types
221 switch ( s[ 0 ] ) {
224 * Subcontext
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 ) {
236 rc = -1;
237 goto cleanup;
239 break;
242 * External command (not implemented yet)
244 case REWRITE_OPERATOR_COMMAND: /* '|' */
245 rc = -1;
246 goto cleanup;
249 * Variable set
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 );
256 } else {
257 map->lm_type = REWRITE_MAP_SET_SESN_VAR;
258 map->lm_name = strdup( s + 2 );
260 } else {
261 if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
262 map->lm_type = REWRITE_MAP_SETW_OP_VAR;
263 map->lm_name = strdup( s + 2 );
264 } else {
265 map->lm_type = REWRITE_MAP_SET_OP_VAR;
266 map->lm_name = strdup( s + 1 );
269 break;
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 );
278 } else {
279 map->lm_type = REWRITE_MAP_GET_OP_VAR;
280 map->lm_name = strdup( s + 1 );
282 break;
285 * Parameter
287 case REWRITE_OPERATOR_PARAM_GET: /* '$' */
288 map->lm_type = REWRITE_MAP_GET_PARAM;
289 map->lm_name = strdup( s + 1 );
290 break;
293 * Built-in map
295 default:
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 ) {
300 rc = -1;
301 goto cleanup;
303 break;
307 cleanup:
308 free( s );
309 if ( rc ) {
310 if ( subst != NULL ) {
311 free( subst );
313 if ( map ) {
314 #ifdef USE_REWRITE_LDAP_PVT_THREADS
315 if ( mtx ) {
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 );
322 map->lm_name = NULL;
324 free( map );
325 map = NULL;
329 return map;
333 * Applies the new map type
336 rewrite_map_apply(
337 struct rewrite_info *info,
338 struct rewrite_op *op,
339 struct rewrite_map *map,
340 struct berval *key,
341 struct berval *val
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 );
352 val->bv_val = NULL;
353 val->bv_len = 0;
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;
363 key->bv_val = NULL;
364 } else {
365 val->bv_len = strlen( val->bv_val );
368 break;
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,
373 key->bv_val, 1 )
374 ? REWRITE_SUCCESS : REWRITE_ERR;
375 if ( map->lm_type == REWRITE_MAP_SET_OP_VAR ) {
376 val->bv_val = strdup( "" );
377 } else {
378 val->bv_val = strdup( key->bv_val );
379 val->bv_len = key->bv_len;
381 break;
383 case REWRITE_MAP_GET_OP_VAR: {
384 struct rewrite_var *var;
386 var = rewrite_var_find( op->lo_vars, map->lm_name );
387 if ( var == NULL ) {
388 rc = REWRITE_ERR;
389 } else {
390 val->bv_val = strdup( var->lv_value.bv_val );
391 val->bv_len = var->lv_value.bv_len;
393 break;
396 case REWRITE_MAP_SET_SESN_VAR:
397 case REWRITE_MAP_SETW_SESN_VAR:
398 if ( op->lo_cookie == NULL ) {
399 rc = REWRITE_ERR;
400 break;
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( "" );
406 } else {
407 val->bv_val = strdup( key->bv_val );
408 val->bv_len = key->bv_len;
410 break;
412 case REWRITE_MAP_GET_SESN_VAR:
413 rc = rewrite_session_var_get( info, op->lo_cookie,
414 map->lm_name, val );
415 break;
417 case REWRITE_MAP_GET_PARAM:
418 rc = rewrite_param_get( info, map->lm_name, val );
419 break;
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,
426 val );
427 else
428 rc = REWRITE_ERR;
429 break;
430 break;
433 default:
434 rc = REWRITE_ERR;
435 break;
438 return rc;
441 void
442 rewrite_builtin_map_free(
443 void *tmp
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 );
454 free( map );
458 rewrite_map_destroy(
459 struct rewrite_map **pmap
462 struct rewrite_map *map;
464 assert( pmap != NULL );
465 assert( *pmap != NULL );
467 map = *pmap;
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 );
475 map->lm_name = NULL;
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 */
487 free( map );
488 *pmap = NULL;
490 return 0;
493 /* ldapmap.c */
494 extern const rewrite_mapper rewrite_ldap_mapper;
496 const rewrite_mapper *
497 rewrite_mapper_find(
498 const char *name
501 int i;
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 ))
508 return mappers[i];
509 return NULL;
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 * ));
521 if ( mnew )
522 mappers = mnew;
523 else
524 return -1;
526 mappers[num_mappers++] = map;
527 return 0;
531 rewrite_mapper_unregister(
532 const rewrite_mapper *map
535 int i;
537 for (i = 0; i<num_mappers; i++) {
538 if ( mappers[i] == map ) {
539 num_mappers--;
540 mappers[i] = mappers[num_mappers];
541 mappers[num_mappers] = NULL;
542 return 0;
545 /* not found */
546 return -1;