~ubuntu-branches/ubuntu/oneiric/likewise-open/oneiric

« back to all changes in this revision

Viewing changes to openldap/libraries/librewrite/map.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Salley
  • Date: 2010-11-22 12:06:00 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122120600-8lba1fpceot71wlb
Tags: 6.0.0.53010-1
Likewise Open 6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $OpenLDAP: pkg/ldap/libraries/librewrite/map.c,v 1.21.2.6 2009/01/22 00:00:58 kurt Exp $ */
 
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
3
 *
 
4
 * Copyright 2000-2009 The OpenLDAP Foundation.
 
5
 * All rights reserved.
 
6
 *
 
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.
 
10
 *
 
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>.
 
14
 */
 
15
/* ACKNOWLEDGEMENT:
 
16
 * This work was initially developed by Pierangelo Masarati for
 
17
 * inclusion in OpenLDAP Software.
 
18
 */
 
19
 
 
20
#include <portable.h>
 
21
 
 
22
#include <stdio.h>
 
23
 
 
24
#ifdef HAVE_PWD_H
 
25
#include <pwd.h>
 
26
#endif
 
27
 
 
28
#include "rewrite-int.h"
 
29
#include "rewrite-map.h"
 
30
 
 
31
static int num_mappers;
 
32
static const rewrite_mapper **mappers;
 
33
#define MAPPER_ALLOC    8
 
34
 
 
35
struct rewrite_map *
 
36
rewrite_map_parse(
 
37
                struct rewrite_info *info,
 
38
                const char *string,
 
39
                const char **currpos
 
40
)
 
41
{
 
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;
 
47
 
 
48
        assert( info != NULL );
 
49
        assert( string != NULL );
 
50
        assert( currpos != NULL );
 
51
 
 
52
        *currpos = NULL;
 
53
 
 
54
        /*
 
55
         * Go to the end of the map invocation (the right closing brace)
 
56
         */
 
57
        for ( p = string, cnt = 1; p[ 0 ] != '\0' && cnt > 0; p++ ) {
 
58
                if ( IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
 
59
                        /*
 
60
                         * '%' marks the beginning of a new map
 
61
                         */
 
62
                        if ( p[ 1 ] == '{' ) {
 
63
                                cnt++;
 
64
                        /*
 
65
                         * '%' followed by a digit may mark the beginning
 
66
                         * of an old map
 
67
                         */
 
68
                        } else if ( isdigit( (unsigned char) p[ 1 ] ) && p[ 2 ] == '{' ) {
 
69
                                cnt++;
 
70
                                p++;
 
71
                        }
 
72
 
 
73
                        if ( p[ 1 ] != '\0' ) {
 
74
                                p++;
 
75
                        }
 
76
 
 
77
                } else if ( p[ 0 ] == '}' ) {
 
78
                        cnt--;
 
79
                }
 
80
        }
 
81
        if ( cnt != 0 ) {
 
82
                return NULL;
 
83
        }
 
84
        *currpos = p;
 
85
        
 
86
        /*
 
87
         * Copy the map invocation
 
88
         */
 
89
        l = p - string - 1;
 
90
        s = calloc( sizeof( char ), l + 1 );
 
91
        if ( s == NULL ) {
 
92
                return NULL;
 
93
        }
 
94
        AC_MEMCPY( s, string, l );
 
95
        s[ l ] = 0;
 
96
 
 
97
        /*
 
98
         * Isolate the map name (except for variable deref)
 
99
         */
 
100
        switch ( s[ 0 ] ) {
 
101
        case REWRITE_OPERATOR_VARIABLE_GET:
 
102
        case REWRITE_OPERATOR_PARAM_GET:
 
103
                break;
 
104
 
 
105
        default:
 
106
                begin = strchr( s, '(' );
 
107
                if ( begin == NULL ) {
 
108
                        rc = -1;
 
109
                        goto cleanup;
 
110
                }
 
111
                begin[ 0 ] = '\0';
 
112
                begin++;
 
113
                break;
 
114
        }
 
115
 
 
116
        /*
 
117
         * Check for special map types
 
118
         */
 
119
        p = s;
 
120
        switch ( p[ 0 ] ) {
 
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:
 
126
                p++;
 
127
                break;
 
128
        }
 
129
 
 
130
        /*
 
131
         * Variable set and get may be repeated to indicate session-wide
 
132
         * instead of operation-wide variables
 
133
         */
 
134
        switch ( p[ 0 ] ) {
 
135
        case REWRITE_OPERATOR_VARIABLE_SET:
 
136
        case REWRITE_OPERATOR_VARIABLE_GET:
 
137
                p++;
 
138
                break;
 
139
        }
 
140
 
 
141
        /*
 
142
         * Variable get token can be appended to variable set to mean store
 
143
         * AND rewrite
 
144
         */
 
145
        if ( p[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
 
146
                p++;
 
147
        }
 
148
        
 
149
        /*
 
150
         * Check the syntax of the variable name
 
151
         */
 
152
        if ( !isalpha( (unsigned char) p[ 0 ] ) ) {
 
153
                rc = -1;
 
154
                goto cleanup;
 
155
        }
 
156
        for ( p++; p[ 0 ] != '\0'; p++ ) {
 
157
                if ( !isalnum( (unsigned char) p[ 0 ] ) ) {
 
158
                        rc = -1;
 
159
                        goto cleanup;
 
160
                }
 
161
        }
 
162
 
 
163
        /*
 
164
         * Isolate the argument of the map (except for variable deref)
 
165
         */
 
166
        switch ( s[ 0 ] ) {
 
167
        case REWRITE_OPERATOR_VARIABLE_GET:
 
168
        case REWRITE_OPERATOR_PARAM_GET:
 
169
                break;
 
170
 
 
171
        default:
 
172
                end = strrchr( begin, ')' );
 
173
                if ( end == NULL ) {
 
174
                        rc = -1;
 
175
                        goto cleanup;
 
176
                }
 
177
                end[ 0 ] = '\0';
 
178
 
 
179
                /*
 
180
                 * Compile the substitution pattern of the map argument
 
181
                 */
 
182
                subst = rewrite_subst_compile( info, begin );
 
183
                if ( subst == NULL ) {
 
184
                        rc = -1;
 
185
                        goto cleanup;
 
186
                }
 
187
                break;
 
188
        }
 
189
 
 
190
        /*
 
191
         * Create the map
 
192
         */
 
193
        map = calloc( sizeof( struct rewrite_map ), 1 );
 
194
        if ( map == NULL ) {
 
195
                rc = -1;
 
196
                goto cleanup;
 
197
        }
 
198
        memset( map, 0, sizeof( struct rewrite_map ) );
 
199
        
 
200
#ifdef USE_REWRITE_LDAP_PVT_THREADS
 
201
        if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
 
202
                rc = -1;
 
203
                goto cleanup;
 
204
        }
 
205
        ++mtx;
 
206
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
 
207
                        
 
208
        /*
 
209
         * No subst for variable deref
 
210
         */
 
211
        switch ( s[ 0 ] ) {
 
212
        case REWRITE_OPERATOR_VARIABLE_GET:
 
213
        case REWRITE_OPERATOR_PARAM_GET:
 
214
                break;
 
215
 
 
216
        default:
 
217
                map->lm_subst = subst;
 
218
                break;
 
219
        }
 
220
 
 
221
        /*
 
222
         * Parses special map types
 
223
         */
 
224
        switch ( s[ 0 ] ) {
 
225
        
 
226
        /*
 
227
         * Subcontext
 
228
         */
 
229
        case REWRITE_OPERATOR_SUBCONTEXT:               /* '>' */
 
230
 
 
231
                /*
 
232
                 * Fetch the rewrite context
 
233
                 * it MUST have been defined previously
 
234
                 */
 
235
                map->lm_type = REWRITE_MAP_SUBCONTEXT;
 
236
                map->lm_name = strdup( s + 1 );
 
237
                if ( map->lm_name == NULL ) {
 
238
                        rc = -1;
 
239
                        goto cleanup;
 
240
                }
 
241
                map->lm_data = rewrite_context_find( info, s + 1 );
 
242
                if ( map->lm_data == NULL ) {
 
243
                        rc = -1;
 
244
                        goto cleanup;
 
245
                }
 
246
                break;
 
247
 
 
248
        /*
 
249
         * External command (not implemented yet)
 
250
         */
 
251
        case REWRITE_OPERATOR_COMMAND:          /* '|' */
 
252
                rc = -1;
 
253
                goto cleanup;
 
254
        
 
255
        /*
 
256
         * Variable set
 
257
         */
 
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 );
 
263
                        } else {
 
264
                                map->lm_type = REWRITE_MAP_SET_SESN_VAR;
 
265
                                map->lm_name = strdup( s + 2 );
 
266
                        }
 
267
                } else {
 
268
                        if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
 
269
                                map->lm_type = REWRITE_MAP_SETW_OP_VAR;
 
270
                                map->lm_name = strdup( s + 2 );
 
271
                        } else {
 
272
                                map->lm_type = REWRITE_MAP_SET_OP_VAR;
 
273
                                map->lm_name = strdup( s + 1 );
 
274
                        }
 
275
                }
 
276
                if ( map->lm_name == NULL ) {
 
277
                        rc = -1;
 
278
                        goto cleanup;
 
279
                }
 
280
                break;
 
281
        
 
282
        /*
 
283
         * Variable dereference
 
284
         */
 
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 );
 
289
                } else {
 
290
                        map->lm_type = REWRITE_MAP_GET_OP_VAR;
 
291
                        map->lm_name = strdup( s + 1 );
 
292
                }
 
293
                if ( map->lm_name == NULL ) {
 
294
                        rc = -1;
 
295
                        goto cleanup;
 
296
                }
 
297
                break;
 
298
        
 
299
        /*
 
300
         * Parameter
 
301
         */
 
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 ) {
 
306
                        rc = -1;
 
307
                        goto cleanup;
 
308
                }
 
309
                break;
 
310
        
 
311
        /*
 
312
         * Built-in map
 
313
         */
 
314
        default:
 
315
                map->lm_type = REWRITE_MAP_BUILTIN;
 
316
                map->lm_name = strdup( s );
 
317
                if ( map->lm_name == NULL ) {
 
318
                        rc = -1;
 
319
                        goto cleanup;
 
320
                }
 
321
                map->lm_data = rewrite_builtin_map_find( info, s );
 
322
                if ( map->lm_data == NULL ) {
 
323
                        rc = -1;
 
324
                        goto cleanup;
 
325
                }
 
326
                break;
 
327
 
 
328
        }
 
329
 
 
330
cleanup:
 
331
        free( s );
 
332
        if ( rc ) {
 
333
                if ( subst != NULL ) {
 
334
                        free( subst );
 
335
                }
 
336
                if ( map ) {
 
337
#ifdef USE_REWRITE_LDAP_PVT_THREADS
 
338
                        if ( mtx ) {
 
339
                                ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
 
340
                        }
 
341
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
 
342
 
 
343
                        if ( map->lm_name ) {
 
344
                                free( map->lm_name );
 
345
                                map->lm_name = NULL;
 
346
                        }
 
347
                        free( map );
 
348
                        map = NULL;
 
349
                }
 
350
        }
 
351
 
 
352
        return map;
 
353
}
 
354
 
 
355
/*
 
356
 * Applies the new map type
 
357
 */
 
358
int
 
359
rewrite_map_apply(
 
360
                struct rewrite_info *info,
 
361
                struct rewrite_op *op,
 
362
                struct rewrite_map *map,
 
363
                struct berval *key,
 
364
                struct berval *val
 
365
)
 
366
{
 
367
        int rc = REWRITE_SUCCESS;
 
368
 
 
369
        assert( info != NULL );
 
370
        assert( op != NULL );
 
371
        assert( map != NULL );
 
372
        assert( key != NULL );
 
373
        assert( val != NULL );
 
374
 
 
375
        val->bv_val = NULL;
 
376
        val->bv_len = 0;
 
377
        
 
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;
 
386
                                key->bv_val = NULL;
 
387
                        } else {
 
388
                                val->bv_len = strlen( val->bv_val );
 
389
                        }
 
390
                }
 
391
                break;
 
392
 
 
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,
 
396
                                key->bv_val, 1 )
 
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( "" );
 
401
                        } else {
 
402
                                val->bv_val = strdup( key->bv_val );
 
403
                                val->bv_len = key->bv_len;
 
404
                        }
 
405
                        if ( val->bv_val == NULL ) {
 
406
                                rc = REWRITE_ERR;
 
407
                        }
 
408
                }
 
409
                break;
 
410
        
 
411
        case REWRITE_MAP_GET_OP_VAR: {
 
412
                struct rewrite_var *var;
 
413
 
 
414
                var = rewrite_var_find( op->lo_vars, map->lm_name );
 
415
                if ( var == NULL ) {
 
416
                        rc = REWRITE_ERR;
 
417
                } else {
 
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 ) {
 
421
                                rc = REWRITE_ERR;
 
422
                        }
 
423
                }
 
424
                break;  
 
425
        }
 
426
 
 
427
        case REWRITE_MAP_SET_SESN_VAR:
 
428
        case REWRITE_MAP_SETW_SESN_VAR:
 
429
                if ( op->lo_cookie == NULL ) {
 
430
                        rc = REWRITE_ERR;
 
431
                        break;
 
432
                }
 
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( "" );
 
438
                        } else {
 
439
                                val->bv_val = strdup( key->bv_val );
 
440
                                val->bv_len = key->bv_len;
 
441
                        }
 
442
                        if ( val->bv_val == NULL ) {
 
443
                                rc = REWRITE_ERR;
 
444
                        }
 
445
                }
 
446
                break;
 
447
 
 
448
        case REWRITE_MAP_GET_SESN_VAR:
 
449
                rc = rewrite_session_var_get( info, op->lo_cookie,
 
450
                                map->lm_name, val );
 
451
                break;          
 
452
 
 
453
        case REWRITE_MAP_GET_PARAM:
 
454
                rc = rewrite_param_get( info, map->lm_name, val );
 
455
                break;
 
456
 
 
457
        case REWRITE_MAP_BUILTIN: {
 
458
                struct rewrite_builtin_map *bmap = map->lm_data;
 
459
 
 
460
                if ( bmap->lb_mapper && bmap->lb_mapper->rm_apply )
 
461
                        rc = bmap->lb_mapper->rm_apply( bmap->lb_private, key->bv_val,
 
462
                                val );
 
463
                else
 
464
                        rc = REWRITE_ERR;
 
465
                        break;
 
466
                break;
 
467
        }
 
468
 
 
469
        default:
 
470
                rc = REWRITE_ERR;
 
471
                break;
 
472
        }
 
473
 
 
474
        return rc;
 
475
}
 
476
 
 
477
void
 
478
rewrite_builtin_map_free(
 
479
                void *tmp
 
480
)
 
481
{
 
482
        struct rewrite_builtin_map *map = ( struct rewrite_builtin_map * )tmp;
 
483
 
 
484
        assert( map != NULL );
 
485
 
 
486
        if ( map->lb_mapper && map->lb_mapper->rm_destroy )
 
487
                map->lb_mapper->rm_destroy( map->lb_private );
 
488
 
 
489
        free( map->lb_name );
 
490
        free( map );
 
491
}
 
492
 
 
493
int
 
494
rewrite_map_destroy(
 
495
                struct rewrite_map **pmap
 
496
)
 
497
{
 
498
        struct rewrite_map *map;
 
499
        
 
500
        assert( pmap != NULL );
 
501
        assert( *pmap != NULL );
 
502
 
 
503
        map = *pmap;
 
504
 
 
505
#ifdef USE_REWRITE_LDAP_PVT_THREADS
 
506
        ldap_pvt_thread_mutex_lock( &map->lm_mutex );
 
507
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
 
508
 
 
509
        if ( map->lm_name ) {
 
510
                free( map->lm_name );
 
511
                map->lm_name = NULL;
 
512
        }
 
513
 
 
514
        if ( map->lm_subst ) {
 
515
                rewrite_subst_destroy( &map->lm_subst );
 
516
        }
 
517
 
 
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 */
 
522
 
 
523
        free( map );
 
524
        *pmap = NULL;
 
525
        
 
526
        return 0;
 
527
}
 
528
 
 
529
/* ldapmap.c */
 
530
extern const rewrite_mapper rewrite_ldap_mapper;
 
531
 
 
532
const rewrite_mapper *
 
533
rewrite_mapper_find(
 
534
        const char *name
 
535
)
 
536
{
 
537
        int i;
 
538
 
 
539
        if ( !strcasecmp( name, "ldap" ))
 
540
                return &rewrite_ldap_mapper;
 
541
 
 
542
        for (i=0; i<num_mappers; i++)
 
543
                if ( !strcasecmp( name, mappers[i]->rm_name ))
 
544
                        return mappers[i];
 
545
        return NULL;
 
546
}
 
547
 
 
548
int
 
549
rewrite_mapper_register(
 
550
        const rewrite_mapper *map
 
551
)
 
552
{
 
553
        if ( num_mappers % MAPPER_ALLOC == 0 ) {
 
554
                const rewrite_mapper **mnew;
 
555
                mnew = realloc( mappers, (num_mappers + MAPPER_ALLOC) *
 
556
                        sizeof( rewrite_mapper * ));
 
557
                if ( mnew )
 
558
                        mappers = mnew;
 
559
                else
 
560
                        return -1;
 
561
        }
 
562
        mappers[num_mappers++] = map;
 
563
        return 0;
 
564
}
 
565
 
 
566
int
 
567
rewrite_mapper_unregister(
 
568
        const rewrite_mapper *map
 
569
)
 
570
{
 
571
        int i;
 
572
 
 
573
        for (i = 0; i<num_mappers; i++) {
 
574
                if ( mappers[i] == map ) {
 
575
                        num_mappers--;
 
576
                        mappers[i] = mappers[num_mappers];
 
577
                        mappers[num_mappers] = NULL;
 
578
                        return 0;
 
579
                }
 
580
        }
 
581
        /* not found */
 
582
        return -1;
 
583
}