1 /*	$NetBSD: var.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2000-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENT:
18  * This work was initially developed by Pierangelo Masarati for
19  * inclusion in OpenLDAP Software.
20  */
21 
22 #include <portable.h>
23 
24 #include "rewrite-int.h"
25 
26 /*
27  * Compares two vars
28  */
29 static int
rewrite_var_cmp(const void * c1,const void * c2)30 rewrite_var_cmp(
31 		const void *c1,
32 		const void *c2
33 )
34 {
35 	const struct rewrite_var *v1, *v2;
36 
37 	v1 = ( const struct rewrite_var * )c1;
38 	v2 = ( const struct rewrite_var * )c2;
39 
40 	assert( v1 != NULL );
41 	assert( v2 != NULL );
42 	assert( v1->lv_name != NULL );
43 	assert( v2->lv_name != NULL );
44 
45 	return strcasecmp( v1->lv_name, v2->lv_name );
46 }
47 
48 /*
49  * Duplicate var ?
50  */
51 static int
rewrite_var_dup(void * c1,void * c2)52 rewrite_var_dup(
53 		void *c1,
54 		void *c2
55 )
56 {
57 	struct rewrite_var *v1, *v2;
58 
59 	v1 = ( struct rewrite_var * )c1;
60 	v2 = ( struct rewrite_var * )c2;
61 
62 	assert( v1 != NULL );
63 	assert( v2 != NULL );
64 	assert( v1->lv_name != NULL );
65 	assert( v2->lv_name != NULL );
66 
67 	return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
68 }
69 
70 /*
71  * Frees a var
72  */
73 static void
rewrite_var_free(void * v_var)74 rewrite_var_free(
75 		void *v_var
76 )
77 {
78 	struct rewrite_var *var = v_var;
79 	assert( var != NULL );
80 
81 	assert( var->lv_name != NULL );
82 	assert( var->lv_value.bv_val != NULL );
83 
84 	if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
85 		free( var->lv_name );
86 	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
87 		free( var->lv_value.bv_val );
88 	free( var );
89 }
90 
91 /*
92  * Deletes a var tree
93  */
94 int
rewrite_var_delete(Avlnode * tree)95 rewrite_var_delete(
96 		Avlnode *tree
97 )
98 {
99 	ldap_avl_free( tree, rewrite_var_free );
100 	return REWRITE_SUCCESS;
101 }
102 
103 /*
104  * Finds a var
105  */
106 struct rewrite_var *
rewrite_var_find(Avlnode * tree,const char * name)107 rewrite_var_find(
108 		Avlnode *tree,
109 		const char *name
110 )
111 {
112 	struct rewrite_var var;
113 
114 	assert( name != NULL );
115 
116 	var.lv_name = ( char * )name;
117 	return ( struct rewrite_var * )ldap_avl_find( tree,
118 			( caddr_t )&var, rewrite_var_cmp );
119 }
120 
121 int
rewrite_var_replace(struct rewrite_var * var,const char * value,int flags)122 rewrite_var_replace(
123 		struct rewrite_var *var,
124 		const char *value,
125 		int flags
126 )
127 {
128 	ber_len_t	len;
129 
130 	assert( value != NULL );
131 
132 	len = strlen( value );
133 
134 	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
135 		if ( flags & REWRITE_VAR_COPY_VALUE ) {
136 			if ( len <= var->lv_value.bv_len ) {
137 				AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
138 
139 			} else {
140 				free( var->lv_value.bv_val );
141 				var->lv_value.bv_val = strdup( value );
142 			}
143 
144 		} else {
145 			free( var->lv_value.bv_val );
146 			var->lv_value.bv_val = (char *)value;
147 			var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
148 		}
149 
150 	} else {
151 		if ( flags & REWRITE_VAR_COPY_VALUE ) {
152 			var->lv_value.bv_val = strdup( value );
153 			var->lv_flags |= REWRITE_VAR_COPY_VALUE;
154 
155 		} else {
156 			var->lv_value.bv_val = (char *)value;
157 		}
158 	}
159 
160 	if ( var->lv_value.bv_val == NULL ) {
161 		return -1;
162 	}
163 
164 	var->lv_value.bv_len = len;
165 
166 	return 0;
167 }
168 
169 /*
170  * Inserts a newly created var
171  */
172 struct rewrite_var *
rewrite_var_insert_f(Avlnode ** tree,const char * name,const char * value,int flags)173 rewrite_var_insert_f(
174 		Avlnode **tree,
175 		const char *name,
176 		const char *value,
177 		int flags
178 )
179 {
180 	struct rewrite_var *var;
181 	int rc = 0;
182 
183 	assert( tree != NULL );
184 	assert( name != NULL );
185 	assert( value != NULL );
186 
187 	var = rewrite_var_find( *tree, name );
188 	if ( var != NULL ) {
189 		if ( flags & REWRITE_VAR_UPDATE ) {
190 			(void)rewrite_var_replace( var, value, flags );
191 			goto cleanup;
192 		}
193 		rc = -1;
194 		goto cleanup;
195 	}
196 
197 	var = calloc( sizeof( struct rewrite_var ), 1 );
198 	if ( var == NULL ) {
199 		return NULL;
200 	}
201 
202 	memset( var, 0, sizeof( struct rewrite_var ) );
203 
204 	if ( flags & REWRITE_VAR_COPY_NAME ) {
205 		var->lv_name = strdup( name );
206 		if ( var->lv_name == NULL ) {
207 			rc = -1;
208 			goto cleanup;
209 		}
210 		var->lv_flags |= REWRITE_VAR_COPY_NAME;
211 
212 	} else {
213 		var->lv_name = (char *)name;
214 	}
215 
216 	if ( flags & REWRITE_VAR_COPY_VALUE ) {
217 		var->lv_value.bv_val = strdup( value );
218 		if ( var->lv_value.bv_val == NULL ) {
219 			rc = -1;
220 			goto cleanup;
221 		}
222 		var->lv_flags |= REWRITE_VAR_COPY_VALUE;
223 
224 	} else {
225 		var->lv_value.bv_val = (char *)value;
226 	}
227 	var->lv_value.bv_len = strlen( value );
228 	rc = ldap_avl_insert( tree, ( caddr_t )var,
229 			rewrite_var_cmp, rewrite_var_dup );
230 
231 cleanup:;
232 	if ( rc != 0 && var ) {
233 		ldap_avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
234 		rewrite_var_free( var );
235 		var = NULL;
236 	}
237 
238 	return var;
239 }
240 
241 /*
242  * Sets/inserts a var
243  */
244 struct rewrite_var *
rewrite_var_set_f(Avlnode ** tree,const char * name,const char * value,int flags)245 rewrite_var_set_f(
246 		Avlnode **tree,
247 		const char *name,
248 		const char *value,
249 		int flags
250 )
251 {
252 	struct rewrite_var *var;
253 
254 	assert( tree != NULL );
255 	assert( name != NULL );
256 	assert( value != NULL );
257 
258 	var = rewrite_var_find( *tree, name );
259 	if ( var == NULL ) {
260 		if ( flags & REWRITE_VAR_INSERT ) {
261 			return rewrite_var_insert_f( tree, name, value, flags );
262 
263 		} else {
264 			return NULL;
265 		}
266 
267 	} else {
268 		assert( var->lv_value.bv_val != NULL );
269 
270 		(void)rewrite_var_replace( var, value, flags );
271 	}
272 
273 	return var;
274 }
275 
276