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