diff --git a/typo3/sysext/backend/Classes/Backend/Shortcut/ShortcutRepository.php b/typo3/sysext/backend/Classes/Backend/Shortcut/ShortcutRepository.php index 90d2d67862805c041cb07c7c974e177e1320a9d4..d3ac50d07d037c2dc8c3bb2130a5a17032797442 100644 --- a/typo3/sysext/backend/Classes/Backend/Shortcut/ShortcutRepository.php +++ b/typo3/sysext/backend/Classes/Backend/Shortcut/ShortcutRepository.php @@ -405,7 +405,7 @@ class ShortcutRepository $combinedIdentifier = (string)($arguments['id'] ?? ''); if ($combinedIdentifier !== '') { $storage = GeneralUtility::makeInstance(StorageRepository::class)->findByCombinedIdentifier($combinedIdentifier); - if ($storage === null || $storage->getUid() === 0) { + if ($storage === null || $storage->isFallbackStorage()) { // Continue, if invalid storage or disallowed fallback storage continue; } diff --git a/typo3/sysext/backend/Classes/Controller/LinkController.php b/typo3/sysext/backend/Classes/Controller/LinkController.php index d67d10960992c6892da189e4d17c74202e8d4a59..9254b20f51a1f2c05902dfba8e24f600f5e75f02 100644 --- a/typo3/sysext/backend/Classes/Controller/LinkController.php +++ b/typo3/sysext/backend/Classes/Controller/LinkController.php @@ -56,7 +56,7 @@ final class LinkController if (!$resource instanceof File && !$resource instanceof Folder) { throw new \InvalidArgumentException('Resource must be a file or a folder', 1679039649); } - if ($resource->getStorage()->getUid() === 0) { + if ($resource->getStorage()->isFallbackStorage()) { throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1679039650); } if ($resource instanceof File) { diff --git a/typo3/sysext/backend/Classes/Controller/Resource/ResourceController.php b/typo3/sysext/backend/Classes/Controller/Resource/ResourceController.php index 9d86b618b39b796dcece84209bfcaac374f38247..8528e4eb0a6170ffbeda0a7f7a272f1dfb974759 100644 --- a/typo3/sysext/backend/Classes/Controller/Resource/ResourceController.php +++ b/typo3/sysext/backend/Classes/Controller/Resource/ResourceController.php @@ -54,7 +54,7 @@ final class ResourceController if (!$origin instanceof File && !$origin instanceof Folder) { throw new \InvalidArgumentException('Resource must be a file or a folder', 1676979120); } - if ($origin->getStorage()->getUid() === 0) { + if ($origin->getStorage()->isFallbackStorage()) { throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1676299579); } if (!$origin->checkActionPermission('rename')) { diff --git a/typo3/sysext/backend/Classes/Form/Element/LinkElement.php b/typo3/sysext/backend/Classes/Form/Element/LinkElement.php index 8986b75bc6474c11e3995aa79f3fca21a98e6c6d..621bcef6d5600f7e6854fb0d4a2bd48d0e87c397 100644 --- a/typo3/sysext/backend/Classes/Form/Element/LinkElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/LinkElement.php @@ -31,6 +31,7 @@ use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException; use TYPO3\CMS\Core\Resource\Exception\InvalidPathException; use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\Folder; +use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Utility\StringUtility; @@ -335,10 +336,12 @@ class LinkElement extends AbstractFormElement } } + $backendUser = $this->getBackendUser(); // Resolve the actual link switch ($linkData['type']) { case LinkService::TYPE_PAGE: - $pageRecord = BackendUtility::readPageAccess($linkData['pageuid'] ?? null, '1=1'); + $pagePermissionClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW); + $pageRecord = BackendUtility::readPageAccess($linkData['pageuid'] ?? null, $pagePermissionClause); // Is this a real page if ($pageRecord['uid'] ?? 0) { $fragmentTitle = ''; @@ -372,7 +375,7 @@ class LinkElement extends AbstractFormElement break; case LinkService::TYPE_FILE: $file = $linkData['file'] ?? null; - if ($file instanceof File) { + if ($file instanceof File && $file->checkActionPermission('read') && !$file->getStorage()->isFallbackStorage()) { $data = [ 'text' => $file->getPublicUrl(), 'icon' => $this->iconFactory->getIconForFileExtension($file->getExtension(), Icon::SIZE_SMALL)->render(), @@ -381,7 +384,7 @@ class LinkElement extends AbstractFormElement break; case LinkService::TYPE_FOLDER: $folder = $linkData['folder'] ?? null; - if ($folder instanceof Folder) { + if ($folder instanceof Folder && $folder->checkActionPermission('read') && !$folder->getStorage()->isFallbackStorage()) { $data = [ 'text' => $folder->getPublicUrl(), 'icon' => $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL)->render(), @@ -391,7 +394,9 @@ class LinkElement extends AbstractFormElement case LinkService::TYPE_RECORD: $table = $this->data['pageTsConfig']['TCEMAIN.']['linkHandler.'][$linkData['identifier'] . '.']['configuration.']['table'] ?? ''; $record = BackendUtility::getRecord($table, $linkData['uid']); - if ($record) { + $pagePermissionClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW); + $hasPageAccess = BackendUtility::readPageAccess($record['pid'] ?? null, $pagePermissionClause) !== false; + if ($record && $hasPageAccess && $backendUser->check('tables_select', $table)) { $recordTitle = BackendUtility::getRecordTitle($table, $record); $tableTitle = $this->getLanguageService()->sL($GLOBALS['TCA'][$table]['ctrl']['title']); $data = [ diff --git a/typo3/sysext/backend/Classes/LinkHandler/PageLinkHandler.php b/typo3/sysext/backend/Classes/LinkHandler/PageLinkHandler.php index c805e6658c2bf4489cbe6a65352f3788b0de4d40..f7f48a73f4e53c126b378cef920ae7d8b4013792 100644 --- a/typo3/sysext/backend/Classes/LinkHandler/PageLinkHandler.php +++ b/typo3/sysext/backend/Classes/LinkHandler/PageLinkHandler.php @@ -25,6 +25,7 @@ use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\LinkHandling\LinkService; +use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; @@ -87,11 +88,19 @@ class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac $titleLen = (int)$this->getBackendUser()->uc['titleLen']; $id = (int)$this->linkParts['url']['pageuid']; - $pageTitle = BackendUtility::getRecordWSOL('pages', $id, 'title')['title'] ?? ''; + $idInfo = 'ID: ' . $id . (!empty($this->linkParts['url']['fragment']) ? ', #' . $this->linkParts['url']['fragment'] : ''); + + $permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); + $pageRecord = BackendUtility::readPageAccess($id, $permsClause); + if ($pageRecord === false) { + return $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_browse_links.xlf:page') . ' ' . $idInfo; + } + + $pageTitle = $pageRecord['title'] ?? ''; return $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_browse_links.xlf:page') . ($pageTitle ? ' \'' . GeneralUtility::fixed_lgd_cs($pageTitle, $titleLen) . '\'' : '') - . ' (ID: ' . $id . (!empty($this->linkParts['url']['fragment']) ? ', #' . $this->linkParts['url']['fragment'] : '') . ')'; + . ' (' . $idInfo . ')'; } /** diff --git a/typo3/sysext/core/Classes/LinkHandling/FileLinkHandler.php b/typo3/sysext/core/Classes/LinkHandling/FileLinkHandler.php index f6d7ce8dfbc1eca55e43b9834bf6d03ae4fb74a5..845cceb9cfadb654b92b04f46e6900dcea1435eb 100644 --- a/typo3/sysext/core/Classes/LinkHandling/FileLinkHandler.php +++ b/typo3/sysext/core/Classes/LinkHandling/FileLinkHandler.php @@ -20,6 +20,7 @@ namespace TYPO3\CMS\Core\LinkHandling; use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException; use TYPO3\CMS\Core\Resource\FileInterface; use TYPO3\CMS\Core\Resource\ResourceFactory; +use TYPO3\CMS\Core\Resource\Security\FileNameValidator; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -71,6 +72,13 @@ class FileLinkHandler implements LinkHandlingInterface { try { $file = $this->resolveFile($data); + $fileNameValidator = GeneralUtility::makeInstance(FileNameValidator::class); + if ( + !$fileNameValidator->isValid(basename($file->getIdentifier())) || + !$fileNameValidator->isValid($file->getName()) + ) { + $file = null; + } } catch (FileDoesNotExistException $e) { $file = null; } diff --git a/typo3/sysext/core/Classes/LinkHandling/LegacyLinkNotationConverter.php b/typo3/sysext/core/Classes/LinkHandling/LegacyLinkNotationConverter.php index 889b484a297c5f514fcae36d194494c23744e87b..80555d3fa96586f2c376a2edda52702227ee1e2d 100644 --- a/typo3/sysext/core/Classes/LinkHandling/LegacyLinkNotationConverter.php +++ b/typo3/sysext/core/Classes/LinkHandling/LegacyLinkNotationConverter.php @@ -220,7 +220,7 @@ class LegacyLinkNotationConverter } $fileOrFolderObject = $this->getResourceFactory()->retrieveFileOrFolderObject($fileIdentifier); // Links to a file/folder in the main TYPO3 directory should not be considered as file links, but an external link - if ($fileOrFolderObject instanceof ResourceInterface && $fileOrFolderObject->getStorage()->getUid() === 0) { + if ($fileOrFolderObject instanceof ResourceInterface && $fileOrFolderObject->getStorage()->isFallbackStorage()) { return [ 'type' => LinkService::TYPE_URL, 'url' => $mixedIdentifier, diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php index e0db2210ecc3194be21c159da672af060117b9dc..38f61e19973181f59f4c9be9df137bee60b2b339 100644 --- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php +++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php @@ -354,6 +354,17 @@ class ResourceStorage implements ResourceStorageInterface return true; } + /** + * Returns true if this storage is a virtual storage that provides + * access to all files in the project root. + * + * @internal + */ + public function isFallbackStorage(): bool + { + return $this->getUid() === 0; + } + /********************************* * Capabilities ********************************/ @@ -718,7 +729,7 @@ class ResourceStorage implements ResourceStorageInterface return false; } // Check 3: No action allowed on files for denied file extensions - if (!$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkValidFileExtension($file)) { return false; } $isReadCheck = false; @@ -830,6 +841,17 @@ class ResourceStorage implements ResourceStorageInterface return GeneralUtility::makeInstance(FileNameValidator::class)->isValid($fileName); } + /** + * Check file extension of an existing file against the + * current file deny pattern. + */ + protected function checkValidFileExtension(FileInterface $file): bool + { + $fileNameValidator = GeneralUtility::makeInstance(FileNameValidator::class); + return $fileNameValidator->isValid($file->getName()) && + $fileNameValidator->isValid(basename($file->getIdentifier())); + } + /** * Assures read permission for given folder. * @@ -896,7 +918,7 @@ class ResourceStorage implements ResourceStorageInterface 1375955429 ); } - if (!$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkValidFileExtension($file)) { throw new IllegalFileExtensionException( 'You are not allowed to use that file extension. File: "' . $file->getName() . '"', 1375955430 @@ -917,7 +939,7 @@ class ResourceStorage implements ResourceStorageInterface if (!$this->checkFileActionPermission('write', $file)) { throw new InsufficientFileWritePermissionsException('Writing to file "' . $file->getIdentifier() . '" is not allowed.', 1330121088); } - if (!$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkValidFileExtension($file)) { throw new IllegalFileExtensionException('You are not allowed to edit a file with extension "' . $file->getExtension() . '"', 1366711933); } } @@ -950,7 +972,7 @@ class ResourceStorage implements ResourceStorageInterface protected function assureFileDeletePermissions(FileInterface $file) { // Check for disallowed file extensions - if (!$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkValidFileExtension($file)) { throw new IllegalFileExtensionException('You are not allowed to delete a file with extension "' . $file->getExtension() . '"', 1377778916); } // Check further permissions if file is not a processed file @@ -1071,7 +1093,7 @@ class ResourceStorage implements ResourceStorageInterface protected function assureFileRenamePermissions(FileInterface $file, $targetFileName) { // Check if file extension is allowed - if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkValidFileExtension($file)) { throw new IllegalFileExtensionException('You are not allowed to rename a file with this extension. File given: "' . $file->getName() . '"', 1371466663); } // Check if user is allowed to rename @@ -1114,7 +1136,7 @@ class ResourceStorage implements ResourceStorageInterface throw new InsufficientFolderWritePermissionsException('You are not allowed to write to the target folder "' . $targetFolder->getIdentifier() . '"', 1319550435); } // Check for a valid file extension - if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkFileExtensionPermission($file->getName())) { + if (!$this->checkFileExtensionPermission($targetFileName) || !$this->checkValidFileExtension($file)) { throw new IllegalFileExtensionException('You are not allowed to copy a file of that type.', 1319553317); } } @@ -1733,6 +1755,7 @@ class ResourceStorage implements ResourceStorageInterface string $alternativeFilename = null, string $overrideMimeType = null ): ResponseInterface { + $this->assureFileReadPermission($file); if (!$this->driver instanceof StreamableDriverInterface) { return $this->getPseudoStream($file, $asDownload, $alternativeFilename, $overrideMimeType); } diff --git a/typo3/sysext/core/Classes/Resource/Security/StoragePermissionsAspect.php b/typo3/sysext/core/Classes/Resource/Security/StoragePermissionsAspect.php index a01c7ea2f213c419bb64714b22ae187e2bbd93f2..f5459b3b93cc60ac1c06a22401a4d164645a5cab 100644 --- a/typo3/sysext/core/Classes/Resource/Security/StoragePermissionsAspect.php +++ b/typo3/sysext/core/Classes/Resource/Security/StoragePermissionsAspect.php @@ -42,13 +42,10 @@ final class StoragePermissionsAspect if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface && ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend() && !$GLOBALS['BE_USER']->isAdmin() + && !$storage->isFallbackStorage() ) { $storage->setEvaluatePermissions(true); - if ($storage->getUid() > 0) { - $storage->setUserPermissions($GLOBALS['BE_USER']->getFilePermissionsForStorage($storage)); - } else { - $storage->setEvaluatePermissions(false); - } + $storage->setUserPermissions($GLOBALS['BE_USER']->getFilePermissionsForStorage($storage)); $this->addFileMountsToStorage($storage); } } diff --git a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php index 79167723aa62ed1ef152963ae7c4bc4ca4d7b400..31bd5612667cb61b10357fb59eb4e6e74cd13c20 100644 --- a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php +++ b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php @@ -590,7 +590,7 @@ class ExtendedFileUtility extends BasicFileUtility if ($object === null) { throw new InvalidFileException('The item ' . $identifier . ' was not a file or directory', 1320122453); } - if ($object->getStorage()->getUid() === 0) { + if ($object->getStorage()->isFallbackStorage()) { throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1375889830); } return $object; diff --git a/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkSoftReferenceParserTest.php b/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkSoftReferenceParserTest.php index 2e28e6c92f44c2d8c957aa690b6bce670050b16b..e1ca423840d97cbb6e0acb6a7adaae8132b7f09e 100644 --- a/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkSoftReferenceParserTest.php +++ b/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkSoftReferenceParserTest.php @@ -247,6 +247,9 @@ final class TypoLinkSoftReferenceParserTest extends AbstractSoftReferenceParserT $storageObject->method('getUid')->willReturn(1); $fileObject = $this->createMock(File::class); $fileObject->expects(self::once())->method('getUid')->willReturn(42); + $fileObject->expects(self::any())->method('getName')->willReturn('download.jpg'); + $fileObject->expects(self::any())->method('getIdentifier')->willReturn('fileadmin/download.jpg'); + $fileObject->expects(self::any())->method('getStorage')->willReturn($storageObject); $resourceFactory = $this->createMock(ResourceFactory::class); diff --git a/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkTagSoftReferenceParserTest.php b/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkTagSoftReferenceParserTest.php index 2c96f03814fcd8825bca8f49bb0a39625b51af69..eb8d7738b3ddf80bbda5070d3f324ff27f41b671 100644 --- a/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkTagSoftReferenceParserTest.php +++ b/typo3/sysext/core/Tests/Unit/DataHandling/SoftReference/TypoLinkTagSoftReferenceParserTest.php @@ -189,6 +189,8 @@ final class TypoLinkTagSoftReferenceParserTest extends AbstractSoftReferencePars { $fileObject = $this->createMock(File::class); $fileObject->expects(self::once())->method('getUid')->willReturn(42); + $fileObject->expects(self::any())->method('getName')->willReturn('download.jpg'); + $fileObject->expects(self::any())->method('getIdentifier')->willReturn('fileadmin/download.jpg'); $resourceFactory = $this->createMock(ResourceFactory::class); $resourceFactory->method('getFileObject')->with('42')->willReturn($fileObject); diff --git a/typo3/sysext/core/Tests/Unit/LinkHandling/FileLinkHandlerTest.php b/typo3/sysext/core/Tests/Unit/LinkHandling/FileLinkHandlerTest.php index 66a3e9f9e8e1b20b4898fd57d15518bc6962a9f9..284efec7cc8f4f6ccea65f55611d0bf1af8d4e06 100644 --- a/typo3/sysext/core/Tests/Unit/LinkHandling/FileLinkHandlerTest.php +++ b/typo3/sysext/core/Tests/Unit/LinkHandling/FileLinkHandlerTest.php @@ -98,7 +98,7 @@ final class FileLinkHandlerTest extends UnitTestCase ->getMock(); // fake methods to return proper objects - $fileObject = new File(['identifier' => $expected['file'], 'name' => 'foobar.txt'], $storage); + $fileObject = new File(['identifier' => 'fileadmin/deep/down.jpg', 'name' => 'down.jpg'], $storage); $factory->method('getFileObject')->with($expected['file'])->willReturn($fileObject); $factory->method('getFileObjectFromCombinedIdentifier')->with($expected['file'])->willReturn($fileObject); $expected['file'] = $fileObject; diff --git a/typo3/sysext/filelist/Classes/Controller/File/CreateFileController.php b/typo3/sysext/filelist/Classes/Controller/File/CreateFileController.php index fcb8ff4bf8862be7f629324389f5b3552a14ffca..d7c970ef33841d167819b39394d33d8a2f0f662a 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/CreateFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/CreateFileController.php @@ -119,7 +119,7 @@ class CreateFileController $message = $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:targetNoDir'); throw new \RuntimeException($title . ': ' . $message, 1667565756); } - if ($this->folderObject->getStorage()->getUid() === 0) { + if ($this->folderObject->getStorage()->isFallbackStorage()) { throw new InsufficientFolderAccessPermissionsException( 'You are not allowed to access folders outside your storages', 1667565757 diff --git a/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php b/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php index 7ed1408363420613694e9e48f7a2e8441db46837..0ad65be4a762706d803e50c67d1a0ba8464fb379 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/EditFileController.php @@ -119,7 +119,7 @@ class EditFileController if (!$file instanceof FileInterface) { throw new InvalidFileException('Referenced target "' . $combinedIdentifier . '" could not be resolved to a valid file', 1294586841); } - if ($file->getStorage()->getUid() === 0) { + if ($file->getStorage()->isFallbackStorage()) { throw new InsufficientFileAccessPermissionsException('You are not allowed to access files outside your storages', 1375889832); } diff --git a/typo3/sysext/filelist/Classes/Controller/File/FileUploadController.php b/typo3/sysext/filelist/Classes/Controller/File/FileUploadController.php index f27b6d80d174a4f2f4b996a3fc8bc9d2b5327f74..a9d9f623863e17714b31fb3c2bd41e772a437d29 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/FileUploadController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/FileUploadController.php @@ -58,7 +58,7 @@ class FileUploadController $folder = $this->resourceFactory->retrieveFileOrFolderObject($targetFolderCombinedIdentifier); if (!$folder instanceof FolderInterface - || $folder->getStorage()->getUid() === 0 + || $folder->getStorage()->isFallbackStorage() ) { throw new InsufficientFolderAccessPermissionsException('You are not allowed to access folders outside your storages, or the folder couldn\'t be resolved', 1375889834); } diff --git a/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php b/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php index 10634c27e3b7eee24cdaee8def7abee86c849bd8..39f50c38af761127e2229d17a740f3d00f4674b8 100644 --- a/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php +++ b/typo3/sysext/filelist/Classes/Controller/File/ReplaceFileController.php @@ -103,7 +103,7 @@ class ReplaceFileController $message = $lang->sL('LLL:EXT:filelist/Resources/Private/Language/locallang_mod_file_list.xlf:targetNoDir'); throw new \RuntimeException($title . ': ' . $message, 1436895930); } - if ($this->fileOrFolderObject->getStorage()->getUid() === 0) { + if ($this->fileOrFolderObject->getStorage()->isFallbackStorage()) { throw new InsufficientFileAccessPermissionsException( 'You are not allowed to access files outside your storages', 1436895931 diff --git a/typo3/sysext/filelist/Classes/Controller/FileListController.php b/typo3/sysext/filelist/Classes/Controller/FileListController.php index fd0bd0840082c857d78e31c0c8c335cde24752bb..dd09637fa2b77f3c9ac954e0c8a99734f476d983 100644 --- a/typo3/sysext/filelist/Classes/Controller/FileListController.php +++ b/typo3/sysext/filelist/Classes/Controller/FileListController.php @@ -124,7 +124,7 @@ class FileListController implements LoggerAwareInterface } $this->folderObject = $storage->getFolder($identifier); // Disallow access to fallback storage 0 - if ($storage->getUid() === 0) { + if ($storage->isFallbackStorage()) { throw new InsufficientFolderAccessPermissionsException( 'You are not allowed to access files outside your storages', 1434539815 diff --git a/typo3/sysext/filelist/Classes/LinkHandler/AbstractResourceLinkHandler.php b/typo3/sysext/filelist/Classes/LinkHandler/AbstractResourceLinkHandler.php index 06665c551658c427ba228cc0c82723dbc9deb11a..07d282e01583627009d35dfdb8ac73971f4b7b42 100644 --- a/typo3/sysext/filelist/Classes/LinkHandler/AbstractResourceLinkHandler.php +++ b/typo3/sysext/filelist/Classes/LinkHandler/AbstractResourceLinkHandler.php @@ -98,6 +98,13 @@ abstract class AbstractResourceLinkHandler implements LinkHandlerInterface, Link public function formatCurrentUrl(): string { + $resource = $this->linkParts['url'][$this->type->value]; + if (!$resource->checkActionPermission('read')) { + return ''; + } + if ($resource->getStorage()->isFallbackStorage()) { + return ''; + } return $this->linkParts['url'][$this->type->value]->getName(); } @@ -181,6 +188,12 @@ abstract class AbstractResourceLinkHandler implements LinkHandlerInterface, Link } catch (FolderDoesNotExistException $e) { } } + if ($this->selectedFolder?->checkActionPermission('read') === false) { + $this->selectedFolder = null; + } + if ($this->selectedFolder?->getStorage()?->isFallbackStorage()) { + $this->selectedFolder = null; + } if (!$this->selectedFolder) { $this->selectedFolder = $this->resourceFactory->getDefaultStorage()?->getRootLevelFolder() ?? null; } @@ -202,6 +215,13 @@ abstract class AbstractResourceLinkHandler implements LinkHandlerInterface, Link public function isUpdateSupported(): bool { + $resource = $this->linkParts['url'][$this->type->value]; + if (!$resource->checkActionPermission('read')) { + return false; + } + if ($resource->getStorage()->isFallbackStorage()) { + return false; + } return true; } @@ -215,15 +235,22 @@ abstract class AbstractResourceLinkHandler implements LinkHandlerInterface, Link */ public function getBodyTagAttributes(): array { - if (isset($this->linkParts['url'][$this->type->value]) && $this->linkParts['url'][$this->type->value] instanceof ($this->type->getResourceType())) { - return [ - 'data-linkbrowser-current-link' => GeneralUtility::makeInstance(LinkService::class)->asString([ - 'type' => $this->type->getLinkServiceType(), - $this->type->value => $this->linkParts['url'][$this->type->value], - ]), - ]; + $resource = $this->linkParts['url'][$this->type->value] ?? null; + if (!$resource instanceof ($this->type->getResourceType())) { + return []; + } + if (!$resource->checkActionPermission('read')) { + return []; + } + if ($resource->getStorage()->isFallbackStorage()) { + return []; } - return []; + return [ + 'data-linkbrowser-current-link' => GeneralUtility::makeInstance(LinkService::class)->asString([ + 'type' => $this->type->getLinkServiceType(), + $this->type->value => $resource, + ]), + ]; } protected function createUri(ServerRequestInterface $request, array $parameters = []): string