xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/info.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/info.c,v 1.15.2.3 2008/02/11 23:26:42 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2008 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 = REWRITE_REGEXEC_OK;
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 
285