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