diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php index 6c928c4d1b7a..090eb5fcac27 100644 --- a/apps/dav/lib/Connector/Sabre/File.php +++ b/apps/dav/lib/Connector/Sabre/File.php @@ -111,7 +111,8 @@ public function put($data) { if ($needsPartFile) { // mark file as partial while uploading (ignored by the scanner) - $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part'; + $fullPath = $this->getPartFileBasePath($this->path); + $partFilePath = dirname($fullPath) . '/' . sha1(basename($fullPath)) . '.ocTransferId' . rand() . '.part'; } else { // upload file directly as the final path $partFilePath = $this->path; @@ -427,12 +428,11 @@ private function createFileChunked($data) { list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath); if ($needsPartFile) { - // we first assembly the target file as a part file - $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part'; + // we first assemble the target file as a part file + $partFile = $this->getPartFileBasePath($path . '/' . sha1($info['name'])) . '.ocTransferId' . $info['transferid'] . '.part'; /** @var \OC\Files\Storage\Storage $targetStorage */ list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile); - $chunk_handler->file_assemble($partStorage, $partInternalPath); // here is the final atomic rename diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php index e8ce11fb20f4..9b82542ddb8f 100644 --- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php @@ -1002,4 +1002,87 @@ public function testGetFopenThrows() { $file->get(); } + + public function testPutCreatesPartFile() { + $stream = $this->getStream('ABCDEFG'); + $storage = $this->getMockBuilder(Local::class) + ->setMethods(['fopen', 'moveFromStorage', 'file_exists']) + ->setConstructorArgs([['datadir' => \OC::$server->getTempManager()->getTemporaryFolder()]]) + ->getMock(); + + $storage->expects($this->atLeastOnce()) + ->method('fopen') + ->with($this->matchesRegularExpression('/a1f13b3bc20a296e08c212be9c56c706c10abc4f.ocTransferId([0-9]+).part$/i')) + ->willReturn($stream); + + $storage->method('moveFromStorage') + ->willReturn(true); + + $storage->method('file_exists') + ->willReturn(true); + + + $path = '/' . $this->user . '/files'; + $info = new FileInfo($path, $this->getMockStorage(), null, [ + 'permissions' => Constants::PERMISSION_ALL + ], null); + + $view = $this->getMockBuilder(View::class) + ->setMethods(['fopen', 'resolvePath']) + ->getMock(); + + + $view->expects($this->atLeastOnce()) + ->method('resolvePath') + ->will($this->returnCallback( + function ($path) use ($storage) { + return [$storage, $path]; + } + )); + + $file = new File($view, $info); + $file->put($stream); + } + + public function testPutWithChunkCreatesPartFile() { + $stream = $this->getStream('ABCDEFG'); + + $storage = $this->getMockBuilder(Local::class) + ->setMethods(['fopen', 'moveFromStorage', 'file_exists']) + ->setConstructorArgs([['datadir' => \OC::$server->getTempManager()->getTemporaryFolder()]]) + ->getMock(); + + $storage->expects($this->atLeastOnce()) + ->method('fopen') + ->with($this->matchesRegularExpression('/^\/1cf7c9c735f7fd721ebe33ea1e7d259397f24007.ocTransferId([0-9]+).part$/i')) + ->willReturn($this->getStream('FOO1231')); + + $path = 'foo.dat-chunking-13242432-0-0'; + + $info = new FileInfo($path, $this->getMockStorage(), null, [ + 'permissions' => Constants::PERMISSION_ALL + ], null); + $info['checksum'] = 'abcdefg123'; + $info['etag'] = 'deadbeef1337'; + + $view = $this->getMockBuilder(View::class) + ->setMethods(['fopen', 'resolvePath', 'getFileInfo']) + ->getMock(); + + $view->method('getFileInfo') + ->willReturn($info); + + $view->expects($this->atLeastOnce()) + ->method('resolvePath') + ->will($this->returnCallback( + function ($path) use ($storage) { + return [$storage, $path]; + } + )); + + + $_SERVER['HTTP_OC_CHUNKED'] = true; + $file = new File($view, $info); + $file->put($stream); + } }