diff --git a/src/Controller/Share/ShareBrowseController.php b/src/Controller/Share/ShareBrowseController.php index 1972f49..ce44962 100644 --- a/src/Controller/Share/ShareBrowseController.php +++ b/src/Controller/Share/ShareBrowseController.php @@ -39,8 +39,8 @@ class ShareBrowseController extends AbstractController $entries = $this->fileSource->dir($path); } catch (ShareNotConfiguredException) { return new JsonResponse(['error' => 'Share not configured.'], 409); - } catch (ShareConnectionException $e) { - return new JsonResponse(['error' => $e->getMessage()], 502); + } catch (ShareConnectionException) { + return new JsonResponse(['error' => 'Unable to reach the file share.'], 502); } return new JsonResponse([ diff --git a/src/Controller/Share/ShareDownloadController.php b/src/Controller/Share/ShareDownloadController.php index 7f3dcd1..b3eb5bd 100644 --- a/src/Controller/Share/ShareDownloadController.php +++ b/src/Controller/Share/ShareDownloadController.php @@ -48,17 +48,19 @@ class ShareDownloadController extends AbstractController $stream = $this->fileSource->read($path); } catch (ShareNotConfiguredException) { return new Response('Share not configured.', 409); - } catch (ShareConnectionException $e) { - throw new NotFoundHttpException($e->getMessage()); + } catch (ShareConnectionException) { + throw new NotFoundHttpException('File not found.'); } $name = basename($path); $extension = pathinfo($name, PATHINFO_EXTENSION); $mime = MimeTypes::getDefault()->getMimeTypes($extension)[0] ?? 'application/octet-stream'; - // SVG toujours en attachment (anti-XSS) ; sinon respecte le paramètre demandé. - $requested = 'attachment' === $request->query->get('disposition') ? 'attachment' : 'inline'; - $disposition = 'image/svg+xml' === $mime ? HeaderUtils::DISPOSITION_ATTACHMENT : $requested; + // Anti-XSS : seuls des types non exécutables sont servis inline (images hors SVG, PDF). + // Tout le reste (HTML, SVG, octet-stream, etc.) est forcé en attachment, même si inline est demandé. + $inlineSafe = ('image/svg+xml' !== $mime && str_starts_with($mime, 'image/')) || 'application/pdf' === $mime; + $wantInline = 'attachment' !== $request->query->get('disposition'); + $disposition = ($inlineSafe && $wantInline) ? HeaderUtils::DISPOSITION_INLINE : HeaderUtils::DISPOSITION_ATTACHMENT; $response = new StreamedResponse(function () use ($stream): void { if (is_resource($stream)) { @@ -68,6 +70,8 @@ class ShareDownloadController extends AbstractController }); $response->headers->set('Content-Type', $mime); $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition($disposition, $name)); + // Empêche le navigateur de "deviner" un type exécutable à partir du contenu. + $response->headers->set('X-Content-Type-Options', 'nosniff'); return $response; }