From a52ca0e92a99f7b7c5b152b11d78ad0fb2017c53 Mon Sep 17 00:00:00 2001
From: Nicole Cordes <typo3@cordes.co>
Date: Fri, 25 May 2018 14:05:16 +0200
Subject: [PATCH] [BUGFIX] Handle access restrictions on recycler search

Fetching a parent folder may throws an error if the user hasn't
access to the parent. This exception needs to be caught and the
search for an existing recycler folder needs to be stopped
immediately.

Furthermore the patch removes the comparison with the root level
folder but checks the parent folder doesn't equal the folder itself.

Another loop is fixed by calling moveFile on the correct
ResourceStorge and not the current one.

Resolves: #85079
Related: #81836
Releases: master, 8.7
Change-Id: I51f5e20d7fa7da9b350ac0ca60cab05866a4d337
Reviewed-on: https://review.typo3.org/57052
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Frans Saris <franssaris@gmail.com>
Tested-by: Frans Saris <franssaris@gmail.com>
---
 .../core/Classes/Resource/ResourceStorage.php | 29 ++++++++++++++-----
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
index 0d34b943f8f1..56c8cb30be83 100644
--- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php
+++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
@@ -1697,14 +1697,20 @@ class ResourceStorage implements ResourceStorageInterface
         $deleted = true;
 
         if ($this->driver->fileExists($fileObject->getIdentifier())) {
-            $recyclerFolder = $this->getNearestRecyclerFolder($fileObject);
+            // Disable permission check to find nearest recycler and move file without errors
+            $currentPermissions = $this->evaluatePermissions;
+            $this->evaluatePermissions = false;
 
+            $recyclerFolder = $this->getNearestRecyclerFolder($fileObject);
             if ($recyclerFolder === null) {
                 $result = $this->driver->deleteFile($fileObject->getIdentifier());
             } else {
                 $result = $this->moveFile($fileObject, $recyclerFolder);
                 $deleted = false;
             }
+
+            $this->evaluatePermissions = $currentPermissions;
+
             if (!$result) {
                 throw new Exception\FileOperationErrorException('Deleting the file "' . $fileObject->getIdentifier() . '\' failed.', 1329831691);
             }
@@ -1809,12 +1815,18 @@ class ResourceStorage implements ResourceStorageInterface
             } else {
                 $tempPath = $file->getForLocalProcessing();
                 $newIdentifier = $this->driver->addFile($tempPath, $targetFolder->getIdentifier(), $sanitizedTargetFileName);
-                $recyclerFolder = $this->getNearestRecyclerFolder($file);
+
+                // Disable permission check to find nearest recycler and move file without errors
+                $currentPermissions = $sourceStorage->evaluatePermissions;
+                $sourceStorage->evaluatePermissions = false;
+
+                $recyclerFolder = $sourceStorage->getNearestRecyclerFolder($file);
                 if ($recyclerFolder === null) {
                     $sourceStorage->driver->deleteFile($file->getIdentifier());
                 } else {
-                    $this->moveFile($file, $recyclerFolder);
+                    $sourceStorage->moveFile($file, $recyclerFolder);
                 }
+                $sourceStorage->evaluatePermissions = $currentPermissions;
                 if ($file instanceof File) {
                     $file->updateProperties(['storage' => $this->getUid(), 'identifier' => $newIdentifier]);
                 }
@@ -3028,12 +3040,9 @@ class ResourceStorage implements ResourceStorageInterface
         }
 
         $recyclerFolder = null;
-        $rootFolder = $this->getRootLevelFolder(false);
-        $folder = null;
+        $folder = $file->getParentFolder();
 
         do {
-            $folder = $folder !== null ? $folder->getParentFolder() : $file->getParentFolder();
-
             if ($folder->getRole() === FolderInterface::ROLE_RECYCLER) {
                 break;
             }
@@ -3044,7 +3053,11 @@ class ResourceStorage implements ResourceStorageInterface
                     break;
                 }
             }
-        } while ($recyclerFolder === null && $folder->getCombinedIdentifier() !== $rootFolder->getCombinedIdentifier());
+
+            $parentFolder = $folder->getParentFolder();
+            $isFolderLoop = $folder->getIdentifier() === $parentFolder->getIdentifier();
+            $folder = $parentFolder;
+        } while ($recyclerFolder === null && !$isFolderLoop);
 
         return $recyclerFolder;
     }
-- 
GitLab