PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/Kohana_Exception.patch

https://github.com/robertleeplummerjr/bluebox
Patch | 871 lines | 828 code | 43 blank | 0 comment | 0 complexity | ba491e445979ff137482171b9a47afac MD5 | raw file
  1. Index: Kohana.php
  2. ===================================================================
  3. --- Kohana.php (revision 3914)
  4. +++ Kohana.php (working copy)
  5. @@ -101,9 +101,28 @@
  6. Event::add('system.shutdown', array(__CLASS__, 'internal_cache_save'));
  7. }
  8. - // Disable notices and "strict" errors
  9. + // Disable notices and "strict" errors, to prevent some oddities in
  10. + // PHP 5.2 and when using Kohana under CLI
  11. $ER = error_reporting(~E_NOTICE & ~E_STRICT);
  12. + // Send default text/html UTF-8 header
  13. + header('Content-Type: text/html; charset=UTF-8');
  14. +
  15. + // Enable exception handling
  16. + Kohana_Exception::enable();
  17. +
  18. + // Enable error handling
  19. + Kohana_PHP_Exception::enable();
  20. +
  21. + if (self::$configuration['core']['log_threshold'] > 0)
  22. + {
  23. + // Set the log directory
  24. + self::log_directory(self::$configuration['core']['log_directory']);
  25. +
  26. + // Enable log writing at shutdown
  27. + register_shutdown_function(array(__CLASS__, 'log_save'));
  28. + }
  29. +
  30. // Set the user agent
  31. self::$user_agent = trim($_SERVER['HTTP_USER_AGENT']);
  32. @@ -128,15 +147,6 @@
  33. // Set autoloader
  34. spl_autoload_register(array('Kohana', 'auto_load'));
  35. - // Set error handler
  36. - set_error_handler(array('Kohana', 'exception_handler'));
  37. -
  38. - // Set exception handler
  39. - set_exception_handler(array('Kohana', 'exception_handler'));
  40. -
  41. - // Send default text/html UTF-8 header
  42. - header('Content-Type: text/html; charset=UTF-8');
  43. -
  44. // Load locales
  45. $locales = self::config('locale.language');
  46. @@ -146,15 +156,6 @@
  47. // Set locale information
  48. self::$locale = setlocale(LC_ALL, $locales);
  49. - if (self::$configuration['core']['log_threshold'] > 0)
  50. - {
  51. - // Set the log directory
  52. - self::log_directory(self::$configuration['core']['log_directory']);
  53. -
  54. - // Enable log writing at shutdown
  55. - register_shutdown_function(array(__CLASS__, 'log_save'));
  56. - }
  57. -
  58. // Enable Kohana routing
  59. Event::add('system.routing', array('Router', 'find_uri'));
  60. Event::add('system.routing', array('Router', 'setup'));
  61. @@ -163,7 +164,7 @@
  62. Event::add('system.execute', array('Kohana', 'instance'));
  63. // Enable Kohana 404 pages
  64. - Event::add('system.404', array('Kohana', 'show_404'));
  65. + Event::add('system.404', array('Kohana_404_Exception', 'trigger'));
  66. // Enable Kohana output handling
  67. Event::add('system.shutdown', array('Kohana', 'shutdown'));
  68. @@ -788,140 +789,6 @@
  69. }
  70. /**
  71. - * Dual-purpose PHP error and exception handler. Uses the kohana_error_page
  72. - * view to display the message.
  73. - *
  74. - * @param integer|object exception object or error code
  75. - * @param string error message
  76. - * @param string filename
  77. - * @param integer line number
  78. - * @return void
  79. - */
  80. - public static function exception_handler($exception, $message = NULL, $file = NULL, $line = NULL)
  81. - {
  82. - // PHP errors have 5 args, always
  83. - $PHP_ERROR = (func_num_args() === 5);
  84. -
  85. - // Test to see if errors should be displayed
  86. - if ($PHP_ERROR AND (error_reporting() & $exception) === 0)
  87. - return;
  88. -
  89. - // This is useful for hooks to determine if a page has an error
  90. - self::$has_error = TRUE;
  91. -
  92. - // Error handling will use exactly 5 args, every time
  93. - if ($PHP_ERROR)
  94. - {
  95. - $code = $exception;
  96. - $type = 'PHP Error';
  97. - $template = 'kohana_error_page';
  98. - }
  99. - else
  100. - {
  101. - $code = $exception->getCode();
  102. - $type = get_class($exception);
  103. - $message = $exception->getMessage();
  104. - $file = $exception->getFile();
  105. - $line = $exception->getLine();
  106. - $template = ($exception instanceof Kohana_Exception) ? $exception->getTemplate() : 'kohana_error_page';
  107. - }
  108. -
  109. - if (is_numeric($code))
  110. - {
  111. - $codes = self::lang('errors');
  112. -
  113. - if ( ! empty($codes[$code]))
  114. - {
  115. - list($level, $error, $description) = $codes[$code];
  116. - }
  117. - else
  118. - {
  119. - $level = 1;
  120. - $error = $PHP_ERROR ? 'Unknown Error' : get_class($exception);
  121. - $description = '';
  122. - }
  123. - }
  124. - else
  125. - {
  126. - // Custom error message, this will never be logged
  127. - $level = 5;
  128. - $error = $code;
  129. - $description = '';
  130. - }
  131. -
  132. - // Remove the DOCROOT from the path, as a security precaution
  133. - $file = str_replace('\\', '/', realpath($file));
  134. - $file = preg_replace('|^'.preg_quote(DOCROOT).'|', '', $file);
  135. -
  136. - if ($level <= self::$configuration['core']['log_threshold'])
  137. - {
  138. - // Log the error
  139. - self::log('error', self::lang('core.uncaught_exception', $type, $message, $file, $line));
  140. - }
  141. -
  142. - if ($PHP_ERROR)
  143. - {
  144. - $description = self::lang('errors.'.E_RECOVERABLE_ERROR);
  145. - $description = is_array($description) ? $description[2] : '';
  146. -
  147. - if ( ! headers_sent())
  148. - {
  149. - // Send the 500 header
  150. - header('HTTP/1.1 500 Internal Server Error');
  151. - }
  152. - }
  153. - else
  154. - {
  155. - if (method_exists($exception, 'sendHeaders') AND ! headers_sent())
  156. - {
  157. - // Send the headers if they have not already been sent
  158. - $exception->sendHeaders();
  159. - }
  160. - }
  161. -
  162. - while (ob_get_level() > self::$buffer_level)
  163. - {
  164. - // Close open buffers
  165. - ob_end_clean();
  166. - }
  167. -
  168. - // Test if display_errors is on
  169. - if (self::$configuration['core']['display_errors'] === TRUE)
  170. - {
  171. - if ( ! IN_PRODUCTION AND $line != FALSE)
  172. - {
  173. - // Remove the first entry of debug_backtrace(), it is the exception_handler call
  174. - $trace = $PHP_ERROR ? array_slice(debug_backtrace(), 1) : $exception->getTrace();
  175. -
  176. - // Beautify backtrace
  177. - $trace = self::backtrace($trace);
  178. - }
  179. -
  180. - // Load the error
  181. - require self::find_file('views', empty($template) ? 'kohana_error_page' : $template);
  182. - }
  183. - else
  184. - {
  185. - // Get the i18n messages
  186. - $error = self::lang('core.generic_error');
  187. - $message = self::lang('core.errors_disabled', url::site(), url::site(Router::$current_uri));
  188. -
  189. - // Load the errors_disabled view
  190. - require self::find_file('views', 'kohana_error_disabled');
  191. - }
  192. -
  193. - if ( ! Event::has_run('system.shutdown'))
  194. - {
  195. - // Run the shutdown even to ensure a clean exit
  196. - Event::run('system.shutdown');
  197. - }
  198. -
  199. - // Turn off error reporting
  200. - error_reporting(0);
  201. - exit;
  202. - }
  203. -
  204. - /**
  205. * Provides class auto-loading.
  206. *
  207. * @throws Kohana_Exception
  208. @@ -1485,67 +1352,185 @@
  209. }
  210. /**
  211. - * Displays nice backtrace information.
  212. - * @see http://php.net/debug_backtrace
  213. + * Simplifies [back trace][ref-btr] information.
  214. *
  215. - * @param array backtrace generated by an exception or debug_backtrace
  216. - * @return string
  217. + * [ref-btr]: http://php.net/debug_backtrace
  218. + *
  219. + * @return array
  220. */
  221. - public static function backtrace($trace)
  222. + public static function read_trace(array $trace_array)
  223. {
  224. - if ( ! is_array($trace))
  225. - return;
  226. + $file = NULL;
  227. - // Final output
  228. - $output = array();
  229. -
  230. - foreach ($trace as $entry)
  231. + $ouput = array();
  232. + foreach ($trace_array as $trace)
  233. {
  234. - $temp = '<li>';
  235. -
  236. - if (isset($entry['file']))
  237. + if (isset($trace['file']))
  238. {
  239. - $temp .= self::lang('core.error_file_line', preg_replace('!^'.preg_quote(DOCROOT).'!', '', $entry['file']), $entry['line']);
  240. - }
  241. + $line = '<strong>'.Kohana::debug_path($trace['file']).'</strong>';
  242. - $temp .= '<pre>';
  243. + if (isset($trace['line']))
  244. + {
  245. + $line .= ', line <strong>'.$trace['line'].'</strong>';
  246. + }
  247. - if (isset($entry['class']))
  248. - {
  249. - // Add class and call type
  250. - $temp .= $entry['class'].$entry['type'];
  251. + $output[] = $line;
  252. }
  253. - // Add function
  254. - $temp .= $entry['function'].'( ';
  255. -
  256. - // Add function args
  257. - if (isset($entry['args']) AND is_array($entry['args']))
  258. + if (isset($trace['function']))
  259. {
  260. - // Separator starts as nothing
  261. - $sep = '';
  262. + // Is this an inline function?
  263. + $inline = in_array($trace['function'], array('require', 'require_once', 'include', 'include_once', 'echo', 'print'));
  264. - while ($arg = array_shift($entry['args']))
  265. + $line = array();
  266. +
  267. + if (isset($trace['class']))
  268. {
  269. - if (is_string($arg) AND is_file($arg))
  270. + $line[] = $trace['class'];
  271. +
  272. + if (isset($trace['type']))
  273. {
  274. - // Remove docroot from filename
  275. - $arg = preg_replace('!^'.preg_quote(DOCROOT).'!', '', $arg);
  276. + $line[] .= $trace['type'];
  277. }
  278. + }
  279. - $temp .= $sep.html::specialchars(print_r($arg, TRUE));
  280. + $line[] = $trace['function'].($inline ? ' ' : '(');
  281. - // Change separator to a comma
  282. - $sep = ', ';
  283. + $args = array();
  284. +
  285. + if ( ! empty($trace['args']))
  286. + {
  287. + foreach ($trace['args'] as $arg)
  288. + {
  289. + if (is_string($arg) AND file_exists($arg))
  290. + {
  291. + // Sanitize path
  292. + $arg = Kohana::debug_path($arg);
  293. + }
  294. +
  295. + $args[] = '<code>'.text::limit_chars(html::specialchars(self::debug_var($arg)), 50, '...').'</code>';
  296. + }
  297. }
  298. +
  299. + $line[] = implode(', ', $args).($inline ? '' : ')');
  300. +
  301. + $output[] = "\t".implode('', $line);
  302. }
  303. + }
  304. - $temp .= ' )</pre></li>';
  305. + return $output;
  306. + }
  307. +
  308. + /**
  309. + * Removes APPPATH, SYSPATH, MODPATH, and DOCROOT from filenames, replacing
  310. + * them with the plain text equivalents.
  311. + *
  312. + * @param string path to sanitize
  313. + * @return string
  314. + */
  315. + public static function debug_path($file)
  316. + {
  317. + if (strpos($file, APPPATH) === 0)
  318. + {
  319. + $file = 'APPPATH/'.substr($file, strlen(APPPATH));
  320. + }
  321. + elseif (strpos($file, SYSPATH) === 0)
  322. + {
  323. + $file = 'SYSPATH/'.substr($file, strlen(SYSPATH));
  324. + }
  325. + elseif (strpos($file, MODPATH) === 0)
  326. + {
  327. + $file = 'MODPATH/'.substr($file, strlen(MODPATH));
  328. + }
  329. + elseif (strpos($file, DOCROOT) === 0)
  330. + {
  331. + $file = 'DOCROOT/'.substr($file, strlen(DOCROOT));
  332. + }
  333. - $output[] = $temp;
  334. + return $file;
  335. + }
  336. +
  337. + /**
  338. + * Similar to print_r or var_dump, generates a string representation of
  339. + * any variable.
  340. + *
  341. + * @param mixed variable to dump
  342. + * @param boolean internal recursion
  343. + * @return string
  344. + */
  345. + public static function debug_var($var, $recursion = FALSE)
  346. + {
  347. + static $objects;
  348. +
  349. + if ($recursion === FALSE)
  350. + {
  351. + $objects = array();
  352. }
  353. - return '<ul class="backtrace">'.implode("\n", $output).'</ul>';
  354. + switch (gettype($var))
  355. + {
  356. + case 'object':
  357. + // Unique hash of the object
  358. + $hash = spl_object_hash($var);
  359. +
  360. + $object = new ReflectionObject($var);
  361. + $more = FALSE;
  362. + $out = 'object '.$object->getName().' { ';
  363. +
  364. + if ($recursion === TRUE AND in_array($hash, $objects))
  365. + {
  366. + $out .= '*RECURSION*';
  367. + }
  368. + else
  369. + {
  370. + // Add the hash to the objects, to detect later recursion
  371. + $objects[] = $hash;
  372. +
  373. + foreach ($object->getProperties() as $property)
  374. + {
  375. + $out .= ($more === TRUE ? ', ' : '').$property->getName().' => ';
  376. + if ($property->isPublic())
  377. + {
  378. + $out .= self::debug_var($property->getValue($var), TRUE);
  379. + }
  380. + elseif ($property->isPrivate())
  381. + {
  382. + $out .= '*PRIVATE*';
  383. + }
  384. + else
  385. + {
  386. + $out .= '*PROTECTED*';
  387. + }
  388. + $more = TRUE;
  389. + }
  390. + }
  391. + return $out.' }';
  392. + case 'array':
  393. + $more = FALSE;
  394. + $out = 'array (';
  395. + foreach ((array) $var as $key => $val)
  396. + {
  397. + if ( ! is_int($key))
  398. + {
  399. + $key = self::debug_var($key, TRUE).' => ';
  400. + }
  401. + else
  402. + {
  403. + $key = '';
  404. + }
  405. + $out .= ($more ? ', ' : '').$key.self::debug_var($val, TRUE);
  406. + $more = TRUE;
  407. + }
  408. + return $out.')';
  409. + case 'string':
  410. + return "'$var'";
  411. + case 'float':
  412. + return number_format($var, 6).'&hellip;';
  413. + case 'boolean':
  414. + return $var === TRUE ? 'TRUE' : 'FALSE';
  415. + default:
  416. + return (string) $var;
  417. + }
  418. }
  419. /**
  420. @@ -1581,25 +1566,97 @@
  421. } // End Kohana
  422. -/**
  423. - * Creates a generic i18n exception.
  424. - */
  425. class Kohana_Exception extends Exception {
  426. - // Template file
  427. - protected $template = 'kohana_error_page';
  428. + // Generate HTML errors
  429. + public static $html_output = TRUE;
  430. - // Header
  431. - protected $header = FALSE;
  432. + // Show stack traces in errors
  433. + public static $trace_output = TRUE;
  434. +
  435. + // Show source code in errors
  436. + public static $source_output = TRUE;
  437. + // Error resources have not been loaded
  438. + protected static $error_resources = FALSE;
  439. +
  440. + // To hold unique identifier to distinguish error output
  441. + protected $instance_identifier;
  442. +
  443. + /**
  444. + * Enable Kohana exception handling.
  445. + *
  446. + * @return void
  447. + */
  448. + public static function enable()
  449. + {
  450. + set_exception_handler(array(__CLASS__, 'handle'));
  451. + }
  452. +
  453. + /**
  454. + * Disable Kohana exception handling.
  455. + *
  456. + * @return void
  457. + */
  458. + public static function disable()
  459. + {
  460. + restore_exception_handler();
  461. + }
  462. +
  463. + /**
  464. + * PHP exception handler.
  465. + *
  466. + * @param object Exception instance
  467. + * @return void
  468. + */
  469. + public static function handle($exception)
  470. + {
  471. + // An error has been triggered
  472. + Kohana::$has_error = TRUE;
  473. +
  474. + if (is_numeric($exception->code))
  475. + {
  476. + $codes = Kohana::lang('errors');
  477. +
  478. + if ( ! empty($codes[$exception->code]))
  479. + {
  480. + list($level, $error) = $codes[$exception->code];
  481. + }
  482. + else
  483. + {
  484. + $level = 1;
  485. + $error = get_class($exception);
  486. + }
  487. + }
  488. + else
  489. + {
  490. + // Custom error message, this will never be logged
  491. + $level = 5;
  492. + $error = $exception->code;
  493. + }
  494. +
  495. + if ($level <= Kohana::config('core.log_threshold'))
  496. + {
  497. + // Log the error
  498. + Kohana::log('error', Kohana::lang('core.uncaught_exception', $error, $exception->message, $exception->file, $exception->line));
  499. + }
  500. +
  501. + echo $exception;
  502. +
  503. + // Exceptions must halt execution
  504. + exit;
  505. + }
  506. +
  507. + // Error template
  508. + public $template = 'kohana/error';
  509. +
  510. // Error code
  511. protected $code = E_KOHANA;
  512. /**
  513. - * Set exception message.
  514. + * Creates a new i18n Kohana_Exception using the passed error and arguments.
  515. *
  516. - * @param string i18n language key for the message
  517. - * @param array addition line parameters
  518. + * @return void
  519. */
  520. public function __construct($error)
  521. {
  522. @@ -1614,18 +1671,144 @@
  523. $message = 'Unknown Exception: '.$error;
  524. }
  525. + $this->instance_identifier = uniqid();
  526. +
  527. // Sets $this->message the proper way
  528. parent::__construct($message);
  529. }
  530. /**
  531. - * Magic method for converting an object to a string.
  532. + * Outputs an inline error message.
  533. *
  534. - * @return string i18n message
  535. + * @return string
  536. */
  537. public function __toString()
  538. {
  539. - return (string) $this->message;
  540. + if (Kohana::config('core.display_errors') === FALSE)
  541. + {
  542. + // Load the "errors disabled" message
  543. + $code = Kohana::lang('core.generic_error');
  544. + $error = Kohana::lang('core.errors_disabled', url::site(''), url::site(Router::$current_uri));
  545. +
  546. + // Do not show the file or line
  547. + $file = $line = NULL;
  548. + }
  549. + else
  550. + {
  551. + // Load exception properties locally
  552. + $code = $this->code;
  553. + $error = $this->message;
  554. + $file = $this->file;
  555. + $line = $this->line;
  556. + $instance_identifier = $this->instance_identifier;
  557. +
  558. + // Load the i18n error name
  559. + $code = Kohana::lang('errors.'.$code.'.1').' ('.$code.')';
  560. + }
  561. +
  562. + if (Kohana_Exception::$html_output)
  563. + {
  564. + if ( ! empty($file))
  565. + {
  566. + // Source code
  567. + $source = '';
  568. +
  569. + if (Kohana_Exception::$source_output)
  570. + {
  571. + // Lines to read from the source
  572. + $start_line = $line - 4;
  573. + $end_line = $line + 3;
  574. +
  575. + $file_source = fopen($file, 'r');
  576. + $file_line = 1;
  577. +
  578. + while ($read_line = fgets($file_source))
  579. + {
  580. + if ($file_line >= $start_line)
  581. + {
  582. + if ($file_line === $line)
  583. + {
  584. + // Wrap the text of this line in <span> tags, for highlighting
  585. + //$read_line = preg_replace('/^(\s+)(.+?)(\s+)$/', '$1<span>$2</span>$3', $read_line);
  586. + $read_line = '<span>'.html::specialchars($read_line).'</span>';
  587. + }
  588. + else
  589. + {
  590. + $read_line = html::specialchars($read_line);
  591. + }
  592. +
  593. + $source .= $read_line;
  594. + }
  595. +
  596. + if (++$file_line > $end_line)
  597. + {
  598. + // Stop reading lines
  599. + fclose($file_source);
  600. +
  601. + break;
  602. + }
  603. + }
  604. + }
  605. +
  606. + if (Kohana_Exception::$trace_output)
  607. + {
  608. + $trace = $this->getTrace();
  609. +
  610. + // Read trace
  611. + $trace = Kohana::read_trace($trace);
  612. + }
  613. + }
  614. +
  615. + if (method_exists($this, 'sendHeaders') AND ! headers_sent())
  616. + {
  617. + // Send the headers if they have not already been sent
  618. + $this->sendHeaders();
  619. + }
  620. +
  621. + // Sanitize filepath for greater security
  622. + $file = Kohana::debug_path($file);
  623. + }
  624. +
  625. + if ( ! Kohana_Exception::$html_output)
  626. + {
  627. + // Show only the error text
  628. + return $code.': '.$error.' [ '.$file.', '.$line.' ] '."\n";
  629. + }
  630. +
  631. + if (Kohana::config('core.display_errors'))
  632. + {
  633. + ob_start();
  634. +
  635. + if ( ! self::$error_resources)
  636. + {
  637. + // Include error style
  638. + echo '<style type="text/css">', "\n";
  639. + include Kohana::find_file('views', 'kohana/error_style', FALSE, 'css');
  640. + echo "\n", '</style>', "\n";
  641. +
  642. + // Include error js
  643. + echo '<script type="text/javascript">', "\n";
  644. + include Kohana::find_file('views', 'kohana/error_script', FALSE, 'js');
  645. + echo "\n", '</script>', "\n";
  646. +
  647. + // Error resources have been loaded
  648. + self::$error_resources = TRUE;
  649. + }
  650. +
  651. + require Kohana::find_file('views', 'kohana/error', FALSE);
  652. + }
  653. + else
  654. + {
  655. + // Clean and stop all output buffers except the Kohana buffer
  656. + Kohana::close_buffers(FALSE, FALSE);
  657. +
  658. + // Clean the Kohana output buffer
  659. + ob_clean();
  660. +
  661. + require Kohana::find_file('views', 'kohana/error_disabled', FALSE);
  662. + }
  663. +
  664. + return ob_get_clean();
  665. }
  666. /**
  667. @@ -1651,8 +1834,93 @@
  668. } // End Kohana Exception
  669. +class Kohana_PHP_Exception extends Kohana_Exception {
  670. +
  671. + /**
  672. + * Enable Kohana PHP error handling.
  673. + *
  674. + * @return void
  675. + */
  676. + public static function enable()
  677. + {
  678. + set_error_handler(array(__CLASS__, 'handle'));
  679. + }
  680. +
  681. + /**
  682. + * Disable Kohana PHP error handling.
  683. + *
  684. + * @return void
  685. + */
  686. + public static function disable()
  687. + {
  688. + restore_error_handler();
  689. + }
  690. +
  691. + /**
  692. + * PHP error handler.
  693. + *
  694. + * @throws Kohana_PHP_Exception
  695. + * @return void
  696. + */
  697. + public static function handle($code, $error, $file, $line, $context = NULL)
  698. + {
  699. + if ((error_reporting() & $code) === 0)
  700. + {
  701. + // Respect error_reporting settings
  702. + return;
  703. + }
  704. +
  705. + // An error has been triggered
  706. + Kohana::$has_error = TRUE;
  707. +
  708. + // Create an exception
  709. + $exception = new Kohana_PHP_Exception($code, $error, $file, $line, $context);
  710. +
  711. + // Get the error level and name
  712. + list ($level, $error) = Kohana::lang('errors.'.$exception->code);
  713. +
  714. + if ($level >= Kohana::config('core.log_threshold'))
  715. + {
  716. + // Log the error
  717. + Kohana::log('error', Kohana::lang('core.uncaught_exception', $error, $exception->message, $exception->file, $exception->line));
  718. + }
  719. +
  720. + echo $exception;
  721. +
  722. + if (Kohana::config('core.display_errors') === FALSE)
  723. + {
  724. + // Execution must halt
  725. + exit;
  726. + }
  727. + }
  728. +
  729. + /**
  730. + * Create a new PHP error exception.
  731. + *
  732. + * @return void
  733. + */
  734. + public function __construct($code, $error, $file, $line, $context = NULL)
  735. + {
  736. + Exception::__construct($error);
  737. +
  738. + // Set the error code, file, line, and context manually
  739. + $this->code = $code;
  740. + $this->file = $file;
  741. + $this->line = $line;
  742. +
  743. + $this->instance_identifier = uniqid();
  744. + }
  745. +
  746. + public function sendHeaders()
  747. + {
  748. + // Send the 500 header
  749. + header('HTTP/1.1 500 Internal Server Error');
  750. + }
  751. +
  752. +} // End Kohana PHP Exception
  753. +
  754. /**
  755. - * Creates a custom exception.
  756. + * Creates a custom exception message.
  757. */
  758. class Kohana_User_Exception extends Kohana_Exception {
  759. @@ -1667,44 +1935,63 @@
  760. {
  761. Exception::__construct($message);
  762. + // Code is the error title
  763. $this->code = $title;
  764. if ($template !== FALSE)
  765. {
  766. + // Override the default template
  767. $this->template = $template;
  768. }
  769. +
  770. + $this->instance_identifier = uniqid();
  771. }
  772. } // End Kohana PHP Exception
  773. /**
  774. - * Creates a Page Not Found exception.
  775. + * Creates a "Page Not Found" exception.
  776. */
  777. class Kohana_404_Exception extends Kohana_Exception {
  778. + /**
  779. + * Throws a new 404 exception.
  780. + *
  781. + * @throws Kohana_404_Exception
  782. + * @return void
  783. + */
  784. + public static function trigger($page = NULL, $template = NULL)
  785. + {
  786. + throw new Kohana_404_Exception($page, $template);
  787. + }
  788. +
  789. protected $code = E_PAGE_NOT_FOUND;
  790. /**
  791. * Set internal properties.
  792. *
  793. - * @param string URL of page
  794. + * @param string URI of page
  795. * @param string custom error template
  796. */
  797. - public function __construct($page = FALSE, $template = FALSE)
  798. + public function __construct($page = NULL, $template = NULL)
  799. {
  800. - if ($page === FALSE)
  801. + if ($page === NULL)
  802. {
  803. - // Construct the page URI using Router properties
  804. - $page = Router::$current_uri.Router::$url_suffix.Router::$query_string;
  805. + // Use the complete URI
  806. + $page = Router::$complete_uri;
  807. }
  808. - Exception::__construct(Kohana::lang('core.page_not_found', $page));
  809. + parent::__construct('core.page_not_found', $page);
  810. - $this->template = $template;
  811. + if ($template !== NULL)
  812. + {
  813. + // Override the default template
  814. + $this->template = $template;
  815. + }
  816. }
  817. /**
  818. - * Sends "File Not Found" headers, to emulate server behavior.
  819. + * Sends 404 headers, to emulate server behavior.
  820. *
  821. * @return void
  822. */
  823. @@ -1714,4 +2001,5 @@
  824. header('HTTP/1.1 404 File Not Found');
  825. }
  826. -} // End Kohana 404 Exception
  827. +} // End Kohana 404 Exception
  828. + No newline at end of file