diff options
author | Louis Chemineau <louis@chmn.me> | 2024-09-05 16:17:32 +0200 |
---|---|---|
committer | backportbot[bot] <backportbot[bot]@users.noreply.github.com> | 2024-09-05 18:15:51 +0000 |
commit | 987840592e6d15c8031f06691d28576757dd2fb1 (patch) | |
tree | 8fc3ba2ef20ff999181c4dfb18c9140c6bfe8c93 /apps | |
parent | 473c9d82490a31c4298aedca8d56682e862e11c8 (diff) | |
download | nextcloud-server-987840592e6d15c8031f06691d28576757dd2fb1.tar.gz nextcloud-server-987840592e6d15c8031f06691d28576757dd2fb1.zip |
fix(dav): Always respond custom error page on exceptions
Signed-off-by: Louis Chemineau <louis@chmn.me>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dav/composer/composer/autoload_classmap.php | 2 | ||||
-rw-r--r-- | apps/dav/composer/composer/autoload_static.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/Connector/Sabre/ServerFactory.php | 6 | ||||
-rw-r--r-- | apps/dav/lib/Files/ErrorPagePlugin.php (renamed from apps/dav/lib/Files/BrowserErrorPagePlugin.php) | 82 | ||||
-rw-r--r-- | apps/dav/lib/Server.php | 6 | ||||
-rw-r--r-- | apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml | 2 | ||||
-rw-r--r-- | apps/dav/tests/unit/DAV/ErrorPagePluginTest.php (renamed from apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php) | 8 |
7 files changed, 55 insertions, 53 deletions
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 3e4dfbcabd1..ff6ac0a0928 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -265,7 +265,7 @@ return array( 'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => $baseDir . '/../lib/Events/SubscriptionUpdatedEvent.php', 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => $baseDir . '/../lib/Exception/ServerMaintenanceMode.php', 'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => $baseDir . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php', - 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php', + 'OCA\\DAV\\Files\\ErrorPagePlugin' => $baseDir . '/../lib/Files/ErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => $baseDir . '/../lib/Files/FilesHome.php', 'OCA\\DAV\\Files\\LazySearchBackend' => $baseDir . '/../lib/Files/LazySearchBackend.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 23feaf5227a..00d90a532fb 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -280,7 +280,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionUpdatedEvent.php', 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => __DIR__ . '/..' . '/../lib/Exception/ServerMaintenanceMode.php', 'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => __DIR__ . '/..' . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php', - 'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php', + 'OCA\\DAV\\Files\\ErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/ErrorPagePlugin.php', 'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php', 'OCA\\DAV\\Files\\FilesHome' => __DIR__ . '/..' . '/../lib/Files/FilesHome.php', 'OCA\\DAV\\Files\\LazySearchBackend' => __DIR__ . '/..' . '/../lib/Files/LazySearchBackend.php', diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index 3b3c10e58cd..c415b49b58d 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -34,7 +34,7 @@ namespace OCA\DAV\Connector\Sabre; use OCA\DAV\AppInfo\PluginManager; use OCA\DAV\CalDAV\DefaultCalendarValidator; use OCA\DAV\DAV\ViewOnlyPlugin; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Folder; use OCP\Files\Mount\IMountManager; @@ -121,9 +121,7 @@ class ServerFactory { $server->addPlugin(new \OCA\DAV\Connector\Sabre\FakeLockerPlugin()); } - if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) { - $server->addPlugin(new BrowserErrorPagePlugin()); - } + $server->addPlugin(new ErrorPagePlugin($this->request, $this->config)); // wait with registering these until auth is handled and the filesystem is setup $server->on('beforeMethod:*', function () use ($server, $objectTree, $viewCallBack) { diff --git a/apps/dav/lib/Files/BrowserErrorPagePlugin.php b/apps/dav/lib/Files/ErrorPagePlugin.php index eccae8afdd5..d918da4fab3 100644 --- a/apps/dav/lib/Files/BrowserErrorPagePlugin.php +++ b/apps/dav/lib/Files/ErrorPagePlugin.php @@ -24,17 +24,22 @@ */ namespace OCA\DAV\Files; -use OC\AppFramework\Http\Request; use OC_Template; use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\IConfig; use OCP\IRequest; use Sabre\DAV\Exception; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; -class BrowserErrorPagePlugin extends ServerPlugin { - /** @var Server */ - private $server; +class ErrorPagePlugin extends ServerPlugin { + private ?Server $server = null; + + public function __construct( + private IRequest $request, + private IConfig $config, + ) { + } /** * This initializes the plugin. @@ -43,35 +48,12 @@ class BrowserErrorPagePlugin extends ServerPlugin { * addPlugin is called. * * This method should set up the required event subscriptions. - * - * @param Server $server - * @return void */ - public function initialize(Server $server) { + public function initialize(Server $server): void { $this->server = $server; $server->on('exception', [$this, 'logException'], 1000); } - /** - * @param IRequest $request - * @return bool - */ - public static function isBrowserRequest(IRequest $request) { - if ($request->getMethod() !== 'GET') { - return false; - } - return $request->isUserAgent([ - Request::USER_AGENT_IE, - Request::USER_AGENT_MS_EDGE, - Request::USER_AGENT_CHROME, - Request::USER_AGENT_FIREFOX, - Request::USER_AGENT_SAFARI, - ]); - } - - /** - * @param \Throwable $ex - */ public function logException(\Throwable $ex): void { if ($ex instanceof Exception) { $httpCode = $ex->getHTTPCode(); @@ -82,7 +64,7 @@ class BrowserErrorPagePlugin extends ServerPlugin { } $this->server->httpResponse->addHeaders($headers); $this->server->httpResponse->setStatus($httpCode); - $body = $this->generateBody($httpCode); + $body = $this->generateBody($ex, $httpCode); $this->server->httpResponse->setBody($body); $csp = new ContentSecurityPolicy(); $this->server->httpResponse->addHeader('Content-Security-Policy', $csp->buildPolicy()); @@ -93,18 +75,32 @@ class BrowserErrorPagePlugin extends ServerPlugin { * @codeCoverageIgnore * @return bool|string */ - public function generateBody(int $httpCode) { - $request = \OC::$server->getRequest(); - - $templateName = 'exception'; - if ($httpCode === 403 || $httpCode === 404) { - $templateName = (string)$httpCode; + public function generateBody(\Throwable $ex, int $httpCode): mixed { + if ($this->acceptHtml()) { + $templateName = 'exception'; + $renderAs = 'guest'; + if ($httpCode === 403 || $httpCode === 404) { + $templateName = (string)$httpCode; + } + } else { + $templateName = 'xml_exception'; + $renderAs = null; + $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); } - $content = new OC_Template('core', $templateName, 'guest'); + $debug = $this->config->getSystemValueBool('debug', false); + + $content = new OC_Template('core', $templateName, $renderAs); $content->assign('title', $this->server->httpResponse->getStatusText()); - $content->assign('remoteAddr', $request->getRemoteAddress()); - $content->assign('requestID', $request->getId()); + $content->assign('remoteAddr', $this->request->getRemoteAddress()); + $content->assign('requestID', $this->request->getId()); + $content->assign('debugMode', $debug); + $content->assign('errorClass', get_class($ex)); + $content->assign('errorMsg', $ex->getMessage()); + $content->assign('errorCode', $ex->getCode()); + $content->assign('file', $ex->getFile()); + $content->assign('line', $ex->getLine()); + $content->assign('exception', $ex); return $content->fetchPage(); } @@ -115,4 +111,14 @@ class BrowserErrorPagePlugin extends ServerPlugin { $this->server->sapi->sendResponse($this->server->httpResponse); exit(); } + + private function acceptHtml(): bool { + foreach (explode(',', $this->request->getHeader('Accept')) as $part) { + $subparts = explode(';', $part); + if (str_ends_with($subparts[0], '/html')) { + return true; + } + } + return false; + } } diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 11fa61015e8..8c5d3eef4c6 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -72,7 +72,7 @@ use OCA\DAV\DAV\PublicAuth; use OCA\DAV\DAV\ViewOnlyPlugin; use OCA\DAV\Events\SabrePluginAddEvent; use OCA\DAV\Events\SabrePluginAuthInitEvent; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use OCA\DAV\Files\LazySearchBackend; use OCA\DAV\Profiler\ProfilerPlugin; use OCA\DAV\Provisioning\Apple\AppleProvisioningPlugin; @@ -249,9 +249,7 @@ class Server { $this->server->addPlugin(new FakeLockerPlugin()); } - if (BrowserErrorPagePlugin::isBrowserRequest($request)) { - $this->server->addPlugin(new BrowserErrorPagePlugin()); - } + $this->server->addPlugin(new ErrorPagePlugin($this->request, \OC::$server->getConfig())); $lazySearchBackend = new LazySearchBackend(); $this->server->addPlugin(new SearchPlugin($lazySearchBackend)); diff --git a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml index cf4fcde251f..388d9df8413 100644 --- a/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml +++ b/apps/dav/tests/travis/caldavtest/tests/CalDAV/sync-report.xml @@ -2712,7 +2712,7 @@ <callback>prepostcondition</callback> <arg> <name>error</name> - <value>{DAV:}valid-sync-token</value> + <value>{http://sabredav.org/ns}exception</value> </arg> <arg> <name>ignoreextras</name> diff --git a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php b/apps/dav/tests/unit/DAV/ErrorPagePluginTest.php index b6ec05afd78..3c87574e8d2 100644 --- a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php +++ b/apps/dav/tests/unit/DAV/ErrorPagePluginTest.php @@ -23,11 +23,11 @@ */ namespace OCA\DAV\Tests\unit\DAV; -use OCA\DAV\Files\BrowserErrorPagePlugin; +use OCA\DAV\Files\ErrorPagePlugin; use Sabre\DAV\Exception\NotFound; use Sabre\HTTP\Response; -class BrowserErrorPagePluginTest extends \Test\TestCase { +class ErrorPagePluginTest extends \Test\TestCase { /** * @dataProvider providesExceptions @@ -35,8 +35,8 @@ class BrowserErrorPagePluginTest extends \Test\TestCase { * @param $exception */ public function test($expectedCode, $exception): void { - /** @var BrowserErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */ - $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->setMethods(['sendResponse', 'generateBody'])->getMock(); + /** @var ErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */ + $plugin = $this->getMockBuilder(ErrorPagePlugin::class)->disableOriginalConstructor()->setMethods(['sendResponse', 'generateBody'])->getMock(); $plugin->expects($this->once())->method('generateBody')->willReturn(':boom:'); $plugin->expects($this->once())->method('sendResponse'); /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject $server */ |