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 */ 29static int 30rewrite_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 */ 51static int 52rewrite_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 */ 73static void 74rewrite_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 */ 94int 95rewrite_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 */ 106struct rewrite_var * 107rewrite_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 121int 122rewrite_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 */ 172struct rewrite_var * 173rewrite_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 231cleanup:; 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 */ 244struct rewrite_var * 245rewrite_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