summaryrefslogtreecommitdiffstats
path: root/libraries/librewrite/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/librewrite/info.c')
-rw-r--r--libraries/librewrite/info.c284
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..9db006d
--- /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-2022 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 ) ) {
+ ldap_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 );
+ ldap_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 ) {
+ ldap_avl_free( info->li_context, rewrite_context_free );
+ }
+ info->li_context = NULL;
+
+ if ( info->li_maps ) {
+ ldap_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;
+}
+