2003-12-09 01:41:40 +08:00
|
|
|
/* $OpenLDAP$ */
|
|
|
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
2001-05-12 08:51:28 +08:00
|
|
|
*
|
2019-01-15 02:46:16 +08:00
|
|
|
* Copyright 2000-2019 The OpenLDAP Foundation.
|
2001-05-12 08:51:28 +08:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2003-12-09 01:41:40 +08:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted only as authorized by the OpenLDAP
|
|
|
|
* Public License.
|
2001-05-12 08:51:28 +08:00
|
|
|
*
|
2003-12-09 01:41:40 +08:00
|
|
|
* A copy of this license is available in the file LICENSE in the
|
|
|
|
* top-level directory of the distribution or, alternatively, at
|
|
|
|
* <http://www.OpenLDAP.org/license.html>.
|
|
|
|
*/
|
|
|
|
/* ACKNOWLEDGEMENT:
|
|
|
|
* This work was initially developed by Pierangelo Masarati for
|
|
|
|
* inclusion in OpenLDAP Software.
|
|
|
|
*/
|
2001-05-12 08:51:28 +08:00
|
|
|
|
|
|
|
#include <portable.h>
|
|
|
|
|
|
|
|
#include "rewrite-int.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compares two vars
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
rewrite_var_cmp(
|
|
|
|
const void *c1,
|
|
|
|
const void *c2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const struct rewrite_var *v1, *v2;
|
|
|
|
|
2002-04-08 17:43:22 +08:00
|
|
|
v1 = ( const struct rewrite_var * )c1;
|
|
|
|
v2 = ( const struct rewrite_var * )c2;
|
2001-05-12 08:51:28 +08:00
|
|
|
|
|
|
|
assert( v1 != NULL );
|
|
|
|
assert( v2 != NULL );
|
|
|
|
assert( v1->lv_name != NULL );
|
|
|
|
assert( v2->lv_name != NULL );
|
|
|
|
|
|
|
|
return strcasecmp( v1->lv_name, v2->lv_name );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Duplicate var ?
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
rewrite_var_dup(
|
|
|
|
void *c1,
|
|
|
|
void *c2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct rewrite_var *v1, *v2;
|
|
|
|
|
|
|
|
v1 = ( struct rewrite_var * )c1;
|
|
|
|
v2 = ( struct rewrite_var * )c2;
|
|
|
|
|
|
|
|
assert( v1 != NULL );
|
|
|
|
assert( v2 != NULL );
|
|
|
|
assert( v1->lv_name != NULL );
|
|
|
|
assert( v2->lv_name != NULL );
|
|
|
|
|
|
|
|
return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
|
|
|
|
}
|
|
|
|
|
2003-12-28 02:48:06 +08:00
|
|
|
/*
|
|
|
|
* Frees a var
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rewrite_var_free(
|
|
|
|
void *v_var
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct rewrite_var *var = v_var;
|
|
|
|
assert( var != NULL );
|
|
|
|
|
|
|
|
assert( var->lv_name != NULL );
|
|
|
|
assert( var->lv_value.bv_val != NULL );
|
|
|
|
|
|
|
|
if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
|
|
|
|
free( var->lv_name );
|
|
|
|
if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
|
|
|
|
free( var->lv_value.bv_val );
|
|
|
|
free( var );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deletes a var tree
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
rewrite_var_delete(
|
|
|
|
Avlnode *tree
|
|
|
|
)
|
|
|
|
{
|
|
|
|
avl_free( tree, rewrite_var_free );
|
|
|
|
return REWRITE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-05-12 08:51:28 +08:00
|
|
|
/*
|
|
|
|
* Finds a var
|
|
|
|
*/
|
|
|
|
struct rewrite_var *
|
|
|
|
rewrite_var_find(
|
|
|
|
Avlnode *tree,
|
|
|
|
const char *name
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct rewrite_var var;
|
|
|
|
|
|
|
|
assert( name != NULL );
|
|
|
|
|
|
|
|
var.lv_name = ( char * )name;
|
|
|
|
return ( struct rewrite_var * )avl_find( tree,
|
|
|
|
( caddr_t )&var, rewrite_var_cmp );
|
|
|
|
}
|
|
|
|
|
2003-12-28 02:48:06 +08:00
|
|
|
int
|
|
|
|
rewrite_var_replace(
|
|
|
|
struct rewrite_var *var,
|
|
|
|
const char *value,
|
|
|
|
int flags
|
|
|
|
)
|
|
|
|
{
|
2008-09-10 03:58:47 +08:00
|
|
|
ber_len_t len;
|
|
|
|
|
|
|
|
assert( value != NULL );
|
|
|
|
|
|
|
|
len = strlen( value );
|
2003-12-28 02:48:06 +08:00
|
|
|
|
|
|
|
if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
|
|
|
|
if ( flags & REWRITE_VAR_COPY_VALUE ) {
|
|
|
|
if ( len <= var->lv_value.bv_len ) {
|
|
|
|
AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
free( var->lv_value.bv_val );
|
|
|
|
var->lv_value.bv_val = strdup( value );
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
free( var->lv_value.bv_val );
|
|
|
|
var->lv_value.bv_val = (char *)value;
|
|
|
|
var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if ( flags & REWRITE_VAR_COPY_VALUE ) {
|
|
|
|
var->lv_value.bv_val = strdup( value );
|
|
|
|
var->lv_flags |= REWRITE_VAR_COPY_VALUE;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
var->lv_value.bv_val = (char *)value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-10 03:58:47 +08:00
|
|
|
if ( var->lv_value.bv_val == NULL ) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2003-12-28 02:48:06 +08:00
|
|
|
var->lv_value.bv_len = len;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-05-12 08:51:28 +08:00
|
|
|
/*
|
|
|
|
* Inserts a newly created var
|
|
|
|
*/
|
|
|
|
struct rewrite_var *
|
2003-12-28 02:48:06 +08:00
|
|
|
rewrite_var_insert_f(
|
2001-05-12 08:51:28 +08:00
|
|
|
Avlnode **tree,
|
|
|
|
const char *name,
|
2003-12-28 02:48:06 +08:00
|
|
|
const char *value,
|
|
|
|
int flags
|
2001-05-12 08:51:28 +08:00
|
|
|
)
|
|
|
|
{
|
|
|
|
struct rewrite_var *var;
|
2003-12-28 02:48:06 +08:00
|
|
|
int rc = 0;
|
2001-05-12 08:51:28 +08:00
|
|
|
|
|
|
|
assert( tree != NULL );
|
|
|
|
assert( name != NULL );
|
|
|
|
assert( value != NULL );
|
|
|
|
|
2003-12-28 02:48:06 +08:00
|
|
|
var = rewrite_var_find( *tree, name );
|
|
|
|
if ( var != NULL ) {
|
|
|
|
if ( flags & REWRITE_VAR_UPDATE ) {
|
|
|
|
(void)rewrite_var_replace( var, value, flags );
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
rc = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2001-05-12 08:51:28 +08:00
|
|
|
var = calloc( sizeof( struct rewrite_var ), 1 );
|
|
|
|
if ( var == NULL ) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-28 02:48:06 +08:00
|
|
|
|
2003-11-15 02:39:18 +08:00
|
|
|
memset( var, 0, sizeof( struct rewrite_var ) );
|
2003-12-28 02:48:06 +08:00
|
|
|
|
|
|
|
if ( flags & REWRITE_VAR_COPY_NAME ) {
|
|
|
|
var->lv_name = strdup( name );
|
|
|
|
if ( var->lv_name == NULL ) {
|
|
|
|
rc = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
var->lv_flags |= REWRITE_VAR_COPY_NAME;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
var->lv_name = (char *)name;
|
2001-05-12 08:51:28 +08:00
|
|
|
}
|
2003-12-28 02:48:06 +08:00
|
|
|
|
|
|
|
if ( flags & REWRITE_VAR_COPY_VALUE ) {
|
|
|
|
var->lv_value.bv_val = strdup( value );
|
|
|
|
if ( var->lv_value.bv_val == NULL ) {
|
|
|
|
rc = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
var->lv_flags |= REWRITE_VAR_COPY_VALUE;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
var->lv_value.bv_val = (char *)value;
|
2001-05-12 08:51:28 +08:00
|
|
|
}
|
|
|
|
var->lv_value.bv_len = strlen( value );
|
|
|
|
rc = avl_insert( tree, ( caddr_t )var,
|
|
|
|
rewrite_var_cmp, rewrite_var_dup );
|
2003-11-15 02:39:18 +08:00
|
|
|
|
|
|
|
cleanup:;
|
2003-12-28 02:48:06 +08:00
|
|
|
if ( rc != 0 && var ) {
|
|
|
|
avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
|
|
|
|
rewrite_var_free( var );
|
2003-11-15 02:39:18 +08:00
|
|
|
var = NULL;
|
2001-05-12 08:51:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sets/inserts a var
|
|
|
|
*/
|
|
|
|
struct rewrite_var *
|
2003-12-28 02:48:06 +08:00
|
|
|
rewrite_var_set_f(
|
2001-05-12 08:51:28 +08:00
|
|
|
Avlnode **tree,
|
|
|
|
const char *name,
|
|
|
|
const char *value,
|
2003-12-28 02:48:06 +08:00
|
|
|
int flags
|
2001-05-12 08:51:28 +08:00
|
|
|
)
|
|
|
|
{
|
|
|
|
struct rewrite_var *var;
|
|
|
|
|
|
|
|
assert( tree != NULL );
|
|
|
|
assert( name != NULL );
|
|
|
|
assert( value != NULL );
|
|
|
|
|
|
|
|
var = rewrite_var_find( *tree, name );
|
|
|
|
if ( var == NULL ) {
|
2003-12-28 02:48:06 +08:00
|
|
|
if ( flags & REWRITE_VAR_INSERT ) {
|
|
|
|
return rewrite_var_insert_f( tree, name, value, flags );
|
|
|
|
|
2001-05-12 08:51:28 +08:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-12-28 02:48:06 +08:00
|
|
|
|
2001-05-12 08:51:28 +08:00
|
|
|
} else {
|
|
|
|
assert( var->lv_value.bv_val != NULL );
|
|
|
|
|
2003-12-28 02:48:06 +08:00
|
|
|
(void)rewrite_var_replace( var, value, flags );
|
2001-05-12 08:51:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|