1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 2000-2011 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 * Compares two vars 26 */ 27static int 28rewrite_var_cmp( 29 const void *c1, 30 const void *c2 31) 32{ 33 const struct rewrite_var *v1, *v2; 34 35 v1 = ( const struct rewrite_var * )c1; 36 v2 = ( const struct rewrite_var * )c2; 37 38 assert( v1 != NULL ); 39 assert( v2 != NULL ); 40 assert( v1->lv_name != NULL ); 41 assert( v2->lv_name != NULL ); 42 43 return strcasecmp( v1->lv_name, v2->lv_name ); 44} 45 46/* 47 * Duplicate var ? 48 */ 49static int 50rewrite_var_dup( 51 void *c1, 52 void *c2 53) 54{ 55 struct rewrite_var *v1, *v2; 56 57 v1 = ( struct rewrite_var * )c1; 58 v2 = ( struct rewrite_var * )c2; 59 60 assert( v1 != NULL ); 61 assert( v2 != NULL ); 62 assert( v1->lv_name != NULL ); 63 assert( v2->lv_name != NULL ); 64 65 return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 ); 66} 67 68/* 69 * Frees a var 70 */ 71static void 72rewrite_var_free( 73 void *v_var 74) 75{ 76 struct rewrite_var *var = v_var; 77 assert( var != NULL ); 78 79 assert( var->lv_name != NULL ); 80 assert( var->lv_value.bv_val != NULL ); 81 82 if ( var->lv_flags & REWRITE_VAR_COPY_NAME ) 83 free( var->lv_name ); 84 if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) 85 free( var->lv_value.bv_val ); 86 free( var ); 87} 88 89/* 90 * Deletes a var tree 91 */ 92int 93rewrite_var_delete( 94 Avlnode *tree 95) 96{ 97 avl_free( tree, rewrite_var_free ); 98 return REWRITE_SUCCESS; 99} 100 101/* 102 * Finds a var 103 */ 104struct rewrite_var * 105rewrite_var_find( 106 Avlnode *tree, 107 const char *name 108) 109{ 110 struct rewrite_var var; 111 112 assert( name != NULL ); 113 114 var.lv_name = ( char * )name; 115 return ( struct rewrite_var * )avl_find( tree, 116 ( caddr_t )&var, rewrite_var_cmp ); 117} 118 119int 120rewrite_var_replace( 121 struct rewrite_var *var, 122 const char *value, 123 int flags 124) 125{ 126 ber_len_t len; 127 128 assert( value != NULL ); 129 130 len = strlen( value ); 131 132 if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) { 133 if ( flags & REWRITE_VAR_COPY_VALUE ) { 134 if ( len <= var->lv_value.bv_len ) { 135 AC_MEMCPY(var->lv_value.bv_val, value, len + 1); 136 137 } else { 138 free( var->lv_value.bv_val ); 139 var->lv_value.bv_val = strdup( value ); 140 } 141 142 } else { 143 free( var->lv_value.bv_val ); 144 var->lv_value.bv_val = (char *)value; 145 var->lv_flags &= ~REWRITE_VAR_COPY_VALUE; 146 } 147 148 } else { 149 if ( flags & REWRITE_VAR_COPY_VALUE ) { 150 var->lv_value.bv_val = strdup( value ); 151 var->lv_flags |= REWRITE_VAR_COPY_VALUE; 152 153 } else { 154 var->lv_value.bv_val = (char *)value; 155 } 156 } 157 158 if ( var->lv_value.bv_val == NULL ) { 159 return -1; 160 } 161 162 var->lv_value.bv_len = len; 163 164 return 0; 165} 166 167/* 168 * Inserts a newly created var 169 */ 170struct rewrite_var * 171rewrite_var_insert_f( 172 Avlnode **tree, 173 const char *name, 174 const char *value, 175 int flags 176) 177{ 178 struct rewrite_var *var; 179 int rc = 0; 180 181 assert( tree != NULL ); 182 assert( name != NULL ); 183 assert( value != NULL ); 184 185 var = rewrite_var_find( *tree, name ); 186 if ( var != NULL ) { 187 if ( flags & REWRITE_VAR_UPDATE ) { 188 (void)rewrite_var_replace( var, value, flags ); 189 goto cleanup; 190 } 191 rc = -1; 192 goto cleanup; 193 } 194 195 var = calloc( sizeof( struct rewrite_var ), 1 ); 196 if ( var == NULL ) { 197 return NULL; 198 } 199 200 memset( var, 0, sizeof( struct rewrite_var ) ); 201 202 if ( flags & REWRITE_VAR_COPY_NAME ) { 203 var->lv_name = strdup( name ); 204 if ( var->lv_name == NULL ) { 205 rc = -1; 206 goto cleanup; 207 } 208 var->lv_flags |= REWRITE_VAR_COPY_NAME; 209 210 } else { 211 var->lv_name = (char *)name; 212 } 213 214 if ( flags & REWRITE_VAR_COPY_VALUE ) { 215 var->lv_value.bv_val = strdup( value ); 216 if ( var->lv_value.bv_val == NULL ) { 217 rc = -1; 218 goto cleanup; 219 } 220 var->lv_flags |= REWRITE_VAR_COPY_VALUE; 221 222 } else { 223 var->lv_value.bv_val = (char *)value; 224 } 225 var->lv_value.bv_len = strlen( value ); 226 rc = avl_insert( tree, ( caddr_t )var, 227 rewrite_var_cmp, rewrite_var_dup ); 228 229cleanup:; 230 if ( rc != 0 && var ) { 231 avl_delete( tree, ( caddr_t )var, rewrite_var_cmp ); 232 rewrite_var_free( var ); 233 var = NULL; 234 } 235 236 return var; 237} 238 239/* 240 * Sets/inserts a var 241 */ 242struct rewrite_var * 243rewrite_var_set_f( 244 Avlnode **tree, 245 const char *name, 246 const char *value, 247 int flags 248) 249{ 250 struct rewrite_var *var; 251 252 assert( tree != NULL ); 253 assert( name != NULL ); 254 assert( value != NULL ); 255 256 var = rewrite_var_find( *tree, name ); 257 if ( var == NULL ) { 258 if ( flags & REWRITE_VAR_INSERT ) { 259 return rewrite_var_insert_f( tree, name, value, flags ); 260 261 } else { 262 return NULL; 263 } 264 265 } else { 266 assert( var->lv_value.bv_val != NULL ); 267 268 (void)rewrite_var_replace( var, value, flags ); 269 } 270 271 return var; 272} 273 274