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