diff options
author | Andrey Andreev <narf@devilix.net> | 2014-10-28 22:46:45 +0100 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2014-10-28 22:46:45 +0100 |
commit | 4b838af40d77684539dd40461bd92e6e453fe675 (patch) | |
tree | e998edf78ebbd6e1784e858789ad4fa49a159fd1 | |
parent | 2a86f07f4639c0a25df977c00cef23b8f34f9475 (diff) |
Add a real exception handler
Close #1590
Close #3200
-rwxr-xr-x | application/views/errors/cli/error_exception.php | 61 | ||||
-rwxr-xr-x | application/views/errors/html/error_exception.php | 68 | ||||
-rw-r--r-- | system/core/CodeIgniter.php | 3 | ||||
-rw-r--r-- | system/core/Common.php | 45 | ||||
-rw-r--r-- | system/core/Exceptions.php | 38 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 9 |
6 files changed, 211 insertions, 13 deletions
diff --git a/application/views/errors/cli/error_exception.php b/application/views/errors/cli/error_exception.php new file mode 100755 index 000000000..3314fa1c4 --- /dev/null +++ b/application/views/errors/cli/error_exception.php @@ -0,0 +1,61 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) + * @copyright Copyright (c) 2014, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link http://codeigniter.com + * @since Version 3.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); +?> + +An uncaught Exception was encountered + +Type: <?php echo get_class($exception); ?> +Message: <?php echo $message; ?> +Filename: <?php echo $exception->getFile(); ?> +Line Number: <?php echo $exception->getLine(); ?> + +<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?> + +Backtrace: + <?php foreach ($exception->getTrace() as $error): ?> + <?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?> + + File: <?php echo $error['file']; ?> + Line: <?php echo $error['line']; ?> + Function: <?php echo $error['function']; ?> + + <?php endif ?> + + <?php endforeach ?> +<?php endif ?>
\ No newline at end of file diff --git a/application/views/errors/html/error_exception.php b/application/views/errors/html/error_exception.php new file mode 100755 index 000000000..2f3fe4079 --- /dev/null +++ b/application/views/errors/html/error_exception.php @@ -0,0 +1,68 @@ +<?php +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * This content is released under the MIT License (MIT) + * + * Copyright (c) 2014, British Columbia Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/) + * @copyright Copyright (c) 2014, British Columbia Institute of Technology (http://bcit.ca/) + * @license http://opensource.org/licenses/MIT MIT License + * @link http://codeigniter.com + * @since Version 1.0.0 + * @filesource + */ +defined('BASEPATH') OR exit('No direct script access allowed'); +?> + +<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;"> + +<h4>An uncaught Exception was encountered</h4> + +<p>Type: <?php echo get_class($exception); ?></p> +<p>Message: <?php echo $message; ?></p> +<p>Filename: <?php echo $exception->getFile(); ?></p> +<p>Line Number: <?php echo $exception->getLine(); ?></p> + +<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?> + + <p>Backtrace:</p> + <?php foreach ($exception->getTrace() as $error): ?> + + <?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?> + + <p style="margin-left:10px"> + File: <?php echo $error['file']; ?><br /> + Line: <?php echo $error['line']; ?><br /> + Function: <?php echo $error['function']; ?> + </p> + <?php endif ?> + + <?php endforeach ?> + +<?php endif ?> + +</div>
\ No newline at end of file diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index e3d3a1ffb..88e730bc3 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -132,7 +132,8 @@ if ( ! is_php('5.4')) * Define a custom error handler so we can log PHP errors * ------------------------------------------------------ */ - set_error_handler('_exception_handler'); + set_error_handler('_error_handler'); + set_exception_handler('_exception_handler'); register_shutdown_function('_shutdown_handler'); /* diff --git a/system/core/Common.php b/system/core/Common.php index 8bc9d015e..4277ef5b1 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -570,17 +570,17 @@ if ( ! function_exists('set_status_header')) // -------------------------------------------------------------------- -if ( ! function_exists('_exception_handler')) +if ( ! function_exists('_error_handler')) { /** - * Exception Handler + * Error Handler * - * This is the custom exception handler that is declared at the top - * of CodeIgniter.php. The main reason we use this is to permit + * This is the custom error handler that is declared at the (relative) + * top of CodeIgniter.php. The main reason we use this is to permit * PHP errors to be logged in our own log files since the user may - * not have access to server logs. Since this function - * effectively intercepts PHP errors, however, we also need - * to display errors based on the current error_reporting level. + * not have access to server logs. Since this function effectively + * intercepts PHP errors, however, we also need to display errors + * based on the current error_reporting level. * We do that with the use of a PHP error template. * * @param int $severity @@ -589,7 +589,7 @@ if ( ! function_exists('_exception_handler')) * @param int $line * @return void */ - function _exception_handler($severity, $message, $filepath, $line) + function _error_handler($severity, $message, $filepath, $line) { $is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity); @@ -632,6 +632,35 @@ if ( ! function_exists('_exception_handler')) // ------------------------------------------------------------------------ +if ( ! function_exists('_exception_handler')) +{ + /** + * Exception Handler + * + * Sends uncaught exceptions to the logger and displays them + * only if display_errors is On so that they don't show up in + * production environments. + * + * @param Exception $exception + * @return void + */ + function _exception_handler($exception) + { + $_error =& load_class('Exceptions', 'core'); + $_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine()); + + // Should we display the error? + if (ini_get('display_errors')) + { + $_error->show_exception($exception); + } + + exit(1); // EXIT_ERROR + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('_shutdown_handler')) { /** diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index 6324fba2b..0531a4e92 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -187,6 +187,44 @@ class CI_Exceptions { // -------------------------------------------------------------------- + public function show_exception(Exception $exception) + { + $templates_path = config_item('error_views_path'); + if (empty($templates_path)) + { + $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; + } + + $message = $exception->getMessage(); + if (empty($message)) + { + $message = '(null)'; + } + + if (is_cli()) + { + $templates_path .= 'cli'.DIRECTORY_SEPARATOR; + } + else + { + set_status_header(500); + $templates_path .= 'html'.DIRECTORY_SEPARATOR; + } + + if (ob_get_level() > $this->ob_level + 1) + { + ob_end_flush(); + } + + ob_start(); + include($templates_path.'error_exception.php'); + $buffer = ob_get_contents(); + ob_end_clean(); + echo $buffer; + } + + // -------------------------------------------------------------------- + /** * Native PHP error handler * diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 909c3bc3c..9d567482e 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -42,9 +42,9 @@ Release Date: Not Released Only entries in ``$autoload['libraries']`` are auto-loaded now. - Removed previously deprecated EXT constant. - Updated all classes to be written in PHP 5 style, with visibility declarations and no ``var`` usage for properties. - - Moved error templates to *application/views/errors/*. + - Added an Exception handler. + - Moved error templates to *application/views/errors/* and made the path configurable via ``$config['error_views_path']``. - Added support non-HTML error templates for CLI applications. - - Made error templates path configurable using ``$config['error_views_path']``. - Moved the Log class to *application/core/* - Global config files are loaded first, then environment ones. Environment config keys overwrite base ones, allowing to only set the keys we want changed per environment. - Changed detection of ``$view_folder`` so that if it's not found in the current path, it will now also be searched for under the application folder. @@ -480,7 +480,8 @@ Release Date: Not Released - Added function :func:`get_mimes()` to return the *application/config/mimes.php* array. - Added support for HTTP code 303 ("See Other") in :func:`set_status_header()`. - Removed redundant conditional to determine HTTP server protocol in :func:`set_status_header()`. - - Changed ``_exception_handler()`` to respect php.ini *display_errors* setting. + - Renamed ``_exception_handler()`` to ``_error_handler()`` and replaced it with a real exception handler. + - Changed ``_error_handler()`` to respect php.ini *display_errors* setting. - Added function :func:`is_https()` to check if a secure connection is used. - Added function :func:`is_cli()` to replace the ``CI_Input::is_cli_request()`` method. - Added function :func:`function_usable()` to work around a bug in `Suhosin <http://www.hardened-php.net/suhosin/>`. @@ -547,7 +548,7 @@ Release Date: Not Released - Removed ``CI_CORE`` boolean constant from *CodeIgniter.php* (no longer Reactor and Core versions). - Added support for HTTP-Only cookies with new config option *cookie_httponly* (default FALSE). - ``$config['time_reference']`` now supports all timezone strings supported by PHP. - - Fatal PHP errors are now also passed to ``_exception_handler()``, so they can be logged. + - Fatal PHP errors are now also passed to ``_error_handler()``, so they can be logged. Bug fixes for 3.0 |