diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 3ea7eb733..ae5a370bc 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -8,8 +8,8 @@ namespace OCA\Photos\Controller; +use JsonException; use OCA\Photos\AppInfo\Application; -use OCA\Photos\Service\UserConfigService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\ContentSecurityPolicy; @@ -50,14 +50,58 @@ public function setUserConfig(string $key, string $value): JSONResponse { return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); } - if (!in_array($key, array_keys(UserConfigService::DEFAULT_CONFIGS))) { - return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); + switch ($key) { + case 'croppedLayout': + if ($value !== 'true' && $value !== 'false') { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + break; + case 'photosLocation': + if (!$this->validatePath($value)) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + break; + case 'photosSourceFolders': + try { + $paths = json_decode($value, true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + + if (!array_is_list($paths)) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + + foreach ($paths as $path) { + if (!$this->validatePath($path)) { + return new JSONResponse([], Http::STATUS_BAD_REQUEST); + } + } + break; + default: + return new JSONResponse([], Http::STATUS_BAD_REQUEST); } $this->config->setUserValue($user->getUid(), Application::APP_ID, $key, $value); return new JSONResponse([], Http::STATUS_OK); } + private function validatePath(mixed $path): bool { + if (!is_string($path)) { + return false; + } + + if (!str_starts_with($path, '/')) { + return false; + } + + if (str_contains($path, '..')) { + return false; + } + + return true; + } + /** * @NoAdminRequired * @NoCSRFRequired diff --git a/lib/Service/UserConfigService.php b/lib/Service/UserConfigService.php index 80cd88d85..8257663bd 100644 --- a/lib/Service/UserConfigService.php +++ b/lib/Service/UserConfigService.php @@ -18,6 +18,7 @@ class UserConfigService { 'croppedLayout' => 'false', 'photosLocation' => '/Photos', 'photosSourceFolders' => '["/Photos"]', + /** If you add any new configs, make sure to validate the contents in {@see \OCA\Photos\Controller\ApiController::setUserConfig} */ ]; private readonly IConfig $config;