]> git.sur5r.net Git - openldap/blob - libraries/librewrite/config.c
From HEAD
[openldap] / libraries / librewrite / config.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2004 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 [numPassesPerRule]
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
107                 info->li_max_passes = atoi( argv[ 1 ] );
108                 if ( info->li_max_passes <= 0 ) {
109                         Debug( LDAP_DEBUG_ANY,
110                                         "[%s:%d] negative or null rewriteMaxPasses'\n",
111                                         fname, lineno, 0 );
112                 }
113
114                 if ( argc > 2 ) {
115                         info->li_max_passes_per_rule = atoi( argv[ 2 ] );
116                         if ( info->li_max_passes_per_rule <= 0 ) {
117                                 Debug( LDAP_DEBUG_ANY,
118                                                 "[%s:%d] negative or null rewriteMaxPassesPerRule'\n",
119                                                 fname, lineno, 0 );
120                         }
121
122                 } else {
123                         info->li_max_passes_per_rule = info->li_max_passes;
124                 }
125                 rc = REWRITE_SUCCESS;
126         
127         /*
128          * Start a new rewrite context and set current context
129          */
130         } else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
131                 if ( argc < 2 ) {
132                         Debug( LDAP_DEBUG_ANY,
133                                         "[%s:%d] rewriteContext needs 'name'\n%s",
134                                         fname, lineno, "" );
135                         return -1;
136                 } 
137
138                 /*
139                  * Checks for existence (lots of contexts should be
140                  * available by default ...)
141                  */
142                  rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] );
143                  if ( rewrite_int_curr_context == NULL ) {
144                          rewrite_int_curr_context = rewrite_context_create( info,
145                                          argv[ 1 ] );                       
146                  }
147                  if ( rewrite_int_curr_context == NULL ) {
148                          return -1;
149                  }
150                                                 
151                  if ( argc > 2 ) {
152
153                          /*
154                           * A context can alias another (e.g., the `builtin'
155                           * contexts for backend operations, if not defined,
156                           * alias the `default' rewrite context (with the
157                           * notable exception of the searchResult context,
158                           * which can be undefined)
159                           */
160                          if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
161                                  struct rewrite_context *aliased;
162                                  
163                                  if ( argc == 3 ) {
164                                          Debug( LDAP_DEBUG_ANY,
165                                                          "[%s:%d] rewriteContext"
166                                                          " needs 'name' after"
167                                                          " 'alias'\n%s",
168                                                          fname, lineno, "" );
169                                          return -1;
170
171                                  } else if ( argc > 4 ) {
172                                          Debug( LDAP_DEBUG_ANY,
173                                                          "[%s:%d] extra fields in"
174                                                          " rewriteContext"
175                                                          " after aliased name"
176                                                          " will be"
177                                                          " discarded\n%s",
178                                                          fname, lineno, "" );
179                                  }
180                                  
181                                  aliased = rewrite_context_find( info, 
182                                                  argv[ 3 ] );
183                                  if ( aliased == NULL ) {
184                                          Debug( LDAP_DEBUG_ANY,
185                                                          "[%s:%d] aliased"
186                                                          " rewriteContext '%s'"
187                                                          " does not exists\n",
188                                                          fname, lineno,
189                                                          argv[ 3 ] );
190                                          return -1;
191                                  }
192                                  
193                                  rewrite_int_curr_context->lc_alias = aliased;
194                                  rewrite_int_curr_context = aliased;
195
196                          } else {
197                                  Debug( LDAP_DEBUG_ANY,
198                                                  "[%s:%d] extra fields"
199                                                  " in rewriteContext"
200                                                  " will be discarded\n%s",
201                                                  fname, lineno, "" );
202                          }
203                  }
204                  rc = REWRITE_SUCCESS;
205                  
206         /*
207          * Compile a rule in current context
208          */
209         } else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
210                 if ( argc < 3 ) {
211                         Debug( LDAP_DEBUG_ANY,
212                                         "[%s:%d] rewriteRule needs 'pattern'"
213                                         " 'subst' ['flags']\n%s",
214                                         fname, lineno, "" );
215                         return -1;
216
217                 } else if ( argc > 4 ) {
218                         Debug( LDAP_DEBUG_ANY,
219                                         "[%s:%d] extra fields in rewriteRule"
220                                         " will be discarded\n%s",
221                                         fname, lineno, "" );
222                 }
223
224                 if ( rewrite_int_curr_context == NULL ) {
225                         Debug( LDAP_DEBUG_ANY,
226                                         "[%s:%d] rewriteRule outside a"
227                                         " context; will add to default\n%s",
228                                         fname, lineno, "" );
229                         rewrite_int_curr_context = rewrite_context_find( info,
230                                         REWRITE_DEFAULT_CONTEXT );
231
232                         /*
233                          * Default context MUST exist in a properly initialized
234                          * struct rewrite_info
235                          */
236                         assert( rewrite_int_curr_context != NULL );
237                 }
238                 
239                 rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ],
240                                 argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
241         
242         /*
243          * Add a plugin map to the map tree
244          */
245         } else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
246                 if ( argc < 3 ) {
247                         Debug( LDAP_DEBUG_ANY,
248                                         "[%s:%d] rewriteMap needs at least 'type'"
249                                         " and 'name' ['args']\n%s",
250                                         fname, lineno, "" );
251                         return -1;
252                 }
253
254                 rc = rewrite_parse_builtin_map( info, fname, lineno,
255                                 argc, argv );
256
257         /*
258          * Set the value of a global scope parameter
259          */
260         } else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
261                 if ( argc < 3 ) {
262                         Debug( LDAP_DEBUG_ANY,
263                                         "[%s:%d] rewriteParam needs 'name'"
264                                         " and 'value'\n%s",
265                                         fname, lineno, "" );
266                         return -1;
267                 }
268
269                 rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
270                 
271         /*
272          * Error
273          */
274         } else {
275                 Debug( LDAP_DEBUG_ANY,
276                                 "[%s:%d] unknown command '%s'\n",
277                                 fname, lineno, "" );
278                 return -1;
279         }
280
281         return rc;
282 }
283
284 /*
285  * Compares two maps
286  */
287 static int
288 rewrite_builtin_map_cmp(
289                 const void *c1,
290                 const void *c2
291 )
292 {
293         const struct rewrite_builtin_map *m1, *m2;
294
295         m1 = ( const struct rewrite_builtin_map * )c1;
296         m2 = ( const struct rewrite_builtin_map * )c2;
297
298         assert( m1 != NULL );
299         assert( m2 != NULL );
300         assert( m1->lb_name != NULL );
301         assert( m2->lb_name != NULL );
302
303         return strcasecmp( m1->lb_name, m2->lb_name );
304 }
305
306 /*
307  * Duplicate map ?
308  */
309 static int
310 rewrite_builtin_map_dup(
311                         void *c1,
312                         void *c2
313 )
314 {
315         struct rewrite_builtin_map *m1, *m2;
316
317         m1 = ( struct rewrite_builtin_map * )c1;
318         m2 = ( struct rewrite_builtin_map * )c2;
319
320         assert( m1 != NULL );
321         assert( m2 != NULL );
322         assert( m1->lb_name != NULL );
323         assert( m2->lb_name != NULL );
324
325         return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
326 }
327
328 /*
329  * Adds a map to the info map tree
330  */
331 static int
332 rewrite_builtin_map_insert(
333                 struct rewrite_info *info,
334                 struct rewrite_builtin_map *map
335 )
336 {
337         /*
338          * May need a mutex?
339          */
340         return avl_insert( &info->li_maps, ( caddr_t )map,
341                         rewrite_builtin_map_cmp,
342                         rewrite_builtin_map_dup );
343 }
344
345 /*
346  * Retrieves a map
347  */
348 struct rewrite_builtin_map *
349 rewrite_builtin_map_find(
350                 struct rewrite_info *info,
351                 const char *name
352 )
353 {
354         struct rewrite_builtin_map tmp;
355
356         assert( info != NULL );
357         assert( name != NULL );
358
359         tmp.lb_name = ( char * )name;
360
361         return ( struct rewrite_builtin_map * )avl_find( info->li_maps,
362                         ( caddr_t )&tmp, rewrite_builtin_map_cmp );
363 }
364
365 /*
366  * Parses a plugin map
367  */
368 static int
369 rewrite_parse_builtin_map(
370                 struct rewrite_info *info,
371                 const char *fname,
372                 int lineno,
373                 int argc,
374                 char **argv
375 )
376 {
377         struct rewrite_builtin_map *map;
378         
379 #define MAP_TYPE        1
380 #define MAP_NAME        2
381         
382         assert( info != NULL );
383         assert( fname != NULL );
384         assert( argc > 2 );
385         assert( argv != NULL );
386         assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
387
388         map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
389         if ( map == NULL ) {
390                 return REWRITE_ERR;
391         }
392
393         map->lb_name = strdup( argv[ MAP_NAME ] );
394         if ( map->lb_name == NULL ) {
395                 free( map );
396                 return REWRITE_ERR;
397         }
398         
399         /*
400          * Built-in ldap map
401          */
402         if ( strcasecmp( argv[ MAP_TYPE ], "ldap" ) == 0 ) {
403                 map->lb_type = REWRITE_BUILTIN_MAP_LDAP;
404
405 #ifdef USE_REWRITE_LDAP_PVT_THREADS
406                 if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
407                         free( map->lb_name );
408                         free( map );
409                         return REWRITE_ERR;
410                 }
411 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
412                 
413                 map->lb_private = map_ldap_parse( info, fname, lineno,
414                                 argc - 3, argv + 3 );
415                 
416         /* 
417          * Error
418          */     
419         } else {
420                 Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s",
421                                 fname, lineno, "" );
422                 return -1;
423         }
424
425         return rewrite_builtin_map_insert( info, map );
426 }