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