[BUGFIX] Do not move processed files to recycler folder 17/56917/2
authorNicole Cordes <typo3@cordes.co>
Thu, 10 May 2018 22:06:16 +0000 (00:06 +0200)
committerNicole Cordes <typo3@cordes.co>
Sat, 12 May 2018 10:16:29 +0000 (12:16 +0200)
When a file gets moved to the recycler folder on delete. The processed
files should not be moved to the recycler folder but directly deleted.

Resolves: #81836
Releases: master, 8.7
Change-Id: I7a53830ea5d96735243fd9ee89e8c5aa80d084c0
Reviewed-on: https://review.typo3.org/56917
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Guido Schmechel <guido.schmechel@brandung.de>
Tested-by: Guido Schmechel <guido.schmechel@brandung.de>
Reviewed-by: Alessandro Filira <alessandro.filira@pallino.it>
Tested-by: Alessandro Filira <alessandro.filira@pallino.it>
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Tested-by: Nicole Cordes <typo3@cordes.co>
typo3/sysext/core/Classes/Resource/Driver/LocalDriver.php
typo3/sysext/core/Classes/Resource/ResourceStorage.php
typo3/sysext/filelist/Classes/FileList.php

index 264a6b8..f7a91f6 100644 (file)
@@ -1174,12 +1174,7 @@ class LocalDriver extends AbstractHierarchicalFilesystemDriver
     public function deleteFile($fileIdentifier)
     {
         $filePath = $this->getAbsolutePath($fileIdentifier);
-        $recycleDirectory = $this->getRecycleDirectory($filePath);
-        if (!empty($recycleDirectory)) {
-            $result = $this->recycleFileOrFolder($filePath, $recycleDirectory);
-        } else {
-            $result = unlink($filePath);
-        }
+        $result = unlink($filePath);
         if ($result === false) {
             throw new \RuntimeException('Deletion of file ' . $fileIdentifier . ' failed.', 1320855304);
         }
index 5063efa..983bea0 100644 (file)
@@ -1719,15 +1719,23 @@ class ResourceStorage implements ResourceStorageInterface
         $this->assureFileDeletePermissions($fileObject);
 
         $this->emitPreFileDeleteSignal($fileObject);
+        $deleted = true;
 
         if ($this->driver->fileExists($fileObject->getIdentifier())) {
-            $result = $this->driver->deleteFile($fileObject->getIdentifier());
+            $recyclerFolder = $this->getNearestRecyclerFolder($fileObject);
+
+            if ($recyclerFolder === null) {
+                $result = $this->driver->deleteFile($fileObject->getIdentifier());
+            } else {
+                $result = $this->moveFile($fileObject, $recyclerFolder);
+                $deleted = false;
+            }
             if (!$result) {
                 throw new Exception\FileOperationErrorException('Deleting the file "' . $fileObject->getIdentifier() . '\' failed.', 1329831691);
             }
         }
         // Mark the file object as deleted
-        if ($fileObject instanceof AbstractFile) {
+        if ($deleted && $fileObject instanceof AbstractFile) {
             $fileObject->setDeleted();
         }
 
@@ -1826,7 +1834,12 @@ class ResourceStorage implements ResourceStorageInterface
             } else {
                 $tempPath = $file->getForLocalProcessing();
                 $newIdentifier = $this->driver->addFile($tempPath, $targetFolder->getIdentifier(), $sanitizedTargetFileName);
-                $sourceStorage->driver->deleteFile($file->getIdentifier());
+                $recyclerFolder = $this->getNearestRecyclerFolder($file);
+                if ($recyclerFolder === null) {
+                    $sourceStorage->driver->deleteFile($file->getIdentifier());
+                } else {
+                    $this->moveFile($file, $recyclerFolder);
+                }
                 if ($file instanceof File) {
                     $file->updateProperties(['storage' => $this->getUid(), 'identifier' => $newIdentifier]);
                 }
@@ -3023,6 +3036,45 @@ class ResourceStorage implements ResourceStorageInterface
     }
 
     /**
+     * Get the nearest Recycler folder for given file
+     *
+     * Return null if:
+     *  - There is no folder with ROLE_RECYCLER in the rootline of the given File
+     *  - File is a ProcessedFile (we don't know the concept of recycler folders for processedFiles)
+     *  - File is located in a folder with ROLE_RECYCLER
+     *
+     * @param FileInterface $file
+     * @return Folder|null
+     */
+    protected function getNearestRecyclerFolder(FileInterface $file)
+    {
+        if ($file instanceof ProcessedFile) {
+            return null;
+        }
+
+        $recyclerFolder = null;
+        $rootFolder = $this->getRootLevelFolder(false);
+        $folder = null;
+
+        do {
+            $folder = $folder !== null ? $folder->getParentFolder() : $file->getParentFolder();
+
+            if ($folder->getRole() === FolderInterface::ROLE_RECYCLER) {
+                break;
+            }
+
+            foreach ($folder->getSubfolders() as $subFolder) {
+                if ($subFolder->getRole() === FolderInterface::ROLE_RECYCLER) {
+                    $recyclerFolder = $subFolder;
+                    break;
+                }
+            }
+        } while ($recyclerFolder === null && $folder !== $rootFolder);
+
+        return $recyclerFolder;
+    }
+
+    /**
      * @return \TYPO3\CMS\Core\Log\Logger
      */
     protected function getLogger()
index 33ea383..729d216 100644 (file)
@@ -742,7 +742,7 @@ class FileList extends AbstractRecordList
                             $processedFile = $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, []);
                             if ($processedFile) {
                                 $thumbUrl = $processedFile->getPublicUrl(true);
-                                $theData[$field] .= '<br /><img src="' . $thumbUrl . '" ' .
+                                $theData[$field] .= '<br /><img src="' . htmlspecialchars($thumbUrl) . '" ' .
                                     'width="' . $processedFile->getProperty('width') . '" ' .
                                     'height="' . $processedFile->getProperty('height') . '" ' .
                                     'title="' . htmlspecialchars($fileName) . '" alt="" />';