]> git.sur5r.net Git - openldap/blob - libraries/librewrite/info.c
Happy new year (belated)
[openldap] / libraries / librewrite / info.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2014 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
24 /*
25  * Global data
26  */
27
28 /*
29  * This becomes the running context for subsequent calls to
30  * rewrite_parse; it can be altered only by a 
31  * rewriteContext config line or by a change in info.
32  */
33 struct rewrite_context *rewrite_int_curr_context = NULL;
34
35 /*
36  * Inits the info
37  */
38 struct rewrite_info *
39 rewrite_info_init(
40                 int mode
41 )
42 {
43         struct rewrite_info *info;
44         struct rewrite_context *context;
45
46         switch ( mode ) {
47         case REWRITE_MODE_ERR:
48         case REWRITE_MODE_OK:
49         case REWRITE_MODE_COPY_INPUT:
50         case REWRITE_MODE_USE_DEFAULT:
51                 break;
52         default:
53                 mode = REWRITE_MODE_USE_DEFAULT;
54                 break;
55                 /* return NULL */
56         }
57
58         /*
59          * Resets the running context for parsing ...
60          */
61         rewrite_int_curr_context = NULL;
62
63         info = calloc( sizeof( struct rewrite_info ), 1 );
64         if ( info == NULL ) {
65                 return NULL;
66         }
67
68         info->li_state = REWRITE_DEFAULT;
69         info->li_max_passes = REWRITE_MAX_PASSES;
70         info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
71         info->li_rewrite_mode = mode;
72
73         /*
74          * Add the default (empty) rule
75          */
76         context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
77         if ( context == NULL ) {
78                 free( info );
79                 return NULL;
80         }
81
82 #ifdef USE_REWRITE_LDAP_PVT_THREADS
83         if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
84                 avl_free( info->li_context, rewrite_context_free );
85                 free( info );
86                 return NULL;
87         }
88         if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
89                 ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
90                 avl_free( info->li_context, rewrite_context_free );
91                 free( info );
92                 return NULL;
93         }
94 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
95         
96         return info;
97 }
98
99 /*
100  * Cleans up the info structure
101  */
102 int
103 rewrite_info_delete(
104                 struct rewrite_info **pinfo
105 )
106 {
107         struct rewrite_info     *info;
108
109         assert( pinfo != NULL );
110         assert( *pinfo != NULL );
111
112         info = *pinfo;
113         
114         if ( info->li_context ) {
115                 avl_free( info->li_context, rewrite_context_free );
116         }
117         info->li_context = NULL;
118
119         if ( info->li_maps ) {
120                 avl_free( info->li_maps, rewrite_builtin_map_free );
121         }
122         info->li_maps = NULL;
123
124         rewrite_session_destroy( info );
125
126 #ifdef USE_REWRITE_LDAP_PVT_THREADS
127         ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
128 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
129
130         rewrite_param_destroy( info );
131         
132 #ifdef USE_REWRITE_LDAP_PVT_THREADS
133         ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
134 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
135
136         free( info );
137         *pinfo = NULL;
138
139         return REWRITE_SUCCESS;
140 }
141
142 /*
143  * Rewrites a string according to context.
144  * If the engine is off, OK is returned, but the return string will be NULL.
145  * In case of 'unwilling to perform', UNWILLING is returned, and the
146  * return string will also be null. The same in case of error.
147  * Otherwise, OK is returned, and result will hold a newly allocated string
148  * with the rewriting.
149  * 
150  * What to do in case of non-existing rewrite context is still an issue.
151  * Four possibilities:
152  *      - error, 
153  *      - ok with NULL result, 
154  *      - ok with copy of string as result,
155  *      - use the default rewrite context.
156  */
157 int
158 rewrite(
159                 struct rewrite_info *info,
160                 const char *rewriteContext,
161                 const char *string,
162                 char **result
163 )
164 {
165         return rewrite_session( info, rewriteContext, 
166                         string, NULL, result );
167 }
168
169 int
170 rewrite_session(
171                 struct rewrite_info *info,
172                 const char *rewriteContext,
173                 const char *string,
174                 const void *cookie,
175                 char **result
176 )
177 {
178         struct rewrite_context *context;
179         struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
180         int rc;
181         
182         assert( info != NULL );
183         assert( rewriteContext != NULL );
184         assert( string != NULL );
185         assert( result != NULL );
186
187         /*
188          * cookie can be null; means: don't care about session stuff
189          */
190
191         *result = NULL;
192         op.lo_cookie = cookie;
193         
194         /*
195          * Engine not on means no failure, but explicit no rewriting
196          */
197         if ( info->li_state != REWRITE_ON ) {
198                 rc = REWRITE_REGEXEC_OK;
199                 goto rc_return;
200         }
201         
202         /*
203          * Undefined context means no rewriting also
204          * (conservative, are we sure it's what we want?)
205          */
206         context = rewrite_context_find( info, rewriteContext );
207         if ( context == NULL ) {
208                 switch ( info->li_rewrite_mode ) {
209                 case REWRITE_MODE_ERR:
210                         rc = REWRITE_REGEXEC_ERR;
211                         goto rc_return;
212                         
213                 case REWRITE_MODE_OK:
214                         rc = REWRITE_REGEXEC_OK;
215                         goto rc_return;
216
217                 case REWRITE_MODE_COPY_INPUT:
218                         *result = strdup( string );
219                         rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
220                         goto rc_return;
221
222                 case REWRITE_MODE_USE_DEFAULT:
223                         context = rewrite_context_find( info,
224                                         REWRITE_DEFAULT_CONTEXT );
225                         break;
226                 }
227         }
228
229 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
230         op.lo_string = strdup( string );
231         if ( op.lo_string == NULL ) {
232                 rc = REWRITE_REGEXEC_ERR;
233                 goto rc_return;
234         }
235 #endif
236         
237         /*
238          * Applies rewrite context
239          */
240         rc = rewrite_context_apply( info, &op, context, string, result );
241         assert( op.lo_depth == 0 );
242
243 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */        
244         free( op.lo_string );
245 #endif
246         
247         switch ( rc ) {
248         /*
249          * Success
250          */
251         case REWRITE_REGEXEC_OK:
252         case REWRITE_REGEXEC_STOP:
253                 /*
254                  * If rewrite succeeded return OK regardless of how
255                  * the successful rewriting was obtained!
256                  */
257                 rc = REWRITE_REGEXEC_OK;
258                 break;
259                 
260         
261         /*
262          * Internal or forced error, return = NULL; rc already OK.
263          */
264         case REWRITE_REGEXEC_UNWILLING:
265         case REWRITE_REGEXEC_ERR:
266                 if ( *result != NULL ) {
267                         if ( *result != string ) {
268                                 free( *result );
269                         }
270                         *result = NULL;
271                 }
272
273         default:
274                 break;
275         }
276
277 rc_return:;
278         if ( op.lo_vars ) {
279                 rewrite_var_delete( op.lo_vars );
280         }
281         
282         return rc;
283 }
284