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