Show exception file and line in exception dialog (#2895)
authorMatthias Schmidt <gravatronics@live.com>
Mon, 15 Apr 2019 16:01:54 +0000 (18:01 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 15 Apr 2019 16:01:54 +0000 (18:01 +0200)
* Show exception file and line in exception dialog

Close #2894

* Add missing semicolon

See #2895

wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Request.js
wcfsetup/install/files/lib/action/TAJAXException.class.php
wcfsetup/install/files/lib/system/exception/AJAXException.class.php

index 04f537cb0946de77eb354456ad0c5911912a543b..85f8cebfa2e744bc4e0feca872b270603114ed55 100644 (file)
@@ -313,8 +313,12 @@ define(['Core', 'Language', 'Dom/ChangeListener', 'Dom/Util', 'Ui/Dialog', 'Wolt
                        var message = '';
                        
                        if (data !== null) {
-                               if (data.stacktrace) details = '<br><p>Stacktrace:</p><p>' + data.stacktrace + '</p>';
-                               else if (data.exceptionID) details = '<br><p>Exception ID: <code>' + data.exceptionID + '</code></p>';
+                               if (data.file && data.line) {
+                                       details += '<br><p>File:</p><p>' + data.file + ' in line ' + data.line + '</p>';
+                               }
+                               
+                               if (data.stacktrace) details += '<br><p>Stacktrace:</p><p>' + data.stacktrace + '</p>';
+                               else if (data.exceptionID) details += '<br><p>Exception ID: <code>' + data.exceptionID + '</code></p>';
                                
                                message = data.message;
                                
index adf836fa0a99f9ac78bd645513aca3082da40969..51ceddca0018c7dcea8b7265fe4c44278299d6e4 100644 (file)
@@ -16,7 +16,7 @@ use wcf\system\WCF;
  * @copyright  2001-2019 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\Action
- * @since       5.2
+ * @since      5.2
  */
 trait TAJAXException {
        /**
@@ -29,36 +29,87 @@ trait TAJAXException {
         */
        protected function throwException($e) {
                if ($e instanceof InvalidSecurityTokenException) {
-                       throw new AJAXException(WCF::getLanguage()->getDynamicVariable('wcf.ajax.error.sessionExpired'), AJAXException::SESSION_EXPIRED, $e->getTraceAsString());
+                       throw new AJAXException(
+                               WCF::getLanguage()->getDynamicVariable('wcf.ajax.error.sessionExpired'),
+                               AJAXException::SESSION_EXPIRED,
+                               $e->getTraceAsString(),
+                               [
+                                       'file' => $e->getFile(),
+                                       'line' => $e->getLine()
+                               ]
+                       );
                }
                else if ($e instanceof PermissionDeniedException) {
-                       throw new AJAXException(WCF::getLanguage()->getDynamicVariable('wcf.ajax.error.permissionDenied'), AJAXException::INSUFFICIENT_PERMISSIONS, $e->getTraceAsString());
+                       throw new AJAXException(
+                               WCF::getLanguage()->getDynamicVariable('wcf.ajax.error.permissionDenied'),
+                               AJAXException::INSUFFICIENT_PERMISSIONS,
+                               $e->getTraceAsString(),
+                               [
+                                       'file' => $e->getFile(),
+                                       'line' => $e->getLine()
+                               ]
+                       );
                }
                else if ($e instanceof IllegalLinkException) {
-                       throw new AJAXException(WCF::getLanguage()->get('wcf.ajax.error.illegalLink'), AJAXException::ILLEGAL_LINK, $e->getTraceAsString());
+                       throw new AJAXException(
+                               WCF::getLanguage()->get('wcf.ajax.error.illegalLink'),
+                               AJAXException::ILLEGAL_LINK,
+                               $e->getTraceAsString(),
+                               [
+                                       'file' => $e->getFile(),
+                                       'line' => $e->getLine()
+                               ]
+                       );
                }
                else if ($e instanceof UserInputException) {
                        // repackage as ValidationActionException
                        $exception = new ValidateActionException($e->getField(), $e->getType(), $e->getVariables());
-                       throw new AJAXException($exception->getMessage(), AJAXException::BAD_PARAMETERS, $e->getTraceAsString(), [
-                               'errorMessage' => $exception->getMessage(),
-                               'errorType' => $e->getType(),
-                               'fieldName' => $exception->getFieldName(),
-                               'realErrorMessage' => $exception->getErrorMessage()
-                       ]);
+                       throw new AJAXException(
+                               $exception->getMessage(),
+                               AJAXException::BAD_PARAMETERS,
+                               $e->getTraceAsString(),
+                               [
+                                       'errorMessage' => $exception->getMessage(),
+                                       'errorType' => $e->getType(),
+                                       'file' => $e->getFile(),
+                                       'fieldName' => $e->getFieldName(),
+                                       'line' => $e->getLine(),
+                                       'realErrorMessage' => $exception->getErrorMessage()
+                               ]
+                       );
                }
                else if ($e instanceof ValidateActionException) {
                        throw new AJAXException($e->getMessage(), AJAXException::BAD_PARAMETERS, $e->getTraceAsString(), [
                                'errorMessage' => $e->getMessage(),
+                               'file' => $e->getFile(),
                                'fieldName' => $e->getFieldName(),
+                               'line' => $e->getLine(),
                                'realErrorMessage' => $e->getErrorMessage()
                        ]);
                }
                else if ($e instanceof NamedUserException) {
-                       throw new AJAXException($e->getMessage(), AJAXException::BAD_PARAMETERS, $e->getTraceAsString());
+                       throw new AJAXException(
+                               $e->getMessage(),
+                               AJAXException::BAD_PARAMETERS,
+                               $e->getTraceAsString(),
+                               [
+                                       'file' => $e->getFile(),
+                                       'line' => $e->getLine()
+                               ]
+                       );
                }
                else {
-                       throw new AJAXException($e->getMessage(), AJAXException::INTERNAL_ERROR, $e->getTraceAsString(), [], \wcf\functions\exception\logThrowable($e), $e->getPrevious());
+                       throw new AJAXException(
+                               $e->getMessage(),
+                               AJAXException::INTERNAL_ERROR,
+                               $e->getTraceAsString(),
+                               [
+                                       'file' => $e->getFile(),
+                                       'line' => $e->getLine()
+                               ],
+                               \wcf\functions\exception\logThrowable($e),
+                               $e->getPrevious()
+                       );
                }
        }
 }
index ad6750de06d95a121314c0490cda743cddac54b8..3905a2b152acdc9a631321291bf046d79416ca81 100644 (file)
@@ -62,13 +62,6 @@ class AJAXException extends LoggedException {
        public function __construct($message, $errorType = self::INTERNAL_ERROR, $stacktrace = null, $returnValues = [], $exceptionID = '', $previous = null) {
                if ($stacktrace === null) $stacktrace = $this->getTraceAsString();
                
-               $responseData = [
-                       'code' => $errorType,
-                       'message' => $message,
-                       'previous' => [],
-                       'returnValues' => $returnValues
-               ];
-               
                // include a stacktrace if:
                // - debug mode is enabled or
                // - within ACP and a SystemException was thrown
@@ -84,11 +77,36 @@ class AJAXException extends LoggedException {
                        $includeStacktrace = WCF::debugModeIsEnabled();
                }
                
-               if ($includeStacktrace) {
-                       $responseData['stacktrace'] = nl2br($stacktrace, false);
+               // extract file and line in which exception was thrown and only include it
+               // if stacktrace is also included
+               $file = $line = null;
+               if (isset($returnValues['file'])) {
+                       if ($includeStacktrace) {
+                               $file = $returnValues['file'];
+                       }
+                       
+                       unset($returnValues['file']);
+               }
+               if (isset($returnValues['line'])) {
+                       if ($includeStacktrace) {
+                               $line = $returnValues['line'];
+                       }
+                       
+                       unset($returnValues['line']);
                }
                
+               $responseData = [
+                       'code' => $errorType,
+                       'file' => $file,
+                       'line' => $line,
+                       'message' => $message,
+                       'previous' => [],
+                       'returnValues' => $returnValues
+               ];
+               
                if ($includeStacktrace) {
+                       $responseData['stacktrace'] = nl2br($stacktrace, false);
+                       
                        while ($previous) {
                                $data = ['message' => $previous->getMessage()];
                                $data['stacktrace'] = nl2br($previous->getTraceAsString(), false);