From 979b291a36caabd28f21d2d4b10b431f5f8ebdd3 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <christoph@winzerhof-wurst.at>
Date: Tue, 10 Nov 2020 10:18:33 +0100
Subject: [PATCH] Show the full trace of an exception

Because often we catch the exception at some point and then the trace is
misleading. What's really interesting is the trace of the *previous*
exception.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
---
 core/templates/exception.php       | 22 +++++++++++++++++++---
 lib/private/Template/Base.php      |  3 ++-
 lib/private/legacy/OC_Template.php |  2 +-
 3 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/core/templates/exception.php b/core/templates/exception.php
index 9fd19d5a8b1..c8a26220092 100644
--- a/core/templates/exception.php
+++ b/core/templates/exception.php
@@ -1,8 +1,24 @@
 <?php
-	/** @var array $_ */
-	/** @var \OCP\IL10N $l */
+/** @var array $_ */
+/** @var \OCP\IL10N $l */
 
 style('core', ['styles', 'header']);
+
+function print_exception(Throwable $e, \OCP\IL10N $l): void {
+	print_unescaped('<pre>');
+	p($e->getTraceAsString());
+	print_unescaped('</pre>');
+
+	if ($e->getPrevious() !== null) {
+		print_unescaped('<br />');
+		print_unescaped('<h4>');
+		p($l->t('Previous'));
+		print_unescaped('</h4>');
+
+		print_exception($e->getPrevious(), $l);
+	}
+}
+
 ?>
 <div class="error error-wide">
 	<h2><?php p($l->t('Internal Server Error')) ?></h2>
@@ -26,6 +42,6 @@ style('core', ['styles', 'header']);
 	<?php if (isset($_['debugMode']) && $_['debugMode'] === true): ?>
 		<br />
 		<h3><?php p($l->t('Trace')) ?></h3>
-		<pre><?php p($_['trace']) ?></pre>
+		<?php print_exception($_['exception'], $l); ?>
 	<?php endif; ?>
 </div>
diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php
index 04d03b6e6f5..21f2b33cfa3 100644
--- a/lib/private/Template/Base.php
+++ b/lib/private/Template/Base.php
@@ -31,6 +31,7 @@
 namespace OC\Template;
 
 use OCP\Defaults;
+use Throwable;
 
 class Base {
 	private $template; // The template
@@ -92,7 +93,7 @@ class Base {
 	/**
 	 * Assign variables
 	 * @param string $key key
-	 * @param array|bool|integer|string $value value
+	 * @param array|bool|integer|string|Throwable $value value
 	 * @return bool
 	 *
 	 * This function assigns a variable. It can be accessed via $_[$key] in
diff --git a/lib/private/legacy/OC_Template.php b/lib/private/legacy/OC_Template.php
index c14a43ea430..2ddb55096ad 100644
--- a/lib/private/legacy/OC_Template.php
+++ b/lib/private/legacy/OC_Template.php
@@ -325,7 +325,7 @@ class OC_Template extends \OC\Template\Base {
 			$content->assign('errorCode', $exception->getCode());
 			$content->assign('file', $exception->getFile());
 			$content->assign('line', $exception->getLine());
-			$content->assign('trace', $exception->getTraceAsString());
+			$content->assign('exception', $exception);
 			$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
 			$content->assign('remoteAddr', $request->getRemoteAddress());
 			$content->assign('requestID', $request->getId());
-- 
GitLab