/** * Creates a new file in the directory * * Data will either be supplied as a stream resource, or in certain cases * as a string. Keep in mind that you may have to support either. * * After successful creation of the file, you may choose to return the ETag * of the new file here. * * The returned ETag must be surrounded by double-quotes (The quotes should * be part of the actual string). * * If you cannot accurately determine the ETag, you should not return it. * If you don't store the file exactly as-is (you're transforming it * somehow) you should also not return an ETag. * * This means that if a subsequent GET to this new file does not exactly * return the same contents of what was submitted here, you are strongly * recommended to omit the ETag. * * @param string $name Name of the file * @param resource|string $data Initial payload * @return null|string * @throws Exception\EntityTooLarge * @throws Exception\UnsupportedMediaType * @throws FileLocked * @throws InvalidPath * @throws \Sabre\DAV\Exception * @throws \Sabre\DAV\Exception\BadRequest * @throws \Sabre\DAV\Exception\Forbidden * @throws \Sabre\DAV\Exception\ServiceUnavailable */ public function createFile($name, $data = null) { try { // for chunked upload also updating a existing file is a "createFile" // because we create all the chunks before re-assemble them to the existing file. if (isset($_SERVER['HTTP_OC_CHUNKED'])) { // exit if we can't create a new file and we don't updatable existing file $info = \OC_FileChunking::decodeName($name); if (!$this->fileView->isCreatable($this->path) && !$this->fileView->isUpdatable($this->path . '/' . $info['name'])) { throw new \Sabre\DAV\Exception\Forbidden(); } } else { // For non-chunked upload it is enough to check if we can create a new file if (!$this->fileView->isCreatable($this->path)) { throw new \Sabre\DAV\Exception\Forbidden(); } } $this->fileView->verifyPath($this->path, $name); $path = $this->fileView->getAbsolutePath($this->path) . '/' . $name; // using a dummy FileInfo is acceptable here since it will be refreshed after the put is complete $info = new \OC\Files\FileInfo($path, null, null, array(), null); $node = new \OC\Connector\Sabre\File($this->fileView, $info); return $node->put($data); } catch (\OCP\Files\StorageNotAvailableException $e) { throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage()); } catch (\OCP\Files\InvalidPathException $ex) { throw new InvalidPath($ex->getMessage()); } catch (LockedException $e) { throw new FileLocked($e->getMessage(), $e->getCode(), $e); } }
/** * @dataProvider davPermissionsProvider */ public function testDavPermissions($permissions, $type, $shared, $mounted, $expected) { $info = $this->getMockBuilder('\OC\Files\FileInfo') ->disableOriginalConstructor() ->setMethods(array('getPermissions', 'isShared', 'isMounted', 'getType')) ->getMock(); $info->expects($this->any()) ->method('getPermissions') ->will($this->returnValue($permissions)); $info->expects($this->any()) ->method('isShared') ->will($this->returnValue($shared)); $info->expects($this->any()) ->method('isMounted') ->will($this->returnValue($mounted)); $info->expects($this->any()) ->method('getType') ->will($this->returnValue($type)); $view = $this->getMock('\OC\Files\View'); $node = new \OC\Connector\Sabre\File($view, $info); $this->assertEquals($expected, $node->getDavPermissions()); }
/** * Test whether locks are set before and after the operation */ public function testPutLocking() { $view = new \OC\Files\View('/' . $this->user . '/files/'); $path = 'test-locking.txt'; $info = new \OC\Files\FileInfo('/' . $this->user . '/files/' . $path, null, null, ['permissions' => \OCP\Constants::PERMISSION_ALL], null); $file = new \OC\Connector\Sabre\File($view, $info); $this->assertFalse($this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED), 'File unlocked before put'); $this->assertFalse($this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE), 'File unlocked before put'); $wasLockedPre = false; $wasLockedPost = false; $eventHandler = $this->getMockBuilder('\\stdclass')->setMethods(['writeCallback', 'postWriteCallback'])->getMock(); // both pre and post hooks might need access to the file, // so only shared lock is acceptable $eventHandler->expects($this->once())->method('writeCallback')->will($this->returnCallback(function () use($view, $path, &$wasLockedPre) { $wasLockedPre = $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED); $wasLockedPre = $wasLockedPre && !$this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE); })); $eventHandler->expects($this->once())->method('postWriteCallback')->will($this->returnCallback(function () use($view, $path, &$wasLockedPost) { $wasLockedPost = $this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED); $wasLockedPost = $wasLockedPost && !$this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE); })); \OCP\Util::connectHook(Filesystem::CLASSNAME, Filesystem::signal_write, $eventHandler, 'writeCallback'); \OCP\Util::connectHook(Filesystem::CLASSNAME, Filesystem::signal_post_write, $eventHandler, 'postWriteCallback'); $this->assertNotEmpty($file->put($this->getStream('test data'))); $this->assertTrue($wasLockedPre, 'File was locked during pre-hooks'); $this->assertTrue($wasLockedPost, 'File was locked during post-hooks'); $this->assertFalse($this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_SHARED), 'File unlocked after put'); $this->assertFalse($this->isFileLocked($view, $path, \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE), 'File unlocked after put'); }
/** * @expectedException \Sabre\DAV\Exception\Forbidden */ public function testDeleteThrowsWhenDeletionFailed() { // setup $view = $this->getMock('\\OC\\Files\\View', array()); // but fails $view->expects($this->once())->method('unlink')->will($this->returnValue(false)); $info = new \OC\Files\FileInfo('/test.txt', null, null, array('permissions' => \OCP\Constants::PERMISSION_ALL), null); $file = new \OC\Connector\Sabre\File($view, $info); // action $file->delete(); }
/** * @expectedException \Sabre\DAV\Exception\ServiceUnavailable */ public function testGetFopenFails() { $view = $this->getMock('\\OC\\Files\\View', ['fopen'], array()); $view->expects($this->atLeastOnce())->method('fopen')->will($this->returnValue(false)); $info = new \OC\Files\FileInfo('/test.txt', null, null, array('permissions' => \OCP\Constants::PERMISSION_ALL), null); $file = new \OC\Connector\Sabre\File($view, $info); $file->get(); }