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