Skip to content

Commit 55181aa

Browse files
Merge pull request #62835 from nextcloud/backport/62807/stable32
[stable32] check free space in the proper folder when restoring from trash
2 parents 2dc7e88 + 16b548f commit 55181aa

3 files changed

Lines changed: 63 additions & 10 deletions

File tree

apps/files_trashbin/lib/Sabre/TrashbinPlugin.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
namespace OCA\Files_Trashbin\Sabre;
1010

1111
use OC\Files\FileInfo;
12-
use OC\Files\View;
1312
use OCA\DAV\Connector\Sabre\FilesPlugin;
1413
use OCA\Files_Trashbin\Trash\ITrashItem;
14+
use OCP\Files\IRootFolder;
15+
use OCP\Files\Mount\IMountManager;
1516
use OCP\IPreview;
1617
use Psr\Log\LoggerInterface;
1718
use Sabre\DAV\INode;
@@ -36,7 +37,8 @@ class TrashbinPlugin extends ServerPlugin {
3637

3738
public function __construct(
3839
private IPreview $previewManager,
39-
private View $view,
40+
private IRootFolder $rootFolder,
41+
private IMountManager $mountManager,
4042
) {
4143
}
4244

@@ -164,9 +166,20 @@ public function beforeMove(string $sourcePath, string $destinationPath): bool {
164166
if (!$fileInfo instanceof ITrashItem) {
165167
return true;
166168
}
167-
$restoreFolder = dirname($fileInfo->getOriginalLocation());
168-
$freeSpace = $this->view->free_space($restoreFolder);
169-
if ($freeSpace === FileInfo::SPACE_NOT_COMPUTED
169+
170+
$userFolder = $this->rootFolder->getUserFolder($fileInfo->getUser()->getUID());
171+
$originalPath = $userFolder->getFullPath(dirname($fileInfo->getOriginalLocation()));
172+
173+
// Since the parent folder might no longer exist, we don't try to get the parent node to check the free space
174+
// instead we resolve the mount where the restore would go to, and check that for the free space
175+
$originalMount = $this->mountManager->find($originalPath);
176+
if (!$originalMount) {
177+
throw new \Exception('no mount found when looking for restore path');
178+
}
179+
$freeSpace = $originalMount->getStorage()->free_space($originalMount->getInternalPath($originalPath));
180+
181+
if (
182+
$freeSpace === FileInfo::SPACE_NOT_COMPUTED
170183
|| $freeSpace === FileInfo::SPACE_UNKNOWN
171184
|| $freeSpace === FileInfo::SPACE_UNLIMITED) {
172185
return true;

apps/files_trashbin/lib/Trashbin.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use OCP\Files\IMimeTypeLoader;
3535
use OCP\Files\IRootFolder;
3636
use OCP\Files\Node;
37+
use OCP\Files\NotEnoughSpaceException;
3738
use OCP\Files\NotFoundException;
3839
use OCP\Files\NotPermittedException;
3940
use OCP\Files\Storage\ILockingStorage;
@@ -561,6 +562,14 @@ public static function restore($file, $filename, $timestamp) {
561562

562563
$sourceNode = self::getNodeForPath($user, $sourcePath);
563564
$targetNode = self::getNodeForPath($user, $targetPath, 'files');
565+
566+
$targetParent = $targetNode->getParent();
567+
568+
$free = $targetParent->getFreeSpace();
569+
if ($free >= 0 && $free < $sourceNode->getSize(false)) {
570+
throw new NotEnoughSpaceException('Not enough free space in ' . $targetParent->getPath() . ' to restore ' . $sourceNode->getPath());
571+
}
572+
564573
$run = true;
565574
$event = new BeforeNodeRestoredEvent($sourceNode, $targetNode, $run);
566575
$dispatcher = Server::get(IEventDispatcher::class);

apps/files_trashbin/tests/Sabre/TrashbinPluginTest.php

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99
namespace OCA\Files_Trashbin\Tests\Sabre;
1010

1111
use OC\Files\FileInfo;
12-
use OC\Files\View;
1312
use OCA\Files_Trashbin\Sabre\ITrash;
1413
use OCA\Files_Trashbin\Sabre\RestoreFolder;
1514
use OCA\Files_Trashbin\Sabre\TrashbinPlugin;
1615
use OCA\Files_Trashbin\Trash\ITrashItem;
16+
use OCP\Files\Folder;
17+
use OCP\Files\IRootFolder;
18+
use OCP\Files\Mount\IMountManager;
19+
use OCP\Files\Mount\IMountPoint;
20+
use OCP\Files\Storage\IStorage;
1721
use OCP\IPreview;
22+
use OCP\IUser;
1823
use Sabre\DAV\Server;
1924
use Sabre\DAV\Tree;
2025
use Test\TestCase;
@@ -34,6 +39,13 @@ public function testQuota(int $quota, int $fileSize, bool $expectedResult): void
3439
$fileInfo = $this->createMock(ITrashItem::class);
3540
$fileInfo->method('getSize')
3641
->willReturn($fileSize);
42+
$user = $this->createMock(IUser::class);
43+
$user->method('getUID')
44+
->willReturn('test');
45+
$fileInfo->method('getUser')
46+
->willReturn($user);
47+
$fileInfo->method('getOriginalLocation')
48+
->willReturn('relative/original/location');
3749

3850
$trashNode = $this->createMock(ITrash::class);
3951
$trashNode->method('getFileInfo')
@@ -46,11 +58,30 @@ public function testQuota(int $quota, int $fileSize, bool $expectedResult): void
4658

4759
$previewManager = $this->createMock(IPreview::class);
4860

49-
$view = $this->createMock(View::class);
50-
$view->method('free_space')
61+
$userFolder = $this->createMock(Folder::class);
62+
$userFolder->method('getFullPath')
63+
->with('relative/original') // the parent path
64+
->willReturn('/full/path/to/original');
65+
$rootFolder = $this->createMock(IRootFolder::class);
66+
$rootFolder->method('getUserFolder')
67+
->willReturn($userFolder);
68+
69+
$storage = $this->createMock(IStorage::class);
70+
$storage->method('free_space')
71+
->with('path/to/original')
5172
->willReturn($quota);
73+
$mount = $this->createMock(IMountPoint::class);
74+
$mount->method('getStorage')
75+
->willReturn($storage);
76+
$mount->method('getInternalPath')
77+
->with('/full/path/to/original')
78+
->willReturn('path/to/original');
79+
$mountManager = $this->createMock(IMountManager::class);
80+
$mountManager->method('find')
81+
->with('/full/path/to/original')
82+
->willReturn($mount);
5283

53-
$plugin = new TrashbinPlugin($previewManager, $view);
84+
$plugin = new TrashbinPlugin($previewManager, $rootFolder, $mountManager);
5485
$plugin->initialize($this->server);
5586

5687
$sourcePath = 'trashbin/test/trash/file1';
@@ -63,7 +94,7 @@ public static function quotaProvider(): array {
6394
[ 1024, 512, true ],
6495
[ 512, 513, false ],
6596
[ FileInfo::SPACE_NOT_COMPUTED, 1024, true ],
66-
[ FileInfo::SPACE_UNKNOWN, 1024, true ],
97+
[ FileInfo::SPACE_UNKNOWN, 1024, true],
6798
[ FileInfo::SPACE_UNLIMITED, 1024, true ]
6899
];
69100
}

0 commit comments

Comments
 (0)