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