| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisBT - A PHP based bugtracking system 3 4 # MantisBT is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # (at your option) any later version. 8 # 9 # MantisBT is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Error API 19 * 20 * @package CoreAPI 21 * @subpackage ErrorAPI 22 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 23 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 24 * @link http://www.mantisbt.org 25 * 26 * @uses compress_api.php 27 * @uses config_api.php 28 * @uses constant_api.php 29 * @uses database_api.php 30 * @uses html_api.php 31 * @uses lang_api.php 32 */ 33 34 require_api( 'compress_api.php' ); 35 require_api( 'config_api.php' ); 36 require_api( 'constant_inc.php' ); 37 require_api( 'database_api.php' ); 38 require_api( 'html_api.php' ); 39 require_api( 'lang_api.php' ); 40 41 $g_error_parameters = array(); 42 $g_error_handled = false; 43 $g_error_proceed_url = null; 44 $g_error_send_page_header = true; 45 46 set_error_handler( 'error_handler' ); 47 48 /** 49 * Default error handler 50 * 51 * This handler will not receive E_ERROR, E_PARSE, E_CORE_*, or E_COMPILE_* 52 * errors. 53 * 54 * E_USER_* are triggered by us and will contain an error constant in $p_error 55 * The others, being system errors, will come with a string in $p_error 56 * 57 * @access private 58 * @param int p_type contains the level of the error raised, as an integer. 59 * @param string p_error contains the error message, as a string. 60 * @param string p_file contains the filename that the error was raised in, as a string. 61 * @param int p_line contains the line number the error was raised at, as an integer. 62 * @param array p_context to the active symbol table at the point the error occurred (optional) 63 * @uses lang_api.php 64 * @uses config_api.php 65 * @uses compress_api.php 66 * @uses database_api.php (optional) 67 * @uses html_api.php (optional) 68 */ 69 function error_handler( $p_type, $p_error, $p_file, $p_line, $p_context ) { 70 global $g_error_parameters, $g_error_handled, $g_error_proceed_url; 71 global $g_lang_overrides; 72 global $g_error_send_page_header; 73 74 # check if errors were disabled with @ somewhere in this call chain 75 if( 0 == error_reporting() ) { 76 return; 77 } 78 79 $t_lang_pushed = false; 80 81 $t_db_connected = false; 82 if( function_exists( 'db_is_connected' ) ) { 83 if( db_is_connected() ) { 84 $t_db_connected = true; 85 } 86 } 87 $t_html_api = false; 88 if( function_exists( 'html_end' ) ) { 89 $t_html_api = true; 90 } 91 92 # flush any language overrides to return to user's natural default 93 if( $t_db_connected ) { 94 lang_push( lang_get_default() ); 95 $t_lang_pushed = true; 96 } 97 98 $t_short_file = basename( $p_file ); 99 $t_method_array = config_get_global( 'display_errors' ); 100 if( isset( $t_method_array[$p_type] ) ) { 101 $t_method = $t_method_array[$p_type]; 102 } else { 103 if( isset( $t_method_array[E_ALL] ) ) { 104 $t_method = $t_method_array[E_ALL]; 105 } else { 106 $t_method = 'none'; 107 } 108 } 109 110 # build an appropriate error string 111 switch( $p_type ) { 112 case E_WARNING: 113 $t_error_type = 'SYSTEM WARNING'; 114 $t_error_description = $p_error; 115 break; 116 case E_NOTICE: 117 $t_error_type = 'SYSTEM NOTICE'; 118 $t_error_description = $p_error; 119 break; 120 case E_USER_ERROR: 121 $t_error_type = "APPLICATION ERROR #$p_error"; 122 $t_error_description = error_string( $p_error ); 123 break; 124 case E_USER_WARNING: 125 $t_error_type = "APPLICATION WARNING #$p_error"; 126 $t_error_description = error_string( $p_error ); 127 break; 128 case E_USER_NOTICE: 129 130 # used for debugging 131 $t_error_type = 'DEBUG'; 132 $t_error_description = $p_error; 133 break; 134 default: 135 136 # shouldn't happen, just display the error just in case 137 $t_error_type = ''; 138 $t_error_description = $p_error; 139 } 140 141 $t_error_description = nl2br( $t_error_description ); 142 143 switch( $t_method ) { 144 case 'halt': 145 # disable any further event callbacks 146 if ( function_exists( 'event_clear_callbacks' ) ) { 147 event_clear_callbacks(); 148 } 149 150 $t_oblen = ob_get_length(); 151 if( error_handled() && $t_oblen > 0 ) { 152 $t_old_contents = ob_get_contents(); 153 } 154 155 # We need to ensure compression is off - otherwise the compression headers are output. 156 compress_disable(); 157 158 # then clean the buffer, leaving output buffering on. 159 if( $t_oblen > 0 ) { 160 ob_clean(); 161 } 162 163 # don't send the page header information if it has already been sent 164 if( $g_error_send_page_header ) { 165 if( $t_html_api ) { 166 html_page_top1(); 167 if( $p_error != ERROR_DB_QUERY_FAILED && $t_db_connected == true ) { 168 html_page_top2(); 169 } else { 170 html_page_top2a(); 171 } 172 } else { 173 echo '<html><head><title>', $t_error_type, '</title></head><body>'; 174 } 175 } 176 177 echo '<div id="error-msg">'; 178 echo '<div class="error-type">' . $t_error_type . '</div>'; 179 echo '<div class="error-description">', $t_error_description, '</div>'; 180 echo '<div class="error-info">'; 181 if( null === $g_error_proceed_url ) { 182 echo lang_get( 'error_no_proceed' ); 183 } else { 184 echo '<a href="', $g_error_proceed_url, '">', lang_get( 'proceed' ), '</a>'; 185 } 186 echo '</div>'; 187 188 if( ON == config_get_global( 'show_detailed_errors' ) ) { 189 echo '<div class="error-details">'; 190 error_print_details( $p_file, $p_line, $p_context ); 191 echo '</div>'; 192 echo '<div class="error-trace">'; 193 error_print_stack_trace(); 194 echo '</div>'; 195 } 196 echo '</div>'; 197 198 if( isset( $t_old_contents ) ) { 199 echo '<div class="warning">Previous non-fatal errors occurred. Page contents follow.</div>'; 200 echo '<div id="old-contents">'; 201 echo $t_old_contents; 202 echo '</div>'; 203 } 204 205 if( $t_html_api ) { 206 if( $p_error != ERROR_DB_QUERY_FAILED && $t_db_connected == true ) { 207 html_page_bottom(); 208 } else { 209 html_body_end(); 210 html_end(); 211 } 212 } else { 213 echo '</body></html>', "\n"; 214 } 215 exit(); 216 case 'inline': 217 echo '<div class="error-inline">', $t_error_type, ': ', $t_error_description, '</div>'; 218 $g_error_handled = true; 219 break; 220 default: 221 # do nothing - note we treat this as we've not handled an error, so any redirects go through. 222 } 223 224 if( $t_lang_pushed ) { 225 lang_pop(); 226 } 227 228 $g_error_parameters = array(); 229 $g_error_proceed_url = null; 230 } 231 232 /** 233 * Print out the error details including context 234 * @param string $p_file 235 * @param int $p_line 236 * @param string $p_context 237 * @return null 238 */ 239 function error_print_details( $p_file, $p_line, $p_context ) { 240 ?> 241 <table class="width75"> 242 <tr> 243 <td>Full path: <?php echo htmlentities( $p_file, ENT_COMPAT, 'UTF-8' );?></td> 244 </tr> 245 <tr> 246 <td>Line: <?php echo $p_line?></td> 247 </tr> 248 <tr> 249 <td> 250 <?php error_print_context( $p_context )?> 251 </td> 252 </tr> 253 </table> 254 <?php 255 } 256 257 /** 258 * Print out the variable context given 259 * @param string $p_context 260 * @return null 261 */ 262 function error_print_context( $p_context ) { 263 if( !is_array( $p_context ) ) { 264 return; 265 } 266 267 echo '<table class="width100"><tr><th>Variable</th><th>Value</th><th>Type</th></tr>'; 268 269 # print normal variables 270 foreach( $p_context as $t_var => $t_val ) { 271 if( !is_array( $t_val ) && !is_object( $t_val ) ) { 272 $t_type = gettype( $t_val ); 273 $t_val = htmlentities( (string) $t_val, ENT_COMPAT, 'UTF-8' ); 274 275 # Mask Passwords 276 if( strpos( $t_var, 'password' ) !== false ) { 277 $t_val = '**********'; 278 } 279 280 echo '<tr><td>', $t_var, '</td><td>', $t_val, '</td><td>', $t_type, '</td></tr>', "\n"; 281 } 282 } 283 284 # print arrays 285 foreach( $p_context as $t_var => $t_val ) { 286 if( is_array( $t_val ) && ( $t_var != 'GLOBALS' ) ) { 287 echo '<tr><td colspan="3"><br /><strong>', $t_var, '</strong></td></tr>'; 288 echo '<tr><td colspan="3">'; 289 error_print_context( $t_val ); 290 echo '</td></tr>'; 291 } 292 } 293 294 echo '</table>'; 295 } 296 297 /** 298 * Print out a stack trace 299 * @return null 300 * @uses error_alternate_class 301 */ 302 function error_print_stack_trace() { 303 echo '<table class="width75">'; 304 echo '<tr><th>Filename</th><th>Line</th><th></th><th></th><th>Function</th><th>Args</th></tr>'; 305 306 $t_stack = debug_backtrace(); 307 308 array_shift( $t_stack ); 309 310 # remove the call to this function from the stack trace 311 array_shift( $t_stack ); 312 313 # remove the call to the error handler from the stack trace 314 315 foreach( $t_stack as $t_frame ) { 316 echo '<tr ', error_alternate_class(), '>'; 317 echo '<td>', ( isset( $t_frame['file'] ) ? htmlentities( $t_frame['file'], ENT_COMPAT, 'UTF-8' ) : '-' ), '</td><td>', ( isset( $t_frame['line'] ) ? $t_frame['line'] : '-' ), '</td><td>', ( isset( $t_frame['class'] ) ? $t_frame['class'] : '-' ), '</td><td>', ( isset( $t_frame['type'] ) ? $t_frame['type'] : '-' ), '</td><td>', ( isset( $t_frame['function'] ) ? $t_frame['function'] : '-' ), '</td>'; 318 319 $t_args = array(); 320 if( isset( $t_frame['args'] ) && !empty( $t_frame['args'] ) ) { 321 foreach( $t_frame['args'] as $t_value ) { 322 $t_args[] = error_build_parameter_string( $t_value ); 323 } 324 echo '<td>( ', htmlentities( implode( $t_args, ', ' ), ENT_COMPAT, 'UTF-8' ), ' )</td></tr>'; 325 } else { 326 echo '<td>-</td></tr>'; 327 } 328 } 329 echo '</table>'; 330 } 331 332 /** 333 * Build a string describing the parameters to a function 334 * @param string $p_param 335 * @param bool $p_showtype default true 336 * @param int $p_depth default 0 337 * @return string 338 */ 339 function error_build_parameter_string( $p_param, $p_showtype = true, $p_depth = 0 ) { 340 if( $p_depth++ > 10 ) { 341 return '<strong>***Nesting Level Too Deep***</strong>'; 342 } 343 344 if( is_array( $p_param ) ) { 345 $t_results = array(); 346 347 foreach( $p_param as $t_key => $t_value ) { 348 $t_results[] = '[' . error_build_parameter_string( $t_key, false, $p_depth ) . ']' . ' => ' . error_build_parameter_string( $t_value, false, $p_depth ); 349 } 350 351 return '<Array> { ' . implode( $t_results, ', ' ) . ' }'; 352 } 353 else if( is_object( $p_param ) ) { 354 $t_results = array(); 355 356 $t_class_name = get_class( $p_param ); 357 $t_inst_vars = get_object_vars( $p_param ); 358 359 foreach( $t_inst_vars as $t_name => $t_value ) { 360 $t_results[] = "[$t_name]" . ' => ' . error_build_parameter_string( $t_value, false, $p_depth ); 361 } 362 363 return '<Object><' . $t_class_name . '> ( ' . implode( $t_results, ', ' ) . ' )'; 364 } else { 365 if( $p_showtype ) { 366 return '<' . gettype( $p_param ) . '>' . var_export( $p_param, true ); 367 } else { 368 return var_export( $p_param, true ); 369 } 370 } 371 } 372 373 /** 374 * Return an error string (in the current language) for the given error. 375 * @param int $p_error 376 * @return string 377 * @access public 378 */ 379 function error_string( $p_error ) { 380 global $g_error_parameters; 381 382 # We pad the parameter array to make sure that we don't get errors if 383 # the caller didn't give enough parameters for the error string 384 $t_padding = array_pad( array(), 10, '' ); 385 386 $t_error = lang_get( $p_error, null, false ); 387 388 if( $t_error == '' ) { 389 return lang_get( 'missing_error_string' ) . $p_error; 390 } 391 392 # ripped from string_api 393 $t_string = call_user_func_array( 'sprintf', array_merge( array( $t_error ), $g_error_parameters, $t_padding ) ); 394 return preg_replace( "/&(#[0-9]+|[a-z]+);/i", "&$1;", @htmlspecialchars( $t_string, ENT_COMPAT, 'UTF-8' ) ); 395 } 396 397 /** 398 * Check if we have handled an error during this page 399 * Return true if an error has been handled, false otherwise 400 * @return bool 401 */ 402 function error_handled() { 403 global $g_error_handled; 404 405 return( true == $g_error_handled ); 406 } 407 408 /** 409 * Set additional info parameters to be used when displaying the next error 410 * This function takes a variable number of parameters 411 * 412 * When writing internationalized error strings, note that you can change the 413 * order of parameters in the string. See the PHP manual page for the 414 * sprintf() function for more details. 415 * @access public 416 * @return null 417 */ 418 function error_parameters() { 419 global $g_error_parameters; 420 421 $g_error_parameters = func_get_args(); 422 } 423 424 /** 425 * Set a url to give to the user to proceed after viewing the error 426 * @access public 427 * @param string p_url url given to user after viewing the error 428 * @return null 429 */ 430 function error_proceed_url( $p_url ) { 431 global $g_error_proceed_url; 432 433 $g_error_proceed_url = $p_url; 434 } 435 436 /** 437 * Simple version of helper_alternate_class for use by error api only. 438 * @access private 439 * @return string representing css class 440 */ 441 function error_alternate_class() { 442 static $t_errindex = 1; 443 444 if( 1 == $t_errindex++ % 2 ) { 445 return 'class="row-1"'; 446 } else { 447 return 'class="row-2"'; 448 } 449 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |