[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/core/ -> error_api.php (source)

   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( "/&amp;(#[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  }


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7