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