It is now possible to switch between debug and production, whereas the last setting will suppress any error message including file/line references and stacktraces.
Furthermore errors will ALWAYS be written to a logfile, regardless if running in production or debug mode.
By default debug mode is enabled for now, it MUST be set to 'production' once the software will be tossed into the wild.
<optiontype>boolean</optiontype>
<defaultvalue>0</defaultvalue>
</option>
+
+ <option name="debug_mode">
+ <categoryname>module.system</categoryname>
+ <optiontype>radiobuttons</optiontype>
+ <!-- TODO: change to 'production' later -->
+ <defaultvalue><![CDATA[debug]]></defaultvalue>
+ <selectoptions>
+ <![CDATA[debug:wcf.acp.option.debug_mode.debug
+production:wcf.acp.option.debug_mode.production]]>
+ </selectoptions>
+ </option>
<!-- general.page -->
<option name="page_title">
//]]>
</script>
-<!--
-{$name} thrown in {$file} ({@$line})
-Stracktrace:
-{$stacktrace}
--->
+{if DEBUG_MODE == 'debug'}
+ <!--
+ {$name} thrown in {$file} ({@$line})
+ Stracktrace:
+ {$stacktrace}
+ -->
+{/if}
{include file='footer' sandbox=false}
</body>
-</html>
\ No newline at end of file
+</html>
define('INSTALL_SCRIPT_DIR', dirname(__FILE__).'/');
define('SETUP_FILE', INSTALL_SCRIPT_DIR . 'WCFSetup.tar.gz');
define('NO_IMPORTS', 1);
+define('DEBUG_MODE', 'debug');
// set exception handler
set_exception_handler('handleException');
define('HTTP_GZIP_LEVEL', 0);
define('CACHE_SOURCE_TYPE', 'disk');
define('MODULE_MASTER_PASSWORD', 1);
+define('DEBUG_MODE', 'debug');
/**
* WCFSetup executes the installation of the basic wcf systems.
* @subpackage system.exception
* @category Community Framework
*/
-class AJAXException extends \Exception {
+class AJAXException extends LoggedException {
/**
* Throws a JSON-encoded error message
*
public function __construct($message, $stacktrace = null) {
if ($stacktrace === null) $stacktrace = $this->getTraceAsString();
+ if (DEBUG_MODE == 'debug') {
+ $responseData = array(
+ 'message' => $message,
+ 'stacktrace' => nl2br($stacktrace)
+ );
+ }
+ else {
+ $responseData = array(
+ 'message' => $this->getMessage()
+ );
+ }
+
+ // log error
+ $this->logError();
+
//header('HTTP/1.0 418 I\'m a Teapot');
header('HTTP/1.0 503 Service Unavailable');
header('Content-type: application/json');
- echo JSON::encode(array(
- 'message' => $message,
- 'stacktrace' => nl2br($stacktrace)
- ));
+ echo JSON::encode($responseData);
exit;
}
}
--- /dev/null
+<?php
+namespace wcf\system\exception;
+
+/**
+ * A logged exceptions prevents information disclosures and provides an easy
+ * way to log errors.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2011 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.exception
+ * @category Community Framework
+ */
+class LoggedExceptions extends \Exception {
+ /**
+ * Surpresses the original error message, you can bypass this
+ * by setting $raw to true.
+ *
+ * @param boolean $raw
+ * @see \Exception::getMessage()
+ */
+ public function getMessage($raw = false) {
+ if ($raw) {
+ return parent::getMessage();
+ }
+
+ return 'An error occured. Sorry.';
+ }
+
+ /**
+ * Writes an error to log file.
+ */
+ protected function logError() {
+ $logFile = WCF_DIR . 'log/' . date('Y-m-d', TIME_NOW) . '.txt';
+
+ // try to create file
+ @touch($logFile);
+
+ // validate if file exists and is accessible for us
+ if (!file_exists($logFile) || !is_writable($logFile)) {
+ /*
+ We cannot recover if we reached this point, the server admin
+ is urged to fix his pretty much broken configuration.
+
+ GLaDOS: Look at you, sailing through the air majestically, like an eagle... piloting a blimp.
+ */
+ return;
+ }
+
+ // build message
+ $message = date('r', TIME_NOW) . "\n" . $this->getMessage(true) . "\n\n" . $this->getTraceAsString() . "\n\n\n";
+
+ // append
+ @file_put_contents($logFile, $message, FILE_APPEND);
+ }
+}
* @subpackage system.exception
* @category Community Framework
*/
-class SystemException extends \Exception implements IPrintableException {
+class SystemException extends LoggedException implements IPrintableException {
/**
* error description
* @var string
* @see wcf\system\exception\IPrintableException::show()
*/
public function show() {
+ // log error
+ $this->logError();
+
// send status code
@header('HTTP/1.1 503 Service Unavailable');
<body>
<div class="systemException">
<h1>Fatal error: <?php echo StringUtil::encodeHTML($this->getMessage()); ?></h1>
-
- <div>
- <p><?php echo $this->getDescription(); ?></p>
+
+ <?php if (DEBUG_MODE == 'debug') { ?>
+ <div>
+ <p><?php echo $this->getDescription(); ?></p>
- <h2>Information:</h2>
- <p>
- <b>error message:</b> <?php echo StringUtil::encodeHTML($this->getMessage()); ?><br>
- <b>error code:</b> <?php echo intval($this->getCode()); ?><br>
- <?php echo $this->information; ?>
- <b>file:</b> <?php echo StringUtil::encodeHTML($this->getFile()); ?> (<?php echo $this->getLine(); ?>)<br>
- <b>php version:</b> <?php echo StringUtil::encodeHTML(phpversion()); ?><br>
- <b>wcf version:</b> <?php echo WCF_VERSION; ?><br>
- <b>date:</b> <?php echo gmdate('r'); ?><br>
- <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo StringUtil::encodeHTML($_SERVER['REQUEST_URI']); ?><br>
- <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo StringUtil::encodeHTML($_SERVER['HTTP_REFERER']); ?><br>
- </p>
+ <h2>Information:</h2>
+ <p>
+ <b>error message:</b> <?php echo StringUtil::encodeHTML($this->getMessage()); ?><br>
+ <b>error code:</b> <?php echo intval($this->getCode()); ?><br>
+ <?php echo $this->information; ?>
+ <b>file:</b> <?php echo StringUtil::encodeHTML($this->getFile()); ?> (<?php echo $this->getLine(); ?>)<br>
+ <b>php version:</b> <?php echo StringUtil::encodeHTML(phpversion()); ?><br>
+ <b>wcf version:</b> <?php echo WCF_VERSION; ?><br>
+ <b>date:</b> <?php echo gmdate('r'); ?><br>
+ <b>request:</b> <?php if (isset($_SERVER['REQUEST_URI'])) echo StringUtil::encodeHTML($_SERVER['REQUEST_URI']); ?><br>
+ <b>referer:</b> <?php if (isset($_SERVER['HTTP_REFERER'])) echo StringUtil::encodeHTML($_SERVER['HTTP_REFERER']); ?><br>
+ </p>
- <h2>Stacktrace:</h2>
- <pre><?php echo StringUtil::encodeHTML($this->__getTraceAsString()); ?></pre>
- </div>
+ <h2>Stacktrace:</h2>
+ <pre><?php echo StringUtil::encodeHTML($this->__getTraceAsString()); ?></pre>
+ </div>
+ <?php } ?>
- <?php echo $this->functions; ?>
+ <?php echo $this->functions; ?>
</div>
</body>
</html>
* @subpackage system.exception
* @category Community Framework
*/
-abstract class UserException extends \Exception implements IPrintableException {
+abstract class UserException extends LoggedException implements IPrintableException {
/**
* @see wcf\system\exception\IPrintableException::show()
*/
public function show() {
- echo '<pre>' . $this->getTraceAsString() . '</pre>';
+ if (DEBUG_MODE == 'debug') {
+ echo '<pre>' . $this->getTraceAsString() . '</pre>';
+ }
+ else {
+ echo '<pre>' . $this->getMessage() . '</pre>';
+ }
}
}
define('CACHE_SOURCE_TYPE', 'disk');
define('MODULE_MASTER_PASSWORD', 1);
define('TIMEZONE', 'Europe/Berlin');
+
+// TODO: Change to 'production' later
+define('DEBUG_MODE', 'debug');