]> git.sur5r.net Git - openldap/blob - libraries/librewrite/info.c
Fix previous commit
[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 *__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         __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 *info
106 )
107 {
108         assert( info != NULL );
109         
110         rewrite_session_destroy( info );
111
112         rewrite_param_destroy( info );
113         
114 #ifdef USE_REWRITE_LDAP_PVT_THREADS
115         ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
116         ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
117 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
118
119         return REWRITE_SUCCESS;
120 }
121
122 /*
123  * Rewrites a string according to context.
124  * If the engine is off, OK is returned, but the return string will be NULL.
125  * In case of 'unwilling to perform', UNWILLING is returned, and the
126  * return string will also be null. The same in case of error.
127  * Otherwise, OK is returned, and result will hold a newly allocated string
128  * with the rewriting.
129  * 
130  * What to do in case of non-existing rewrite context is still an issue.
131  * Four possibilities:
132  *      - error, 
133  *      - ok with NULL result, 
134  *      - ok with copy of string as result,
135  *      - use the default rewrite context.
136  */
137 int
138 rewrite(
139                 struct rewrite_info *info,
140                 const char *rewriteContext,
141                 const char *string,
142                 char **result
143 )
144 {
145         return rewrite_session( info, rewriteContext, 
146                         string, NULL, result );
147 }
148
149 int
150 rewrite_session(
151                 struct rewrite_info *info,
152                 const char *rewriteContext,
153                 const char *string,
154                 const void *cookie,
155                 char **result
156 )
157 {
158         struct rewrite_context *context;
159         struct rewrite_op op = { 0, 0, NULL, NULL, NULL, NULL };
160         int rc;
161         
162         assert( info != NULL );
163         assert( rewriteContext != NULL );
164         assert( string != NULL );
165         assert( result != NULL );
166
167         /*
168          * cookie can be null; means: don't care about session stuff
169          */
170
171         *result = NULL;
172         op.lo_cookie = cookie;
173         
174         /*
175          * Engine not on means no failure, but explicit no rewriting
176          */
177         if ( info->li_state != REWRITE_ON ) {
178                 rc = REWRITE_REGEXEC_OK;
179                 goto rc_return;
180         }
181         
182         /*
183          * Undefined context means no rewriting also
184          * (conservative, are we sure it's what we want?)
185          */
186         context = rewrite_context_find( info, rewriteContext );
187         if ( context == NULL ) {
188                 switch ( info->li_rewrite_mode ) {
189                 case REWRITE_MODE_ERR:
190                         rc = REWRITE_REGEXEC_ERR;
191                         goto rc_return;
192                 case REWRITE_MODE_OK:
193                         rc = REWRITE_REGEXEC_OK;
194                         goto rc_return;
195                 case REWRITE_MODE_COPY_INPUT:
196                         *result = strdup( string );
197                         rc = REWRITE_REGEXEC_OK;
198                         goto rc_return;
199                 case REWRITE_MODE_USE_DEFAULT:
200                         context = rewrite_context_find( info,
201                                         REWRITE_DEFAULT_CONTEXT );
202                         break;
203                 }
204         }
205         
206         op.lo_string = strdup( string );
207         if ( op.lo_string == NULL ) {
208                 rc = REWRITE_REGEXEC_ERR;
209                 goto rc_return;
210         }
211         
212         /*
213          * Applies rewrite context
214          */
215         rc = rewrite_context_apply(info, &op, context, string, result );
216         assert( op.lo_depth == 0 );
217
218         /* ?!? */
219         free( op.lo_string );
220         
221         switch ( rc ) {
222         /*
223          * Success
224          */
225         case REWRITE_REGEXEC_OK:
226         case REWRITE_REGEXEC_STOP:
227                 /*
228                  * If rewrite succeeded return OK regardless of how
229                  * the successful rewriting was obtained!
230                  */
231                 rc = REWRITE_REGEXEC_OK;
232                 break;
233                 
234         
235         /*
236          * Internal or forced error, return = NULL; rc already OK.
237          */
238         case REWRITE_REGEXEC_UNWILLING:
239         case REWRITE_REGEXEC_ERR:
240         default:
241                 if ( *result != NULL ) {
242                         free( *result );
243                         *result = NULL;
244                 }
245         }
246
247 rc_return:;
248         if ( op.lo_vars ) {
249                 rewrite_var_delete( op.lo_vars );
250         }
251         
252         return rc;
253 }
254