openldap/libraries/librewrite/info.c

255 lines
5.5 KiB
C
Raw Normal View History

/******************************************************************************
*
* Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
* All rights reserved.
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to alter it and redistribute it, subject
* to the following restrictions:
*
* 1. The author is not responsible for the consequences of use of this
* software, no matter how awful, even if they arise from flaws in it.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Since few users ever read sources,
* credits should appear in the documentation.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software. Since few users
* ever read sources, credits should appear in the documentation.
*
* 4. This notice may not be removed or altered.
*
******************************************************************************/
#include <portable.h>
#include "rewrite-int.h"
/*
* Global data
*/
/*
* This becomes the running context for subsequent calls to
* rewrite_parse; it can be altered only by a
* rewriteContext config line or by a change in info.
*/
struct rewrite_context *__curr_context = NULL;
/*
* Inits the info
*/
struct rewrite_info *
rewrite_info_init(
int mode
)
{
struct rewrite_info *info;
struct rewrite_context *context;
switch ( mode ) {
case REWRITE_MODE_ERR:
case REWRITE_MODE_OK:
case REWRITE_MODE_COPY_INPUT:
case REWRITE_MODE_USE_DEFAULT:
break;
default:
mode = REWRITE_MODE_USE_DEFAULT;
break;
/* return NULL */
}
/*
* Resets the running context for parsing ...
*/
__curr_context = NULL;
info = calloc( sizeof( struct rewrite_info ), 1 );
if ( info == NULL ) {
return NULL;
}
info->li_state = REWRITE_DEFAULT;
info->li_max_passes = REWRITE_MAX_PASSES;
info->li_rewrite_mode = mode;
/*
* Add the default (empty) rule
*/
context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
if ( context == NULL ) {
free( info );
return NULL;
}
#ifdef USE_REWRITE_LDAP_PVT_THREADS
if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
free( info );
return NULL;
}
if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
free( info );
return NULL;
}
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
return info;
}
/*
* Cleans up the info structure
*/
int
rewrite_info_delete(
struct rewrite_info *info
)
{
assert( info != NULL );
rewrite_session_destroy( info );
rewrite_param_destroy( info );
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
return REWRITE_SUCCESS;
}
/*
* Rewrites a string according to context.
* If the engine is off, OK is returned, but the return string will be NULL.
* In case of 'unwilling to perform', UNWILLING is returned, and the
* return string will also be null. The same in case of error.
* Otherwise, OK is returned, and result will hold a newly allocated string
* with the rewriting.
*
* What to do in case of non-existing rewrite context is still an issue.
* Four possibilities:
* - error,
* - ok with NULL result,
* - ok with copy of string as result,
* - use the default rewrite context.
*/
int
rewrite(
struct rewrite_info *info,
const char *rewriteContext,
const char *string,
char **result
)
{
return rewrite_session( info, rewriteContext,
string, NULL, result );
}
int
rewrite_session(
struct rewrite_info *info,
const char *rewriteContext,
const char *string,
const void *cookie,
char **result
)
{
struct rewrite_context *context;
struct rewrite_op op = { 0, 0, NULL, NULL, NULL, NULL };
int rc;
assert( info != NULL );
assert( rewriteContext != NULL );
assert( string != NULL );
assert( result != NULL );
/*
* cookie can be null; means: don't care about session stuff
*/
*result = NULL;
op.lo_cookie = cookie;
/*
* Engine not on means no failure, but explicit no rewriting
*/
if ( info->li_state != REWRITE_ON ) {
rc = REWRITE_REGEXEC_OK;
goto rc_return;
}
/*
* Undefined context means no rewriting also
* (conservative, are we sure it's what we want?)
*/
context = rewrite_context_find( info, rewriteContext );
if ( context == NULL ) {
switch ( info->li_rewrite_mode ) {
case REWRITE_MODE_ERR:
rc = REWRITE_REGEXEC_ERR;
goto rc_return;
case REWRITE_MODE_OK:
rc = REWRITE_REGEXEC_OK;
goto rc_return;
case REWRITE_MODE_COPY_INPUT:
*result = strdup( string );
rc = REWRITE_REGEXEC_OK;
goto rc_return;
case REWRITE_MODE_USE_DEFAULT:
context = rewrite_context_find( info,
REWRITE_DEFAULT_CONTEXT );
break;
}
}
op.lo_string = strdup( string );
if ( op.lo_string == NULL ) {
rc = REWRITE_REGEXEC_ERR;
goto rc_return;
}
/*
* Applies rewrite context
*/
rc = rewrite_context_apply(info, &op, context, string, result );
assert( op.lo_depth == 0 );
/* ?!? */
free( op.lo_string );
switch ( rc ) {
/*
* Success
*/
case REWRITE_REGEXEC_OK:
case REWRITE_REGEXEC_STOP:
/*
* If rewrite succeeded return OK regardless of how
* the successful rewriting was obtained!
*/
rc = REWRITE_REGEXEC_OK;
break;
/*
* Internal or forced error, return = NULL; rc already OK.
*/
case REWRITE_REGEXEC_UNWILLING:
case REWRITE_REGEXEC_ERR:
default:
if ( *result != NULL ) {
free( *result );
*result = NULL;
}
}
rc_return:;
if ( op.lo_vars ) {
rewrite_var_delete( op.lo_vars );
}
return rc;
}