diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 9e3ec663f03e3..24969ece45442 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -538,11 +538,13 @@ private function canDoCrossStorageMove(IStorage $sourceStorage): bool { public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, bool $preserveMtime = false): bool { if ($this->canDoCrossStorageMove($sourceStorage)) { - if ($sourceStorage->instanceOfStorage(Jail::class)) { + // resolve any jailed paths + while ($sourceStorage->instanceOfStorage(Jail::class)) { /** * @var \OC\Files\Storage\Wrapper\Jail $sourceStorage */ $sourceInternalPath = $sourceStorage->getUnjailedPath($sourceInternalPath); + $sourceStorage = $sourceStorage->getUnjailedStorage(); } /** * @var \OC\Files\Storage\Local $sourceStorage @@ -556,11 +558,13 @@ public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalP public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool { if ($this->canDoCrossStorageMove($sourceStorage)) { - if ($sourceStorage->instanceOfStorage(Jail::class)) { + // resolve any jailed paths + while ($sourceStorage->instanceOfStorage(Jail::class)) { /** * @var \OC\Files\Storage\Wrapper\Jail $sourceStorage */ $sourceInternalPath = $sourceStorage->getUnjailedPath($sourceInternalPath); + $sourceStorage = $sourceStorage->getUnjailedStorage(); } /** * @var \OC\Files\Storage\Local $sourceStorage diff --git a/tests/lib/Files/Storage/LocalTest.php b/tests/lib/Files/Storage/LocalTest.php index 4a98970f233af..06e3d9f47e3de 100644 --- a/tests/lib/Files/Storage/LocalTest.php +++ b/tests/lib/Files/Storage/LocalTest.php @@ -7,6 +7,8 @@ namespace Test\Files\Storage; +use OC\Files\Storage\Wrapper\Jail; + /** * Class LocalTest * @@ -135,4 +137,25 @@ public function testUnavailableNonExternal(): void { // no exception thrown $this->assertNotNull($this->instance); } + + public function testMoveNestedJail(): void { + $this->instance->mkdir('foo'); + $this->instance->mkdir('foo/bar'); + $this->instance->mkdir('target'); + $this->instance->file_put_contents('foo/bar/file.txt', 'foo'); + $jail1 = new Jail([ + 'storage' => $this->instance, + 'root' => 'foo' + ]); + $jail2 = new Jail([ + 'storage' => $jail1, + 'root' => 'bar' + ]); + $jail3 = new Jail([ + 'storage' => $this->instance, + 'root' => 'target' + ]); + $jail3->moveFromStorage($jail2, 'file.txt', 'file.txt'); + $this->assertTrue($this->instance->file_exists('target/file.txt')); + } }