From 89eaf508f19be57a07971c5f40b4bb538e36e891 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 20 Nov 2018 22:34:39 +0100
Subject: [PATCH] Catch HTTPExceptions in App::runFrontend()

Set correct http response header, display error message using "404.tpl"
---
 src/App.php | 95 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 42 deletions(-)

diff --git a/src/App.php b/src/App.php
index c41cfdc6c0..bc7890fcf9 100644
--- a/src/App.php
+++ b/src/App.php
@@ -9,6 +9,7 @@ use DOMDocument;
 use DOMXPath;
 use Exception;
 use Friendica\Database\DBA;
+use Friendica\Network\HTTPException;
 use Friendica\Network\HTTPException\InternalServerErrorException;
 
 /**
@@ -1718,63 +1719,73 @@ class App
 			}
 		}
 
-		$content = '';
-
 		// Initialize module that can set the current theme in the init() method, either directly or via App->profile_uid
-		if ($this->module_loaded) {
-			$this->page['page_title'] = $this->module;
-			$placeholder = '';
+		try {
+			$content = '';
 
-			Core\Addon::callHooks($this->module . '_mod_init', $placeholder);
+			// Initialize module that can set the current theme in the init() method, either directly or via App->profile_uid
+			if ($this->module_loaded) {
+				$this->page['page_title'] = $this->module;
+				$placeholder = '';
 
-			call_user_func([$this->module_class, 'init']);
+				Core\Addon::callHooks($this->module . '_mod_init', $placeholder);
 
-			// "rawContent" is especially meant for technical endpoints.
-			// This endpoint doesn't need any theme initialization or other comparable stuff.
-			if (!$this->error) {
-				call_user_func([$this->module_class, 'rawContent']);
-			}
-		}
+				call_user_func([$this->module_class, 'init']);
 
-		// Load current theme info after module has been initialized as theme could have been set in module
-		$theme_info_file = 'view/theme/' . $this->getCurrentTheme() . '/theme.php';
-		if (file_exists($theme_info_file)) {
-			require_once $theme_info_file;
-		}
+				// "rawContent" is especially meant for technical endpoints.
+				// This endpoint doesn't need any theme initialization or other comparable stuff.
+				if (!$this->error) {
+					call_user_func([$this->module_class, 'rawContent']);
+				}
+			}
 
-		if (function_exists(str_replace('-', '_', $this->getCurrentTheme()) . '_init')) {
-			$func = str_replace('-', '_', $this->getCurrentTheme()) . '_init';
-			$func($this);
-		}
+			// Load current theme info after module has been initialized as theme could have been set in module
+			$theme_info_file = 'view/theme/' . $this->getCurrentTheme() . '/theme.php';
+			if (file_exists($theme_info_file)) {
+				require_once $theme_info_file;
+			}
 
-		if ($this->module_loaded) {
-			if (! $this->error && $_SERVER['REQUEST_METHOD'] === 'POST') {
-				Core\Addon::callHooks($this->module . '_mod_post', $_POST);
-				call_user_func([$this->module_class, 'post']);
+			if (function_exists(str_replace('-', '_', $this->getCurrentTheme()) . '_init')) {
+				$func = str_replace('-', '_', $this->getCurrentTheme()) . '_init';
+				$func($this);
 			}
 
-			if (! $this->error) {
-				Core\Addon::callHooks($this->module . '_mod_afterpost', $placeholder);
-				call_user_func([$this->module_class, 'afterpost']);
+			if ($this->module_loaded) {
+				if (! $this->error && $_SERVER['REQUEST_METHOD'] === 'POST') {
+					Core\Addon::callHooks($this->module . '_mod_post', $_POST);
+					call_user_func([$this->module_class, 'post']);
+				}
+
+				if (! $this->error) {
+					Core\Addon::callHooks($this->module . '_mod_afterpost', $placeholder);
+					call_user_func([$this->module_class, 'afterpost']);
+				}
+
+				if (! $this->error) {
+					$arr = ['content' => $content];
+					Core\Addon::callHooks($this->module . '_mod_content', $arr);
+					$content = $arr['content'];
+					$arr = ['content' => call_user_func([$this->module_class, 'content'])];
+					Core\Addon::callHooks($this->module . '_mod_aftercontent', $arr);
+					$content .= $arr['content'];
+				}
 			}
 
-			if (! $this->error) {
-				$arr = ['content' => $content];
-				Core\Addon::callHooks($this->module . '_mod_content', $arr);
-				$content = $arr['content'];
-				$arr = ['content' => call_user_func([$this->module_class, 'content'])];
-				Core\Addon::callHooks($this->module . '_mod_aftercontent', $arr);
-				$content .= $arr['content'];
+			// initialise content region
+			if ($this->getMode()->isNormal()) {
+				Core\Addon::callHooks('page_content_top', $this->page['content']);
 			}
-		}
 
-		// initialise content region
-		if ($this->getMode()->isNormal()) {
-			Core\Addon::callHooks('page_content_top', $this->page['content']);
+			$this->page['content'] .= $content;
+		} catch (HTTPException $e) {
+			header($_SERVER["SERVER_PROTOCOL"] . " " . $e->httpcode . " " . $e->httpdesc , true, $e->httpcode);
+			$error = ($e->getMessage() !== "" ? $e->getMessage() : $e->httpdesc);
+			$tpl = Core\Renderer::getMarkupTemplate("404.tpl");
+			$this->page['content'] = Core\Renderer::replaceMacros($tpl, [
+				'$message' => $error
+			]);
 		}
 
-		$this->page['content'] .= $content;
-
 		/* Create the page head after setting the language
 		 * and getting any auth credentials.
 		 *
-- 
2.39.5