]> git.sur5r.net Git - openldap/blob - libraries/librewrite/config.c
notices and acknowledgements
[openldap] / libraries / librewrite / config.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2003 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 "rewrite-int.h"
23 #include "rewrite-map.h"
24
25 /*
26  * Parses a plugin map
27  */
28 static int
29 rewrite_parse_builtin_map(
30                 struct rewrite_info *info,
31                 const char *fname,
32                 int lineno,
33                 int argc,
34                 char **argv
35 );
36
37 /*
38  * Parses a config line and takes actions to fit content in rewrite structure;
39  * lines handled are of the form:
40  *
41  *      rewriteEngine           {on|off}
42  *      rewriteMaxPasses        numPasses
43  *      rewriteContext          contextName [alias aliasedContextName]
44  *      rewriteRule             pattern substPattern [ruleFlags]
45  *      rewriteMap              mapType mapName [mapArgs]
46  *      rewriteParam            paramName paramValue
47  */
48 int
49 rewrite_parse(
50                 struct rewrite_info *info,
51                 const char *fname,
52                 int lineno,
53                 int argc,
54                 char **argv
55 )
56 {
57         int rc = -1;
58
59         assert( info != NULL );
60         assert( fname != NULL );
61         assert( argv != NULL );
62         assert( argc > 0 );
63         
64         /*
65          * Switch on the rewrite engine
66          */
67         if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) {
68                 if ( argc < 2 ) {
69                         Debug( LDAP_DEBUG_ANY,
70                                         "[%s:%d] rewriteEngine needs 'state'\n%s",
71                                         fname, lineno, "" );
72                         return -1;
73
74                 } else if ( argc > 2 ) {
75                         Debug( LDAP_DEBUG_ANY,
76                                         "[%s:%d] extra fields in rewriteEngine"
77                                         " will be discarded\n%s",
78                                         fname, lineno, "" );
79                 }
80
81                 if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) {
82                         info->li_state = REWRITE_ON;
83
84                 } else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) {
85                         info->li_state = REWRITE_OFF;
86
87                 } else {
88                         Debug( LDAP_DEBUG_ANY,
89                                         "[%s:%d] unknown 'state' in rewriteEngine;"
90                                         " assuming 'on'\n%s",
91                                         fname, lineno, "" );
92                         info->li_state = REWRITE_ON;
93                 }
94                 rc = REWRITE_SUCCESS;
95         
96         /*
97          * Alter max passes
98          */
99         } else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) {
100                 if ( argc < 2 ) {
101                         Debug( LDAP_DEBUG_ANY,
102                                         "[%s:%d] rewriteMaxPasses needs 'value'\n%s",
103                                         fname, lineno, "" );
104                         return -1;
105                 }
106                 info->li_max_passes = atoi( argv[ 1 ] );
107                 rc = REWRITE_SUCCESS;
108         
109         /*
110          * Start a new rewrite context and set current context
111          */
112         } else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
113                 if ( argc < 2 ) {
114                         Debug( LDAP_DEBUG_ANY,
115                                         "[%s:%d] rewriteContext needs 'name'\n%s",
116                                         fname, lineno, "" );
117                         return -1;
118                 } 
119
120                 /*
121                  * Checks for existence (lots of contexts should be
122                  * available by default ...)
123                  */
124                  rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] );
125                  if ( rewrite_int_curr_context == NULL ) {
126                          rewrite_int_curr_context = rewrite_context_create( info,
127                                          argv[ 1 ] );                       
128                  }
129                  if ( rewrite_int_curr_context == NULL ) {
130                          return -1;
131                  }
132                                                 
133                  if ( argc > 2 ) {
134
135                          /*
136                           * A context can alias another (e.g., the `builtin'
137                           * contexts for backend operations, if not defined,
138                           * alias the `default' rewrite context (with the
139                           * notable exception of the searchResult context,
140                           * which can be undefined)
141                           */
142                          if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
143                                  struct rewrite_context *aliased;
144                                  
145                                  if ( argc == 3 ) {
146                                          Debug( LDAP_DEBUG_ANY,
147                                                          "[%s:%d] rewriteContext"
148                                                          " needs 'name' after"
149                                                          " 'alias'\n%s",
150                                                          fname, lineno, "" );
151                                          return -1;
152
153                                  } else if ( argc > 4 ) {
154                                          Debug( LDAP_DEBUG_ANY,
155                                                          "[%s:%d] extra fields in"
156                                                          " rewriteContext"
157                                                          " after aliased name"
158                                                          " will be"
159                                                          " discarded\n%s",
160                                                          fname, lineno, "" );
161                                  }
162                                  
163                                  aliased = rewrite_context_find( info, 
164                                                  argv[ 3 ] );
165                                  if ( aliased == NULL ) {
166                                          Debug( LDAP_DEBUG_ANY,
167                                                          "[%s:%d] aliased"
168                                                          " rewriteContext '%s'"
169                                                          " does not exists\n",
170                                                          fname, lineno,
171                                                          argv[ 3 ] );
172                                          return -1;
173                                  }
174                                  
175                                  rewrite_int_curr_context->lc_alias = aliased;
176                                  rewrite_int_curr_context = aliased;
177
178                          } else {
179                                  Debug( LDAP_DEBUG_ANY,
180                                                  "[%s:%d] extra fields"
181                                                  " in rewriteContext"
182                                                  " will be discarded\n%s",
183                                                  fname, lineno, "" );
184                          }
185                  }
186                  rc = REWRITE_SUCCESS;
187                  
188         /*
189          * Compile a rule in current context
190          */
191         } else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
192                 if ( argc < 3 ) {
193                         Debug( LDAP_DEBUG_ANY,
194                                         "[%s:%d] rewriteRule needs 'pattern'"
195                                         " 'subst' ['flags']\n%s",
196                                         fname, lineno, "" );
197                         return -1;
198
199                 } else if ( argc > 4 ) {
200                         Debug( LDAP_DEBUG_ANY,
201                                         "[%s:%d] extra fields in rewriteRule"
202                                         " will be discarded\n%s",
203                                         fname, lineno, "" );
204                 }
205
206                 if ( rewrite_int_curr_context == NULL ) {
207                         Debug( LDAP_DEBUG_ANY,
208                                         "[%s:%d] rewriteRule outside a"
209                                         " context; will add to default\n%s",
210                                         fname, lineno, "" );
211                         rewrite_int_curr_context = rewrite_context_find( info,
212                                         REWRITE_DEFAULT_CONTEXT );
213
214                         /*
215                          * Default context MUST exist in a properly initialized
216                          * struct rewrite_info
217                          */
218                         assert( rewrite_int_curr_context != NULL );
219                 }
220                 
221                 rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ],
222                                 argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
223         
224         /*
225          * Add a plugin map to the map tree
226          */
227         } else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
228                 if ( argc < 3 ) {
229                         Debug( LDAP_DEBUG_ANY,
230                                         "[%s:%d] rewriteMap needs at least 'type'"
231                                         " and 'name' ['args']\n%s",
232                                         fname, lineno, "" );
233                         return -1;
234                 }
235
236                 rc = rewrite_parse_builtin_map( info, fname, lineno,
237                                 argc, argv );
238
239         /*
240          * Set the value of a global scope parameter
241          */
242         } else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
243                 if ( argc < 3 ) {
244                         Debug( LDAP_DEBUG_ANY,
245                                         "[%s:%d] rewriteParam needs 'name'"
246                                         " and 'value'\n%s",
247                                         fname, lineno, "" );
248                         return -1;
249                 }
250
251                 rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
252                 
253         /*
254          * Error
255          */
256         } else {
257                 Debug( LDAP_DEBUG_ANY,
258                                 "[%s:%d] unknown command '%s'\n",
259                                 fname, lineno, "" );
260                 return -1;
261         }
262
263         return rc;
264 }
265
266 /*
267  * Compares two maps
268  */
269 static int
270 rewrite_builtin_map_cmp(
271                 const void *c1,
272                 const void *c2
273 )
274 {
275         const struct rewrite_builtin_map *m1, *m2;
276
277         m1 = ( const struct rewrite_builtin_map * )c1;
278         m2 = ( const struct rewrite_builtin_map * )c2;
279
280         assert( m1 != NULL );
281         assert( m2 != NULL );
282         assert( m1->lb_name != NULL );
283         assert( m2->lb_name != NULL );
284
285         return strcasecmp( m1->lb_name, m2->lb_name );
286 }
287
288 /*
289  * Duplicate map ?
290  */
291 static int
292 rewrite_builtin_map_dup(
293                         void *c1,
294                         void *c2
295 )
296 {
297         struct rewrite_builtin_map *m1, *m2;
298
299         m1 = ( struct rewrite_builtin_map * )c1;
300         m2 = ( struct rewrite_builtin_map * )c2;
301
302         assert( m1 != NULL );
303         assert( m2 != NULL );
304         assert( m1->lb_name != NULL );
305         assert( m2->lb_name != NULL );
306
307         return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
308 }
309
310 /*
311  * Adds a map to the info map tree
312  */
313 static int
314 rewrite_builtin_map_insert(
315                 struct rewrite_info *info,
316                 struct rewrite_builtin_map *map
317 )
318 {
319         /*
320          * May need a mutex?
321          */
322         return avl_insert( &info->li_maps, ( caddr_t )map,
323                         rewrite_builtin_map_cmp,
324                         rewrite_builtin_map_dup );
325 }
326
327 /*
328  * Retrieves a map
329  */
330 struct rewrite_builtin_map *
331 rewrite_builtin_map_find(
332                 struct rewrite_info *info,
333                 const char *name
334 )
335 {
336         struct rewrite_builtin_map tmp;
337
338         assert( info != NULL );
339         assert( name != NULL );
340
341         tmp.lb_name = ( char * )name;
342
343         return ( struct rewrite_builtin_map * )avl_find( info->li_maps,
344                         ( caddr_t )&tmp, rewrite_builtin_map_cmp );
345 }
346
347 /*
348  * Parses a plugin map
349  */
350 static int
351 rewrite_parse_builtin_map(
352                 struct rewrite_info *info,
353                 const char *fname,
354                 int lineno,
355                 int argc,
356                 char **argv
357 )
358 {
359         struct rewrite_builtin_map *map;
360         
361 #define MAP_TYPE        1
362 #define MAP_NAME        2
363         
364         assert( info != NULL );
365         assert( fname != NULL );
366         assert( argc > 2 );
367         assert( argv != NULL );
368         assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
369
370         map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
371         if ( map == NULL ) {
372                 return REWRITE_ERR;
373         }
374
375         map->lb_name = strdup( argv[ MAP_NAME ] );
376         if ( map->lb_name == NULL ) {
377                 free( map );
378                 return REWRITE_ERR;
379         }
380         
381         /*
382          * Built-in ldap map
383          */
384         if ( strcasecmp( argv[ MAP_TYPE ], "ldap" ) == 0 ) {
385                 map->lb_type = REWRITE_BUILTIN_MAP_LDAP;
386
387 #ifdef USE_REWRITE_LDAP_PVT_THREADS
388                 if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
389                         free( map->lb_name );
390                         free( map );
391                         return REWRITE_ERR;
392                 }
393 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
394                 
395                 map->lb_private = map_ldap_parse( info, fname, lineno,
396                                 argc - 3, argv + 3 );
397                 
398         /* 
399          * Error
400          */     
401         } else {
402                 Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s",
403                                 fname, lineno, "" );
404                 return -1;
405         }
406
407         return rewrite_builtin_map_insert( info, map );
408 }