Skip to content

Commit 04db479

Browse files
Merge pull request #62837 from nextcloud/backport/62807/stable34
[stable34] check free space in the proper folder when restoring from trash
2 parents e8f3f05 + 1ce88b3 commit 04db479

4 files changed

Lines changed: 63 additions & 16 deletions

File tree

apps/files_trashbin/lib/Sabre/TrashbinPlugin.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use OC\Files\View;
1313
use OCA\DAV\Connector\Sabre\FilesPlugin;
1414
use OCA\Files_Trashbin\Trash\ITrashItem;
15+
use OCP\Files\IRootFolder;
16+
use OCP\Files\Mount\IMountManager;
1517
use OCP\IPreview;
1618
use Psr\Log\LoggerInterface;
1719
use Sabre\DAV\INode;
@@ -42,7 +44,8 @@ class TrashbinPlugin extends ServerPlugin {
4244

4345
public function __construct(
4446
private readonly IPreview $previewManager,
45-
private readonly View $view,
47+
private readonly IRootFolder $rootFolder,
48+
private readonly IMountManager $mountManager,
4649
) {
4750
}
4851

@@ -175,7 +178,16 @@ public function beforeMove(string $sourcePath, string $destinationPath): bool {
175178
return true;
176179
}
177180

178-
$freeSpace = $this->view->free_space($destinationParentPath);
181+
$userFolder = $this->rootFolder->getUserFolder($fileInfo->getUser()->getUID());
182+
$originalPath = $userFolder->getFullPath(dirname($fileInfo->getOriginalLocation()));
183+
184+
// Since the parent folder might no longer exist, we don't try to get the parent node to check the free space
185+
// instead we resolve the mount where the restore would go to, and check that for the free space
186+
$originalMount = $this->mountManager->find($originalPath);
187+
if (!$originalMount) {
188+
throw new \Exception('no mount found when looking for restore path');
189+
}
190+
$freeSpace = $originalMount->getStorage()->free_space($originalMount->getInternalPath($originalPath));
179191

180192
if (
181193
$freeSpace === FileInfo::SPACE_NOT_COMPUTED

apps/files_trashbin/lib/Trashbin.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
use OCP\Files\IMimeTypeLoader;
3838
use OCP\Files\IRootFolder;
3939
use OCP\Files\Node;
40+
use OCP\Files\NotEnoughSpaceException;
4041
use OCP\Files\NotFoundException;
4142
use OCP\Files\NotPermittedException;
4243
use OCP\Files\Storage\ILockingStorage;
@@ -568,6 +569,14 @@ public static function restore($file, $filename, $timestamp) {
568569

569570
$sourceNode = self::getNodeForPath($user, $sourcePath);
570571
$targetNode = self::getNodeForPath($user, $targetPath, 'files');
572+
573+
$targetParent = $targetNode->getParent();
574+
575+
$free = $targetParent->getFreeSpace();
576+
if ($free >= 0 && $free < $sourceNode->getSize(false)) {
577+
throw new NotEnoughSpaceException('Not enough free space in ' . $targetParent->getPath() . ' to restore ' . $sourceNode->getPath());
578+
}
579+
571580
$run = true;
572581
$event = new BeforeNodeRestoredEvent($sourceNode, $targetNode, $run);
573582
$dispatcher = Server::get(IEventDispatcher::class);

apps/files_trashbin/tests/Sabre/TrashbinPluginTest.php

Lines changed: 40 additions & 9 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';
@@ -60,11 +91,11 @@ public function testQuota(int $quota, int $fileSize, bool $expectedResult): void
6091

6192
public static function quotaProvider(): array {
6293
return [
63-
[ 1024 * 1024, 512 * 1024, true ],
64-
[ 512 * 1024, 513 * 1024, false ],
65-
[ FileInfo::SPACE_NOT_COMPUTED, 1024 * 1024, true ],
66-
[ FileInfo::SPACE_UNKNOWN, 1024 * 1024, true ],
67-
[ FileInfo::SPACE_UNLIMITED, 1024 * 1024, true ]
94+
[1024 * 1024, 512 * 1024, true],
95+
[512 * 1024, 513 * 1024, false],
96+
[FileInfo::SPACE_NOT_COMPUTED, 1024 * 1024, true],
97+
[FileInfo::SPACE_UNKNOWN, 1024 * 1024, true],
98+
[FileInfo::SPACE_UNLIMITED, 1024 * 1024, true]
6899
];
69100
}
70101
}

build/psalm-baseline.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,11 +1905,6 @@
19051905
<code><![CDATA[INode]]></code>
19061906
</MismatchingDocblockReturnType>
19071907
</file>
1908-
<file src="apps/files_trashbin/lib/Sabre/TrashbinPlugin.php">
1909-
<InternalMethod>
1910-
<code><![CDATA[free_space]]></code>
1911-
</InternalMethod>
1912-
</file>
19131908
<file src="apps/files_trashbin/lib/Storage.php">
19141909
<DeprecatedMethod>
19151910
<code><![CDATA[dispatch]]></code>

0 commit comments

Comments
 (0)