Home | History | Annotate | Line # | Download | only in librewrite
      1 /*	$NetBSD: var.c,v 1.4 2025/09/05 21:16:23 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2000-2024 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
     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
     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
     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
     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 *
    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
    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 *
    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 *
    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