diff --git a/lib/Trash/TrashBackend.php b/lib/Trash/TrashBackend.php index 8d4e384f0..96661e9ff 100644 --- a/lib/Trash/TrashBackend.php +++ b/lib/Trash/TrashBackend.php @@ -23,6 +23,7 @@ use OC\Files\Storage\Wrapper\Encryption; use OCA\Files_Trashbin\Expiration; +use OCA\Files_Trashbin\Storage; use OCA\Files_Trashbin\Trash\ITrashBackend; use OCA\Files_Trashbin\Trash\ITrashItem; use OCA\GroupFolders\ACL\ACLManagerFactory; @@ -229,7 +230,14 @@ public function moveToTrash(IStorage $storage, string $internalPath): bool { $name = basename($internalPath); $fileEntry = $storage->getCache()->get($internalPath); $folderId = $storage->getFolderId(); - $trashFolder = $this->getTrashFolder($folderId); + $user = $this->userSession->getUser(); + if (!$user) { + throw new \Exception("file moved to trash with no user in context"); + } + // ensure the folder exists + $this->getTrashFolder($folderId); + + $trashFolder = $this->rootFolder->get('/' . $user->getUID() . '/files_trashbin/groupfolders/' . $folderId); $trashStorage = $trashFolder->getStorage(); $time = time(); $trashName = $name . '.d' . $time; @@ -242,8 +250,15 @@ public function moveToTrash(IStorage $storage, string $internalPath): bool { } if ($result) { $this->trashManager->addTrashItem($folderId, $name, $time, $internalPath, $fileEntry->getId()); - if ($trashStorage->getCache()->getId($targetInternalPath) !== $fileEntry->getId()) { + + // some storage backends (object/encryption) can either already move the cache item or cause the target to be scanned + // so we only conditionally do the cache move here + if (!$trashStorage->getCache()->inCache($targetInternalPath)) { + // doesn't exist in target yet, do the move $trashStorage->getCache()->moveFromCache($storage->getCache(), $internalPath, $targetInternalPath); + } elseif ($storage->getCache()->inCache($internalPath)) { + // exists in both source and target, cleanup source + $storage->getCache()->remove($internalPath); } } else { throw new \Exception("Failed to move groupfolder item to trash"); @@ -264,6 +279,11 @@ private function moveFromEncryptedStorage(IStorage $sourceStorage, IStorage $tar return false; } + // the trash should be the top wrapper, remove it to prevent recursive attempts to move to trash + if ($sourceStorage instanceof Storage) { + $sourceStorage = $sourceStorage->getWrapperStorage(); + } + $result = $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, true); if ($result) { if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class)) {