diff --git a/lib/base.php b/lib/base.php index 876d62c3596..7bfef10fec2 100644 --- a/lib/base.php +++ b/lib/base.php @@ -141,8 +141,8 @@ class OC { // Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing // slash which is required by URL generation. - if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT && - substr($_SERVER['REQUEST_URI'], -1) !== '/') { + if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT + && substr($_SERVER['REQUEST_URI'], -1) !== '/') { header('Location: ' . \OC::$WEBROOT . '/'); exit(); } @@ -285,8 +285,8 @@ class OC { $tooBig = ($totalUsers > 50); } } - $ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) && - $_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis'; + $ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) + && $_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis'; if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) { // send http status 503 @@ -987,6 +987,7 @@ class OC { } $request = Server::get(IRequest::class); + $request->throwDecodingExceptionIfAny(); $requestPath = $request->getRawPathInfo(); if ($requestPath === '/heartbeat') { return; diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index bc45a653e7f..348aeb0b7c2 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -64,6 +64,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { protected ?CsrfTokenManager $csrfTokenManager; protected bool $contentDecoded = false; + private ?\JsonException $decodingException = null; /** * @param array $vars An associative array with the following optional values: @@ -389,7 +390,11 @@ class Request implements \ArrayAccess, \Countable, IRequest { // 'application/json' and other JSON-related content types must be decoded manually. if (preg_match(self::JSON_CONTENT_TYPE_REGEX, $this->getHeader('Content-Type')) === 1) { - $params = json_decode(file_get_contents($this->inputStream), true); + try { + $params = json_decode(file_get_contents($this->inputStream), true, flags:JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + $this->decodingException = $e; + } if (\is_array($params) && \count($params) > 0) { $this->items['params'] = $params; if ($this->method === 'POST') { @@ -413,6 +418,12 @@ class Request implements \ArrayAccess, \Countable, IRequest { $this->contentDecoded = true; } + public function throwDecodingExceptionIfAny(): void { + if ($this->decodingException !== null) { + throw $this->decodingException; + } + } + /** * Checks if the CSRF check was correct diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php index 2639a234ad5..cbac143d775 100644 --- a/lib/public/IRequest.php +++ b/lib/public/IRequest.php @@ -305,4 +305,14 @@ interface IRequest { * @since 8.1.0 */ public function getServerHost(): string; + + /** + * If decoding the request content failed, throw an exception. + * Currently only \JsonException for json decoding errors, + * but in the future may throw other exceptions for other decoding issues. + * + * @throws \Exception + * @since 32.0.0 + */ + public function throwDecodingExceptionIfAny(): void; } diff --git a/ocs/v1.php b/ocs/v1.php index 3fc800e198a..97032e63740 100644 --- a/ocs/v1.php +++ b/ocs/v1.php @@ -50,11 +50,14 @@ try { // side effects in existing apps OC_App::loadApps(); + $request = Server::get(IRequest::class); + $request->throwDecodingExceptionIfAny(); + if (!Server::get(IUserSession::class)->isLoggedIn()) { - OC::handleLogin(Server::get(IRequest::class)); + OC::handleLogin($request); } - Server::get(Router::class)->match('/ocsapp' . Server::get(IRequest::class)->getRawPathInfo()); + Server::get(Router::class)->match('/ocsapp' . $request->getRawPathInfo()); } catch (MaxDelayReached $ex) { ApiHelper::respond(Http::STATUS_TOO_MANY_REQUESTS, $ex->getMessage()); } catch (ResourceNotFoundException $e) {