diff options
Diffstat (limited to 'libraries/librewrite/info.c')
-rw-r--r-- | libraries/librewrite/info.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/libraries/librewrite/info.c b/libraries/librewrite/info.c new file mode 100644 index 0000000..3952e97 --- /dev/null +++ b/libraries/librewrite/info.c @@ -0,0 +1,284 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 2000-2021 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * 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. + */ + +#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 *rewrite_int_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 ... + */ + rewrite_int_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_max_passes_per_rule = 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 ) ) { + avl_free( info->li_context, rewrite_context_free ); + free( info ); + return NULL; + } + if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) { + ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); + avl_free( info->li_context, rewrite_context_free ); + free( info ); + return NULL; + } +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + return info; +} + +/* + * Cleans up the info structure + */ +int +rewrite_info_delete( + struct rewrite_info **pinfo +) +{ + struct rewrite_info *info; + + assert( pinfo != NULL ); + assert( *pinfo != NULL ); + + info = *pinfo; + + if ( info->li_context ) { + avl_free( info->li_context, rewrite_context_free ); + } + info->li_context = NULL; + + if ( info->li_maps ) { + avl_free( info->li_maps, rewrite_builtin_map_free ); + } + info->li_maps = NULL; + + rewrite_session_destroy( info ); + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rewrite_param_destroy( info ); + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + free( info ); + *pinfo = NULL; + + 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 }; + 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 = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR; + goto rc_return; + + case REWRITE_MODE_USE_DEFAULT: + context = rewrite_context_find( info, + REWRITE_DEFAULT_CONTEXT ); + break; + } + } + +#if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ + op.lo_string = strdup( string ); + if ( op.lo_string == NULL ) { + rc = REWRITE_REGEXEC_ERR; + goto rc_return; + } +#endif + + /* + * Applies rewrite context + */ + rc = rewrite_context_apply( info, &op, context, string, result ); + assert( op.lo_depth == 0 ); + +#if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */ + free( op.lo_string ); +#endif + + 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: + if ( *result != NULL ) { + if ( *result != string ) { + free( *result ); + } + *result = NULL; + } + + default: + break; + } + +rc_return:; + if ( op.lo_vars ) { + rewrite_var_delete( op.lo_vars ); + } + + return rc; +} + |