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