Home | History | Annotate | Line # | Download | only in librewrite
info.c revision 1.1.1.10
      1   1.1.1.9  christos /*	$NetBSD: info.c,v 1.1.1.10 2025/09/05 21:09:34 christos Exp $	*/
      2   1.1.1.2     lukem 
      3   1.1.1.4      tron /* $OpenLDAP$ */
      4       1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5       1.1     lukem  *
      6  1.1.1.10  christos  * Copyright 2000-2024 The OpenLDAP Foundation.
      7       1.1     lukem  * All rights reserved.
      8       1.1     lukem  *
      9       1.1     lukem  * Redistribution and use in source and binary forms, with or without
     10       1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     11       1.1     lukem  * Public License.
     12       1.1     lukem  *
     13       1.1     lukem  * A copy of this license is available in the file LICENSE in the
     14       1.1     lukem  * top-level directory of the distribution or, alternatively, at
     15       1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     16       1.1     lukem  */
     17       1.1     lukem /* ACKNOWLEDGEMENT:
     18       1.1     lukem  * This work was initially developed by Pierangelo Masarati for
     19       1.1     lukem  * inclusion in OpenLDAP Software.
     20       1.1     lukem  */
     21       1.1     lukem 
     22       1.1     lukem #include <portable.h>
     23       1.1     lukem 
     24       1.1     lukem #include "rewrite-int.h"
     25       1.1     lukem 
     26       1.1     lukem /*
     27       1.1     lukem  * Global data
     28       1.1     lukem  */
     29       1.1     lukem 
     30       1.1     lukem /*
     31       1.1     lukem  * This becomes the running context for subsequent calls to
     32       1.1     lukem  * rewrite_parse; it can be altered only by a
     33       1.1     lukem  * rewriteContext config line or by a change in info.
     34       1.1     lukem  */
     35       1.1     lukem struct rewrite_context *rewrite_int_curr_context = NULL;
     36       1.1     lukem 
     37       1.1     lukem /*
     38       1.1     lukem  * Inits the info
     39       1.1     lukem  */
     40       1.1     lukem struct rewrite_info *
     41       1.1     lukem rewrite_info_init(
     42       1.1     lukem 		int mode
     43       1.1     lukem )
     44       1.1     lukem {
     45       1.1     lukem 	struct rewrite_info *info;
     46       1.1     lukem 	struct rewrite_context *context;
     47       1.1     lukem 
     48       1.1     lukem 	switch ( mode ) {
     49       1.1     lukem 	case REWRITE_MODE_ERR:
     50       1.1     lukem 	case REWRITE_MODE_OK:
     51       1.1     lukem 	case REWRITE_MODE_COPY_INPUT:
     52       1.1     lukem 	case REWRITE_MODE_USE_DEFAULT:
     53       1.1     lukem 		break;
     54       1.1     lukem 	default:
     55       1.1     lukem 		mode = REWRITE_MODE_USE_DEFAULT;
     56       1.1     lukem 		break;
     57       1.1     lukem 		/* return NULL */
     58       1.1     lukem 	}
     59       1.1     lukem 
     60       1.1     lukem 	/*
     61       1.1     lukem 	 * Resets the running context for parsing ...
     62       1.1     lukem 	 */
     63       1.1     lukem 	rewrite_int_curr_context = NULL;
     64       1.1     lukem 
     65       1.1     lukem 	info = calloc( sizeof( struct rewrite_info ), 1 );
     66       1.1     lukem 	if ( info == NULL ) {
     67       1.1     lukem 		return NULL;
     68       1.1     lukem 	}
     69       1.1     lukem 
     70       1.1     lukem 	info->li_state = REWRITE_DEFAULT;
     71       1.1     lukem 	info->li_max_passes = REWRITE_MAX_PASSES;
     72       1.1     lukem 	info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
     73       1.1     lukem 	info->li_rewrite_mode = mode;
     74       1.1     lukem 
     75       1.1     lukem 	/*
     76       1.1     lukem 	 * Add the default (empty) rule
     77       1.1     lukem 	 */
     78       1.1     lukem 	context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
     79       1.1     lukem 	if ( context == NULL ) {
     80       1.1     lukem 		free( info );
     81       1.1     lukem 		return NULL;
     82       1.1     lukem 	}
     83       1.1     lukem 
     84       1.1     lukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
     85       1.1     lukem 	if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
     86   1.1.1.9  christos 		ldap_avl_free( info->li_context, rewrite_context_free );
     87       1.1     lukem 		free( info );
     88       1.1     lukem 		return NULL;
     89       1.1     lukem 	}
     90       1.1     lukem 	if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
     91       1.1     lukem 		ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
     92   1.1.1.9  christos 		ldap_avl_free( info->li_context, rewrite_context_free );
     93       1.1     lukem 		free( info );
     94       1.1     lukem 		return NULL;
     95       1.1     lukem 	}
     96       1.1     lukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
     97       1.1     lukem 
     98       1.1     lukem 	return info;
     99       1.1     lukem }
    100       1.1     lukem 
    101       1.1     lukem /*
    102       1.1     lukem  * Cleans up the info structure
    103       1.1     lukem  */
    104       1.1     lukem int
    105       1.1     lukem rewrite_info_delete(
    106       1.1     lukem 		struct rewrite_info **pinfo
    107       1.1     lukem )
    108       1.1     lukem {
    109       1.1     lukem 	struct rewrite_info	*info;
    110       1.1     lukem 
    111       1.1     lukem 	assert( pinfo != NULL );
    112       1.1     lukem 	assert( *pinfo != NULL );
    113       1.1     lukem 
    114       1.1     lukem 	info = *pinfo;
    115       1.1     lukem 
    116       1.1     lukem 	if ( info->li_context ) {
    117   1.1.1.9  christos 		ldap_avl_free( info->li_context, rewrite_context_free );
    118       1.1     lukem 	}
    119       1.1     lukem 	info->li_context = NULL;
    120       1.1     lukem 
    121       1.1     lukem 	if ( info->li_maps ) {
    122   1.1.1.9  christos 		ldap_avl_free( info->li_maps, rewrite_builtin_map_free );
    123       1.1     lukem 	}
    124       1.1     lukem 	info->li_maps = NULL;
    125       1.1     lukem 
    126       1.1     lukem 	rewrite_session_destroy( info );
    127       1.1     lukem 
    128       1.1     lukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
    129       1.1     lukem 	ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
    130       1.1     lukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
    131       1.1     lukem 
    132       1.1     lukem 	rewrite_param_destroy( info );
    133       1.1     lukem 
    134       1.1     lukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
    135       1.1     lukem 	ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
    136       1.1     lukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
    137       1.1     lukem 
    138       1.1     lukem 	free( info );
    139       1.1     lukem 	*pinfo = NULL;
    140       1.1     lukem 
    141       1.1     lukem 	return REWRITE_SUCCESS;
    142       1.1     lukem }
    143       1.1     lukem 
    144       1.1     lukem /*
    145       1.1     lukem  * Rewrites a string according to context.
    146       1.1     lukem  * If the engine is off, OK is returned, but the return string will be NULL.
    147       1.1     lukem  * In case of 'unwilling to perform', UNWILLING is returned, and the
    148       1.1     lukem  * return string will also be null. The same in case of error.
    149       1.1     lukem  * Otherwise, OK is returned, and result will hold a newly allocated string
    150       1.1     lukem  * with the rewriting.
    151       1.1     lukem  *
    152       1.1     lukem  * What to do in case of non-existing rewrite context is still an issue.
    153       1.1     lukem  * Four possibilities:
    154       1.1     lukem  * 	- error,
    155       1.1     lukem  * 	- ok with NULL result,
    156       1.1     lukem  * 	- ok with copy of string as result,
    157       1.1     lukem  * 	- use the default rewrite context.
    158       1.1     lukem  */
    159       1.1     lukem int
    160       1.1     lukem rewrite(
    161       1.1     lukem 		struct rewrite_info *info,
    162       1.1     lukem 		const char *rewriteContext,
    163       1.1     lukem 		const char *string,
    164       1.1     lukem 		char **result
    165       1.1     lukem )
    166       1.1     lukem {
    167       1.1     lukem 	return rewrite_session( info, rewriteContext,
    168       1.1     lukem 			string, NULL, result );
    169       1.1     lukem }
    170       1.1     lukem 
    171       1.1     lukem int
    172       1.1     lukem rewrite_session(
    173       1.1     lukem 		struct rewrite_info *info,
    174       1.1     lukem 		const char *rewriteContext,
    175       1.1     lukem 		const char *string,
    176       1.1     lukem 		const void *cookie,
    177       1.1     lukem 		char **result
    178       1.1     lukem )
    179       1.1     lukem {
    180       1.1     lukem 	struct rewrite_context *context;
    181       1.1     lukem 	struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
    182       1.1     lukem 	int rc;
    183       1.1     lukem 
    184       1.1     lukem 	assert( info != NULL );
    185       1.1     lukem 	assert( rewriteContext != NULL );
    186       1.1     lukem 	assert( string != NULL );
    187       1.1     lukem 	assert( result != NULL );
    188       1.1     lukem 
    189       1.1     lukem 	/*
    190       1.1     lukem 	 * cookie can be null; means: don't care about session stuff
    191       1.1     lukem 	 */
    192       1.1     lukem 
    193       1.1     lukem 	*result = NULL;
    194       1.1     lukem 	op.lo_cookie = cookie;
    195       1.1     lukem 
    196       1.1     lukem 	/*
    197       1.1     lukem 	 * Engine not on means no failure, but explicit no rewriting
    198       1.1     lukem 	 */
    199       1.1     lukem 	if ( info->li_state != REWRITE_ON ) {
    200       1.1     lukem 		rc = REWRITE_REGEXEC_OK;
    201       1.1     lukem 		goto rc_return;
    202       1.1     lukem 	}
    203       1.1     lukem 
    204       1.1     lukem 	/*
    205       1.1     lukem 	 * Undefined context means no rewriting also
    206       1.1     lukem 	 * (conservative, are we sure it's what we want?)
    207       1.1     lukem 	 */
    208       1.1     lukem 	context = rewrite_context_find( info, rewriteContext );
    209       1.1     lukem 	if ( context == NULL ) {
    210       1.1     lukem 		switch ( info->li_rewrite_mode ) {
    211       1.1     lukem 		case REWRITE_MODE_ERR:
    212       1.1     lukem 			rc = REWRITE_REGEXEC_ERR;
    213       1.1     lukem 			goto rc_return;
    214       1.1     lukem 
    215       1.1     lukem 		case REWRITE_MODE_OK:
    216       1.1     lukem 			rc = REWRITE_REGEXEC_OK;
    217       1.1     lukem 			goto rc_return;
    218       1.1     lukem 
    219       1.1     lukem 		case REWRITE_MODE_COPY_INPUT:
    220       1.1     lukem 			*result = strdup( string );
    221   1.1.1.2     lukem 			rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
    222       1.1     lukem 			goto rc_return;
    223       1.1     lukem 
    224       1.1     lukem 		case REWRITE_MODE_USE_DEFAULT:
    225       1.1     lukem 			context = rewrite_context_find( info,
    226       1.1     lukem 					REWRITE_DEFAULT_CONTEXT );
    227       1.1     lukem 			break;
    228       1.1     lukem 		}
    229       1.1     lukem 	}
    230       1.1     lukem 
    231       1.1     lukem #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
    232       1.1     lukem 	op.lo_string = strdup( string );
    233       1.1     lukem 	if ( op.lo_string == NULL ) {
    234       1.1     lukem 		rc = REWRITE_REGEXEC_ERR;
    235       1.1     lukem 		goto rc_return;
    236       1.1     lukem 	}
    237       1.1     lukem #endif
    238       1.1     lukem 
    239       1.1     lukem 	/*
    240       1.1     lukem 	 * Applies rewrite context
    241       1.1     lukem 	 */
    242       1.1     lukem 	rc = rewrite_context_apply( info, &op, context, string, result );
    243       1.1     lukem 	assert( op.lo_depth == 0 );
    244       1.1     lukem 
    245       1.1     lukem #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
    246       1.1     lukem 	free( op.lo_string );
    247       1.1     lukem #endif
    248       1.1     lukem 
    249       1.1     lukem 	switch ( rc ) {
    250       1.1     lukem 	/*
    251       1.1     lukem 	 * Success
    252       1.1     lukem 	 */
    253       1.1     lukem 	case REWRITE_REGEXEC_OK:
    254       1.1     lukem 	case REWRITE_REGEXEC_STOP:
    255       1.1     lukem 		/*
    256       1.1     lukem 		 * If rewrite succeeded return OK regardless of how
    257       1.1     lukem 		 * the successful rewriting was obtained!
    258       1.1     lukem 		 */
    259       1.1     lukem 		rc = REWRITE_REGEXEC_OK;
    260       1.1     lukem 		break;
    261       1.1     lukem 
    262       1.1     lukem 
    263       1.1     lukem 	/*
    264       1.1     lukem 	 * Internal or forced error, return = NULL; rc already OK.
    265       1.1     lukem 	 */
    266       1.1     lukem 	case REWRITE_REGEXEC_UNWILLING:
    267       1.1     lukem 	case REWRITE_REGEXEC_ERR:
    268       1.1     lukem 		if ( *result != NULL ) {
    269       1.1     lukem 			if ( *result != string ) {
    270       1.1     lukem 				free( *result );
    271       1.1     lukem 			}
    272       1.1     lukem 			*result = NULL;
    273       1.1     lukem 		}
    274       1.1     lukem 
    275       1.1     lukem 	default:
    276       1.1     lukem 		break;
    277       1.1     lukem 	}
    278       1.1     lukem 
    279       1.1     lukem rc_return:;
    280       1.1     lukem 	if ( op.lo_vars ) {
    281       1.1     lukem 		rewrite_var_delete( op.lo_vars );
    282       1.1     lukem 	}
    283       1.1     lukem 
    284       1.1     lukem 	return rc;
    285       1.1     lukem }
    286       1.1     lukem 
    287