Merge pull request #7504 from owncloud/webdav-injection
Proper injection of filesystem view into the webdav connector
This commit is contained in:
commit
5194f014c9
|
@ -28,11 +28,8 @@ $authBackend = new OC_Connector_Sabre_Auth();
|
|||
$lockBackend = new OC_Connector_Sabre_Locks();
|
||||
$requestBackend = new OC_Connector_Sabre_Request();
|
||||
|
||||
// Create ownCloud Dir
|
||||
$rootDir = new OC_Connector_Sabre_Directory('');
|
||||
$objectTree = new \OC\Connector\Sabre\ObjectTree($rootDir);
|
||||
|
||||
// Fire up server
|
||||
$objectTree = new \OC\Connector\Sabre\ObjectTree();
|
||||
$server = new OC_Connector_Sabre_Server($objectTree);
|
||||
$server->httpRequest = $requestBackend;
|
||||
$server->setBaseUri($baseuri);
|
||||
|
@ -43,10 +40,21 @@ $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, $defaults->getName())
|
|||
$server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
|
||||
$server->addPlugin(new Sabre_DAV_Browser_Plugin(false));
|
||||
$server->addPlugin(new OC_Connector_Sabre_FilesPlugin());
|
||||
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin());
|
||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
|
||||
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
|
||||
$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
|
||||
|
||||
// wait with registering these until auth is handled and the filesystem is setup
|
||||
$server->subscribeEvent('beforeMethod', function () use ($server, $objectTree) {
|
||||
$view = \OC\Files\Filesystem::getView();
|
||||
$rootInfo = $view->getFileInfo('');
|
||||
|
||||
// Create ownCloud Dir
|
||||
$rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
||||
$objectTree->init($rootDir, $view);
|
||||
|
||||
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view));
|
||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
||||
}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
||||
|
|
|
@ -510,7 +510,11 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
public static function loginHelper($user, $create = false, $password = false) {
|
||||
if ($create) {
|
||||
\OC_User::createUser($user, $user);
|
||||
try {
|
||||
\OC_User::createUser($user, $user);
|
||||
} catch(\Exception $e) { // catch username is already being used from previous aborted runs
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($password === false) {
|
||||
|
|
|
@ -33,6 +33,7 @@ use OCA\Encryption;
|
|||
|
||||
/**
|
||||
* Class Test_Encryption_Webdav
|
||||
*
|
||||
* @brief this class provide basic webdav tests for PUT,GET and DELETE
|
||||
*/
|
||||
class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
||||
|
@ -48,6 +49,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
public $dataShort;
|
||||
public $stateFilesTrashbin;
|
||||
|
||||
private static $storage;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
// reset backend
|
||||
\OC_User::clearBackends();
|
||||
|
@ -65,6 +68,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
// create test user
|
||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1, true);
|
||||
|
||||
self::$storage = new \OC\Files\Storage\Temporary(array());
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
|
@ -96,8 +101,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
// reset app files_trashbin
|
||||
if ($this->stateFilesTrashbin) {
|
||||
OC_App::enable('files_trashbin');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
OC_App::disable('files_trashbin');
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +157,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertTrue(Encryption\Crypt::isCatfileContent($encryptedContent));
|
||||
|
||||
// get decrypted file contents
|
||||
$decrypt = file_get_contents('crypt:///' . $this->userId . '/files'. $filename);
|
||||
$decrypt = file_get_contents('crypt:///' . $this->userId . '/files' . $filename);
|
||||
|
||||
// check if file content match with the written content
|
||||
$this->assertEquals($this->dataShort, $decrypt);
|
||||
|
@ -225,7 +229,12 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
$requestBackend = new OC_Connector_Sabre_Request();
|
||||
|
||||
// Create ownCloud Dir
|
||||
$publicDir = new OC_Connector_Sabre_Directory('');
|
||||
$root = '/' . $this->userId . '/files';
|
||||
\OC\Files\Filesystem::mount(self::$storage, array(), $root);
|
||||
$view = new \OC\Files\View($root);
|
||||
$publicDir = new OC_Connector_Sabre_Directory($view, $view->getFileInfo(''));
|
||||
$objectTree = new \OC\Connector\Sabre\ObjectTree();
|
||||
$objectTree->init($publicDir, $view);
|
||||
|
||||
// Fire up server
|
||||
$server = new Sabre_DAV_Server($publicDir);
|
||||
|
@ -236,8 +245,9 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, 'ownCloud'));
|
||||
$server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
|
||||
$server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload
|
||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
|
||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view));
|
||||
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
|
||||
$server->debugExceptions = true;
|
||||
|
||||
// And off we go!
|
||||
if ($body) {
|
||||
|
|
|
@ -22,11 +22,16 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
|||
private $server;
|
||||
|
||||
/**
|
||||
* is kept public to allow overwrite for unit testing
|
||||
*
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
public $fileView;
|
||||
private $fileView;
|
||||
|
||||
/**
|
||||
* @param \OC\Files\View $view
|
||||
*/
|
||||
public function __construct($view) {
|
||||
$this->fileView = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes the plugin.
|
||||
|
@ -55,7 +60,7 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
|||
|
||||
// we should only react on PUT which is used for upload
|
||||
// e.g. with LOCK this will not work, but LOCK uses createFile() as well
|
||||
if ($this->server->httpRequest->getMethod() !== 'PUT' ) {
|
||||
if ($this->server->httpRequest->getMethod() !== 'PUT') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -70,9 +75,9 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
|||
if (!$expected) {
|
||||
return;
|
||||
}
|
||||
$actual = $this->getFileView()->filesize($filePath);
|
||||
$actual = $this->fileView->filesize($filePath);
|
||||
if ($actual != $expected) {
|
||||
$this->getFileView()->unlink($filePath);
|
||||
$this->fileView->unlink($filePath);
|
||||
throw new Sabre_DAV_Exception_BadRequest('expected filesize ' . $expected . ' got ' . $actual);
|
||||
}
|
||||
|
||||
|
@ -81,8 +86,7 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
public function getLength() {
|
||||
$req = $this->server->httpRequest;
|
||||
$length = $req->getHeader('X-Expected-Entity-Length');
|
||||
if (!$length) {
|
||||
|
@ -91,17 +95,4 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
|||
|
||||
return $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OC\Files\View
|
||||
*/
|
||||
public function getFileView()
|
||||
{
|
||||
if (is_null($this->fileView)) {
|
||||
// initialize fileView
|
||||
$this->fileView = \OC\Files\Filesystem::getView();
|
||||
}
|
||||
|
||||
return $this->fileView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
* 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 succesful creation of the file, you may choose to return the ETag
|
||||
* 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
|
||||
|
@ -51,25 +51,27 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
public function createFile($name, $data = null) {
|
||||
|
||||
// for chunked upload also updating a existing file is a "createFile"
|
||||
// because we create all the chunks before reasamble them to the existing file.
|
||||
// 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 (!\OC\Files\Filesystem::isCreatable($this->path) &&
|
||||
!\OC\Files\Filesystem::isUpdatable($this->path . '/' . $info['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 (!\OC\Files\Filesystem::isCreatable($this->path)) {
|
||||
if (!$this->fileView->isCreatable($this->path)) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
$path = $this->path . '/' . $name;
|
||||
$node = new OC_Connector_Sabre_File($path);
|
||||
$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());
|
||||
$node = new OC_Connector_Sabre_File($this->fileView, $info);
|
||||
return $node->put($data);
|
||||
}
|
||||
|
||||
|
@ -81,13 +83,12 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
* @return void
|
||||
*/
|
||||
public function createDirectory($name) {
|
||||
|
||||
if (!\OC\Files\Filesystem::isCreatable($this->path)) {
|
||||
if (!$this->fileView->isCreatable($this->path)) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
$newPath = $this->path . '/' . $name;
|
||||
if(!\OC\Files\Filesystem::mkdir($newPath)) {
|
||||
if(!$this->fileView->mkdir($newPath)) {
|
||||
throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath);
|
||||
}
|
||||
|
||||
|
@ -97,15 +98,15 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
* Returns a specific child node, referenced by its name
|
||||
*
|
||||
* @param string $name
|
||||
* @param OC\Files\FileInfo $info
|
||||
* @throws Sabre_DAV_Exception_FileNotFound
|
||||
* @param \OCP\Files\FileInfo $info
|
||||
* @throws Sabre_DAV_Exception_NotFound
|
||||
* @return Sabre_DAV_INode
|
||||
*/
|
||||
public function getChild($name, $info = null) {
|
||||
|
||||
$path = $this->path . '/' . $name;
|
||||
if (is_null($info)) {
|
||||
$info = \OC\Files\Filesystem::getFileInfo($path);
|
||||
$info = $this->fileView->getFileInfo($path);
|
||||
}
|
||||
|
||||
if (!$info) {
|
||||
|
@ -113,12 +114,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
}
|
||||
|
||||
if ($info['mimetype'] == 'httpd/unix-directory') {
|
||||
$node = new OC_Connector_Sabre_Directory($path);
|
||||
$node = new OC_Connector_Sabre_Directory($this->fileView, $info);
|
||||
} else {
|
||||
$node = new OC_Connector_Sabre_File($path);
|
||||
$node = new OC_Connector_Sabre_File($this->fileView, $info);
|
||||
}
|
||||
|
||||
$node->setFileinfoCache($info);
|
||||
return $node;
|
||||
}
|
||||
|
||||
|
@ -129,7 +128,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
*/
|
||||
public function getChildren() {
|
||||
|
||||
$folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
|
||||
$folder_content = $this->fileView->getDirectoryContent($this->path);
|
||||
$paths = array();
|
||||
foreach($folder_content as $info) {
|
||||
$paths[] = $this->path.'/'.$info['name'];
|
||||
|
@ -160,7 +159,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
|
||||
$nodes = array();
|
||||
foreach($folder_content as $info) {
|
||||
$node = $this->getChild($info['name'], $info);
|
||||
$node = $this->getChild($info->getName(), $info);
|
||||
$node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
|
||||
$nodes[] = $node;
|
||||
}
|
||||
|
@ -176,7 +175,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
public function childExists($name) {
|
||||
|
||||
$path = $this->path . '/' . $name;
|
||||
return \OC\Files\Filesystem::file_exists($path);
|
||||
return $this->fileView->file_exists($path);
|
||||
|
||||
}
|
||||
|
||||
|
@ -188,11 +187,11 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
*/
|
||||
public function delete() {
|
||||
|
||||
if (!\OC\Files\Filesystem::isDeletable($this->path)) {
|
||||
if (!$this->info->isDeletable()) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
\OC\Files\Filesystem::rmdir($this->path);
|
||||
$this->fileView->rmdir($this->path);
|
||||
|
||||
}
|
||||
|
||||
|
@ -224,7 +223,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
|||
public function getProperties($properties) {
|
||||
$props = parent::getProperties($properties);
|
||||
if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
|
||||
$props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
|
||||
$props[self::GETETAG_PROPERTYNAME] = $this->info->getEtag();
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
|
|
|
@ -42,14 +42,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
*
|
||||
* @param resource $data
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @throws OC_Connector_Sabre_Exception_UnsupportedMediaType
|
||||
* @throws Sabre_DAV_Exception_BadRequest
|
||||
* @throws Sabre_DAV_Exception
|
||||
* @throws OC_Connector_Sabre_Exception_EntityTooLarge
|
||||
* @throws Sabre_DAV_Exception_ServiceUnavailable
|
||||
* @return string|null
|
||||
*/
|
||||
public function put($data) {
|
||||
|
||||
$fs = $this->getFS();
|
||||
|
||||
if ($fs->file_exists($this->path) &&
|
||||
!$fs->isUpdatable($this->path)) {
|
||||
if ($this->info && $this->fileView->file_exists($this->path) &&
|
||||
!$this->info->isUpdateable()) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
|
@ -72,10 +74,10 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
$partpath = $this->path . '.ocTransferId' . rand() . '.part';
|
||||
|
||||
try {
|
||||
$putOkay = $fs->file_put_contents($partpath, $data);
|
||||
$putOkay = $this->fileView->file_put_contents($partpath, $data);
|
||||
if ($putOkay === false) {
|
||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
|
||||
$fs->unlink($partpath);
|
||||
$this->fileView->unlink($partpath);
|
||||
// because we have no clue about the cause we can only throw back a 500/Internal Server Error
|
||||
throw new Sabre_DAV_Exception('Could not write file contents');
|
||||
}
|
||||
|
@ -98,29 +100,30 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
}
|
||||
|
||||
// rename to correct path
|
||||
$renameOkay = $fs->rename($partpath, $this->path);
|
||||
$fileExists = $fs->file_exists($this->path);
|
||||
$renameOkay = $this->fileView->rename($partpath, $this->path);
|
||||
$fileExists = $this->fileView->file_exists($this->path);
|
||||
if ($renameOkay === false || $fileExists === false) {
|
||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
|
||||
$fs->unlink($partpath);
|
||||
$this->fileView->unlink($partpath);
|
||||
throw new Sabre_DAV_Exception('Could not rename part file to final file');
|
||||
}
|
||||
|
||||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($fs->touch($this->path, $mtime)) {
|
||||
if($this->fileView->touch($this->path, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
}
|
||||
}
|
||||
$this->refreshInfo();
|
||||
|
||||
return $this->getETagPropertyForPath($this->path);
|
||||
return '"' . $this->info->getEtag() . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data
|
||||
*
|
||||
* @return string
|
||||
* @return string | resource
|
||||
*/
|
||||
public function get() {
|
||||
|
||||
|
@ -128,7 +131,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
if (\OC_Util::encryptedFiles()) {
|
||||
throw new \Sabre_DAV_Exception_ServiceUnavailable();
|
||||
} else {
|
||||
return \OC\Files\Filesystem::fopen($this->path, 'rb');
|
||||
return $this->fileView->fopen($this->path, 'rb');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,12 +143,10 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function delete() {
|
||||
$fs = $this->getFS();
|
||||
|
||||
if (!$fs->isDeletable($this->path)) {
|
||||
if (!$this->info->isDeletable()) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
$fs->unlink($this->path);
|
||||
$this->fileView->unlink($this->path);
|
||||
|
||||
// remove properties
|
||||
$this->removeProperties();
|
||||
|
@ -158,12 +159,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
* @return int
|
||||
*/
|
||||
public function getSize() {
|
||||
$this->getFileinfoCache();
|
||||
if ($this->fileinfo_cache['size'] > -1) {
|
||||
return $this->fileinfo_cache['size'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $this->info->getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,11 +174,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
* @return mixed
|
||||
*/
|
||||
public function getETag() {
|
||||
$properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
|
||||
if (isset($properties[self::GETETAG_PROPERTYNAME])) {
|
||||
return $properties[self::GETETAG_PROPERTYNAME];
|
||||
}
|
||||
return null;
|
||||
return '"' . $this->info->getEtag() . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,18 +185,14 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
* @return mixed
|
||||
*/
|
||||
public function getContentType() {
|
||||
if (isset($this->fileinfo_cache['mimetype'])) {
|
||||
$mimeType = $this->fileinfo_cache['mimetype'];
|
||||
} else {
|
||||
$mimeType = \OC\Files\Filesystem::getMimeType($this->path);
|
||||
}
|
||||
$mimeType = $this->info->getMimetype();
|
||||
|
||||
return \OC_Helper::getSecureMimeType($mimeType);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $data
|
||||
* @return null|string
|
||||
*/
|
||||
private function createFileChunked($data)
|
||||
{
|
||||
|
@ -236,15 +224,14 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
$chunk_handler->file_assemble($partFile);
|
||||
|
||||
// here is the final atomic rename
|
||||
$fs = $this->getFS();
|
||||
$targetPath = $path . '/' . $info['name'];
|
||||
$renameOkay = $fs->rename($partFile, $targetPath);
|
||||
$fileExists = $fs->file_exists($targetPath);
|
||||
$renameOkay = $this->fileView->rename($partFile, $targetPath);
|
||||
$fileExists = $this->fileView->file_exists($targetPath);
|
||||
if ($renameOkay === false || $fileExists === false) {
|
||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
|
||||
// only delete if an error occurred and the target file was already created
|
||||
if ($fileExists) {
|
||||
$fs->unlink($targetPath);
|
||||
$this->fileView->unlink($targetPath);
|
||||
}
|
||||
throw new Sabre_DAV_Exception('Could not rename part file assembled from chunks');
|
||||
}
|
||||
|
@ -252,12 +239,13 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
|||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($fs->touch($targetPath, $mtime)) {
|
||||
if($this->fileView->touch($targetPath, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
}
|
||||
}
|
||||
|
||||
return OC_Connector_Sabre_Node::getETagPropertyForPath($targetPath);
|
||||
$info = $this->fileView->getFileInfo($targetPath);
|
||||
return $info->getEtag();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties {
|
||||
const GETETAG_PROPERTYNAME = '{DAV:}getetag';
|
||||
const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
|
||||
|
@ -29,15 +28,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
* Allow configuring the method used to generate Etags
|
||||
*
|
||||
* @var array(class_name, function_name)
|
||||
*/
|
||||
*/
|
||||
public static $ETagFunction = null;
|
||||
|
||||
/**
|
||||
* is kept public to allow overwrite for unit testing
|
||||
*
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
public $fileView;
|
||||
protected $fileView;
|
||||
|
||||
/**
|
||||
* The path to the current node
|
||||
|
@ -46,53 +43,55 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* node fileinfo cache
|
||||
* @var array
|
||||
*/
|
||||
protected $fileinfo_cache;
|
||||
/**
|
||||
* node properties cache
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $property_cache = null;
|
||||
|
||||
/**
|
||||
* @brief Sets up the node, expects a full path name
|
||||
* @param string $path
|
||||
* @return void
|
||||
* @var \OCP\Files\FileInfo
|
||||
*/
|
||||
public function __construct($path) {
|
||||
$this->path = $path;
|
||||
protected $info;
|
||||
|
||||
/**
|
||||
* @brief Sets up the node, expects a full path name
|
||||
* @param \OC\Files\View $view
|
||||
* @param \OCP\Files\FileInfo $info
|
||||
*/
|
||||
public function __construct($view, $info) {
|
||||
$this->fileView = $view;
|
||||
$this->path = $this->fileView->getRelativePath($info->getPath());
|
||||
$this->info = $info;
|
||||
}
|
||||
|
||||
|
||||
protected function refreshInfo() {
|
||||
$this->info = $this->fileView->getFileInfo($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the name of the node
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
list(, $name) = Sabre_DAV_URLUtil::splitPath($this->path);
|
||||
return $name;
|
||||
|
||||
return $this->info->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renames the node
|
||||
* @param string $name The new name
|
||||
* @return void
|
||||
* @throws Sabre_DAV_Exception_BadRequest
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function setName($name) {
|
||||
$fs = $this->getFS();
|
||||
|
||||
// rename is only allowed if the update privilege is granted
|
||||
if (!$fs->isUpdatable($this->path)) {
|
||||
if (!$this->info->isUpdateable()) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
|
||||
list($parentPath,) = Sabre_DAV_URLUtil::splitPath($this->path);
|
||||
list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
|
||||
|
||||
if (!\OCP\Util::isValidFileName($newName)) {
|
||||
|
@ -102,38 +101,17 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
$newPath = $parentPath . '/' . $newName;
|
||||
$oldPath = $this->path;
|
||||
|
||||
$fs->rename($this->path, $newPath);
|
||||
$this->fileView->rename($this->path, $newPath);
|
||||
|
||||
$this->path = $newPath;
|
||||
|
||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
||||
$query->execute( array( $newPath, OC_User::getUser(), $oldPath ));
|
||||
|
||||
$query = OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||
$query->execute(array($newPath, OC_User::getUser(), $oldPath));
|
||||
$this->refreshInfo();
|
||||
}
|
||||
|
||||
public function setFileinfoCache($fileinfo_cache)
|
||||
{
|
||||
$this->fileinfo_cache = $fileinfo_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ensure that the fileinfo cache is filled
|
||||
* @note Uses OC_FileCache or a direct stat
|
||||
*/
|
||||
protected function getFileinfoCache() {
|
||||
if (!isset($this->fileinfo_cache)) {
|
||||
if ($fileinfo_cache = \OC\Files\Filesystem::getFileInfo($this->path)) {
|
||||
} else {
|
||||
$fileinfo_cache = \OC\Files\Filesystem::stat($this->path);
|
||||
}
|
||||
|
||||
$this->fileinfo_cache = $fileinfo_cache;
|
||||
}
|
||||
}
|
||||
|
||||
public function setPropertyCache($property_cache)
|
||||
{
|
||||
public function setPropertyCache($property_cache) {
|
||||
$this->property_cache = $property_cache;
|
||||
}
|
||||
|
||||
|
@ -142,8 +120,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
* @return int timestamp as integer
|
||||
*/
|
||||
public function getLastModified() {
|
||||
$this->getFileinfoCache();
|
||||
$timestamp = $this->fileinfo_cache['mtime'];
|
||||
$timestamp = $this->info->getMtime();
|
||||
if (!empty($timestamp)) {
|
||||
return (int)$timestamp;
|
||||
}
|
||||
|
@ -156,39 +133,40 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
* Even if the modification time is set to a custom value the access time is set to now.
|
||||
*/
|
||||
public function touch($mtime) {
|
||||
\OC\Files\Filesystem::touch($this->path, $mtime);
|
||||
$this->fileView->touch($this->path, $mtime);
|
||||
$this->refreshInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates properties on this node,
|
||||
* @see Sabre_DAV_IProperties::updateProperties
|
||||
* @param array $properties
|
||||
* @return boolean
|
||||
*/
|
||||
public function updateProperties($properties) {
|
||||
$existing = $this->getProperties(array());
|
||||
foreach($properties as $propertyName => $propertyValue) {
|
||||
foreach ($properties as $propertyName => $propertyValue) {
|
||||
// If it was null, we need to delete the property
|
||||
if (is_null($propertyValue)) {
|
||||
if(array_key_exists( $propertyName, $existing )) {
|
||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
|
||||
.' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName ));
|
||||
if (array_key_exists($propertyName, $existing)) {
|
||||
$query = OC_DB::prepare('DELETE FROM `*PREFIX*properties`'
|
||||
. ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?');
|
||||
$query->execute(array(OC_User::getUser(), $this->path, $propertyName));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( strcmp( $propertyName, self::GETETAG_PROPERTYNAME) === 0 ) {
|
||||
\OC\Files\Filesystem::putFileInfo($this->path, array('etag'=> $propertyValue));
|
||||
} elseif( strcmp( $propertyName, self::LASTMODIFIED_PROPERTYNAME) === 0 ) {
|
||||
} else {
|
||||
if (strcmp($propertyName, self::GETETAG_PROPERTYNAME) === 0) {
|
||||
\OC\Files\Filesystem::putFileInfo($this->path, array('etag' => $propertyValue));
|
||||
} elseif (strcmp($propertyName, self::LASTMODIFIED_PROPERTYNAME) === 0) {
|
||||
$this->touch($propertyValue);
|
||||
} else {
|
||||
if(!array_key_exists( $propertyName, $existing )) {
|
||||
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties`'
|
||||
.' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
|
||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue ));
|
||||
if (!array_key_exists($propertyName, $existing)) {
|
||||
$query = OC_DB::prepare('INSERT INTO `*PREFIX*properties`'
|
||||
. ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)');
|
||||
$query->execute(array(OC_User::getUser(), $this->path, $propertyName, $propertyValue));
|
||||
} else {
|
||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'
|
||||
.' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
||||
$query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName ));
|
||||
$query = OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'
|
||||
. ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?');
|
||||
$query->execute(array($propertyValue, OC_User::getUser(), $this->path, $propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,9 +180,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
* removes all properties for this node and user
|
||||
*/
|
||||
public function removeProperties() {
|
||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
|
||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
||||
$query->execute( array( OC_User::getUser(), $this->path));
|
||||
$query = OC_DB::prepare('DELETE FROM `*PREFIX*properties`'
|
||||
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||
$query->execute(array(OC_User::getUser(), $this->path));
|
||||
|
||||
$this->setPropertyCache(null);
|
||||
}
|
||||
|
@ -222,29 +200,23 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
|
||||
if (is_null($this->property_cache)) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
|
||||
$result = OC_DB::executeAudited( $sql, array( OC_User::getUser(), $this->path ) );
|
||||
$result = OC_DB::executeAudited($sql, array(OC_User::getUser(), $this->path));
|
||||
|
||||
$this->property_cache = array();
|
||||
while( $row = $result->fetchRow()) {
|
||||
while ($row = $result->fetchRow()) {
|
||||
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
|
||||
}
|
||||
|
||||
// Don't call the static getETagPropertyForPath, its result is not cached
|
||||
$this->getFileinfoCache();
|
||||
if ($this->fileinfo_cache['etag']) {
|
||||
$this->property_cache[self::GETETAG_PROPERTYNAME] = '"'.$this->fileinfo_cache['etag'].'"';
|
||||
} else {
|
||||
$this->property_cache[self::GETETAG_PROPERTYNAME] = null;
|
||||
}
|
||||
$this->property_cache[self::GETETAG_PROPERTYNAME] = '"' . $this->info->getEtag() . '"';
|
||||
}
|
||||
|
||||
// if the array was empty, we need to return everything
|
||||
if(count($properties) == 0) {
|
||||
if (count($properties) == 0) {
|
||||
return $this->property_cache;
|
||||
}
|
||||
|
||||
$props = array();
|
||||
foreach($properties as $property) {
|
||||
foreach ($properties as $property) {
|
||||
if (isset($this->property_cache[$property])) {
|
||||
$props[$property] = $this->property_cache[$property];
|
||||
}
|
||||
|
@ -253,36 +225,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
|||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ETag surrounded by double-quotes for this path.
|
||||
* @param string $path Path of the file
|
||||
* @return string|null Returns null if the ETag can not effectively be determined
|
||||
*/
|
||||
protected function getETagPropertyForPath($path) {
|
||||
$data = $this->getFS()->getFileInfo($path);
|
||||
if (isset($data['etag'])) {
|
||||
return '"'.$data['etag'].'"';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getFS() {
|
||||
if (is_null($this->fileView)) {
|
||||
$this->fileView = \OC\Files\Filesystem::getView();
|
||||
}
|
||||
return $this->fileView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFileId()
|
||||
{
|
||||
$this->getFileinfoCache();
|
||||
|
||||
if (isset($this->fileinfo_cache['fileid'])) {
|
||||
public function getFileId() {
|
||||
if ($this->info->getId()) {
|
||||
$instanceId = OC_Util::getInstanceId();
|
||||
$id = sprintf('%08d', $this->fileinfo_cache['fileid']);
|
||||
$id = sprintf('%08d', $this->info->getId());
|
||||
return $id . $instanceId;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,25 +8,45 @@
|
|||
|
||||
namespace OC\Connector\Sabre;
|
||||
|
||||
use OC\Files\FileInfo;
|
||||
use OC\Files\Filesystem;
|
||||
|
||||
class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||
|
||||
/**
|
||||
* keep this public to allow mock injection during unit test
|
||||
*
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
public $fileView;
|
||||
protected $fileView;
|
||||
|
||||
/**
|
||||
* Creates the object
|
||||
*
|
||||
* This method expects the rootObject to be passed as a parameter
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Sabre_DAV_ICollection $rootNode
|
||||
* @param \OC\Files\View $view
|
||||
*/
|
||||
public function init(\Sabre_DAV_ICollection $rootNode, \OC\Files\View $view) {
|
||||
$this->rootNode = $rootNode;
|
||||
$this->fileView = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the INode object for the requested path
|
||||
*
|
||||
* @param string $path
|
||||
* @throws \Sabre_DAV_Exception_ServiceUnavailable
|
||||
* @throws \Sabre_DAV_Exception_NotFound
|
||||
* @return \Sabre_DAV_INode
|
||||
*/
|
||||
public function getNodeForPath($path) {
|
||||
if (!$this->fileView) {
|
||||
throw new \Sabre_DAV_Exception_ServiceUnavailable('filesystem not setup');
|
||||
}
|
||||
|
||||
$path = trim($path, '/');
|
||||
if (isset($this->cache[$path])) {
|
||||
|
@ -40,31 +60,34 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
|
||||
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
|
||||
// read from storage
|
||||
$absPath = $this->getFileView()->getAbsolutePath($path);
|
||||
$absPath = $this->fileView->getAbsolutePath($path);
|
||||
list($storage, $internalPath) = Filesystem::resolvePath('/' . $absPath);
|
||||
if ($storage) {
|
||||
/**
|
||||
* @var \OC\Files\Storage\Storage $storage
|
||||
*/
|
||||
$scanner = $storage->getScanner($internalPath);
|
||||
// get data directly
|
||||
$info = $scanner->getData($internalPath);
|
||||
$data = $scanner->getData($internalPath);
|
||||
$info = new FileInfo($absPath, $storage, $internalPath, $data);
|
||||
} else {
|
||||
$info = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// read from cache
|
||||
$info = $this->getFileView()->getFileInfo($path);
|
||||
$info = $this->fileView->getFileInfo($path);
|
||||
}
|
||||
|
||||
if (!$info) {
|
||||
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
|
||||
}
|
||||
|
||||
if ($info['mimetype'] === 'httpd/unix-directory') {
|
||||
$node = new \OC_Connector_Sabre_Directory($path);
|
||||
if ($info->getType() === 'dir') {
|
||||
$node = new \OC_Connector_Sabre_Directory($this->fileView, $info);
|
||||
} else {
|
||||
$node = new \OC_Connector_Sabre_File($path);
|
||||
$node = new \OC_Connector_Sabre_File($this->fileView, $info);
|
||||
}
|
||||
|
||||
$node->setFileinfoCache($info);
|
||||
|
||||
$this->cache[$path] = $node;
|
||||
return $node;
|
||||
|
||||
|
@ -75,10 +98,15 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
*
|
||||
* @param string $sourcePath The path to the file which should be moved
|
||||
* @param string $destinationPath The full destination path, so not just the destination parent node
|
||||
* @throws \Sabre_DAV_Exception_BadRequest
|
||||
* @throws \Sabre_DAV_Exception_ServiceUnavailable
|
||||
* @throws \Sabre_DAV_Exception_Forbidden
|
||||
* @return int
|
||||
*/
|
||||
public function move($sourcePath, $destinationPath) {
|
||||
if (!$this->fileView) {
|
||||
throw new \Sabre_DAV_Exception_ServiceUnavailable('filesystem not setup');
|
||||
}
|
||||
|
||||
$sourceNode = $this->getNodeForPath($sourcePath);
|
||||
if ($sourceNode instanceof \Sabre_DAV_ICollection and $this->nodeExists($destinationPath)) {
|
||||
|
@ -94,19 +122,21 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
}
|
||||
|
||||
// check update privileges
|
||||
$fs = $this->getFileView();
|
||||
if (!$fs->isUpdatable($sourcePath) && !$isShareMountPoint) {
|
||||
if (!$this->fileView->isUpdatable($sourcePath) && !$isShareMountPoint) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
if ($sourceDir !== $destinationDir) {
|
||||
// for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
|
||||
if (!$fs->isUpdatable($sourceDir)) {
|
||||
if (ltrim($destinationDir, '/') === '') {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
if (!$fs->isUpdatable($destinationDir)) {
|
||||
if (!$this->fileView->isUpdatable($sourceDir)) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
if (!$fs->isDeletable($sourcePath)) {
|
||||
if (!$this->fileView->isUpdatable($destinationDir)) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
if (!$this->fileView->isDeletable($sourcePath)) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
}
|
||||
|
@ -116,15 +146,15 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
throw new \Sabre_DAV_Exception_BadRequest();
|
||||
}
|
||||
|
||||
$renameOkay = $fs->rename($sourcePath, $destinationPath);
|
||||
$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
|
||||
if (!$renameOkay) {
|
||||
throw new \Sabre_DAV_Exception_Forbidden('');
|
||||
}
|
||||
|
||||
// update properties
|
||||
$query = \OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
||||
$query->execute( array( $destinationPath, \OC_User::getUser(), $sourcePath ));
|
||||
$query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||
$query->execute(array(\OC\Files\Filesystem::normalizePath($destinationPath), \OC_User::getUser(), \OC\Files\Filesystem::normalizePath($sourcePath)));
|
||||
|
||||
$this->markDirty($sourceDir);
|
||||
$this->markDirty($destinationDir);
|
||||
|
@ -139,20 +169,24 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
*
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @throws \Sabre_DAV_Exception_ServiceUnavailable
|
||||
* @return void
|
||||
*/
|
||||
public function copy($source, $destination) {
|
||||
if (!$this->fileView) {
|
||||
throw new \Sabre_DAV_Exception_ServiceUnavailable('filesystem not setup');
|
||||
}
|
||||
|
||||
if (Filesystem::is_file($source)) {
|
||||
Filesystem::copy($source, $destination);
|
||||
if ($this->fileView->is_file($source)) {
|
||||
$this->fileView->copy($source, $destination);
|
||||
} else {
|
||||
Filesystem::mkdir($destination);
|
||||
$dh = Filesystem::opendir($source);
|
||||
if(is_resource($dh)) {
|
||||
while (($subnode = readdir($dh)) !== false) {
|
||||
$this->fileView->mkdir($destination);
|
||||
$dh = $this->fileView->opendir($source);
|
||||
if (is_resource($dh)) {
|
||||
while (($subNode = readdir($dh)) !== false) {
|
||||
|
||||
if ($subnode == '.' || $subnode == '..') continue;
|
||||
$this->copy($source . '/' . $subnode, $destination . '/' . $subnode);
|
||||
if ($subNode == '.' || $subNode == '..') continue;
|
||||
$this->copy($source . '/' . $subNode, $destination . '/' . $subNode);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -161,14 +195,4 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
|||
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
|
||||
$this->markDirty($destinationDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OC\Files\View
|
||||
*/
|
||||
public function getFileView() {
|
||||
if (is_null($this->fileView)) {
|
||||
$this->fileView = \OC\Files\Filesystem::getView();
|
||||
}
|
||||
return $this->fileView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
*/
|
||||
class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||
|
||||
/**
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* Reference to main server object
|
||||
*
|
||||
|
@ -17,11 +22,11 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
|||
private $server;
|
||||
|
||||
/**
|
||||
* is kept public to allow overwrite for unit testing
|
||||
*
|
||||
* @var \OC\Files\View
|
||||
* @param \OC\Files\View $view
|
||||
*/
|
||||
public $fileView;
|
||||
public function __construct($view) {
|
||||
$this->view = $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes the plugin.
|
||||
|
@ -45,22 +50,23 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
|||
/**
|
||||
* This method is called before any HTTP method and validates there is enough free space to store the file
|
||||
*
|
||||
* @throws Sabre_DAV_Exception
|
||||
* @param string $uri
|
||||
* @param null $data
|
||||
* @throws Sabre_DAV_Exception_InsufficientStorage
|
||||
* @return bool
|
||||
*/
|
||||
public function checkQuota($uri, $data = null) {
|
||||
$length = $this->getLength();
|
||||
if ($length) {
|
||||
if (substr($uri, 0, 1)!=='/') {
|
||||
$uri='/'.$uri;
|
||||
if (substr($uri, 0, 1) !== '/') {
|
||||
$uri = '/' . $uri;
|
||||
}
|
||||
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
|
||||
$req = $this->server->httpRequest;
|
||||
if ($req->getHeader('OC-Chunked')) {
|
||||
$info = OC_FileChunking::decodeName($newName);
|
||||
$chunkHandler = new OC_FileChunking($info);
|
||||
// substract the already uploaded size to see whether
|
||||
// subtract the already uploaded size to see whether
|
||||
// there is still enough space for the remaining chunks
|
||||
$length -= $chunkHandler->getCurrentSize();
|
||||
}
|
||||
|
@ -75,8 +81,7 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
|||
return true;
|
||||
}
|
||||
|
||||
public function getLength()
|
||||
{
|
||||
public function getLength() {
|
||||
$req = $this->server->httpRequest;
|
||||
$length = $req->getHeader('X-Expected-Entity-Length');
|
||||
if (!$length) {
|
||||
|
@ -95,14 +100,8 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
|||
* @param $parentUri
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFreeSpace($parentUri)
|
||||
{
|
||||
if (is_null($this->fileView)) {
|
||||
// initialize fileView
|
||||
$this->fileView = \OC\Files\Filesystem::getView();
|
||||
}
|
||||
|
||||
$freeSpace = $this->fileView->free_space($parentUri);
|
||||
public function getFreeSpace($parentUri) {
|
||||
$freeSpace = $this->view->free_space($parentUri);
|
||||
return $freeSpace;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,11 +115,12 @@ class Scanner extends BasicEmitter {
|
|||
}
|
||||
if ($reuseExisting) {
|
||||
// prevent empty etag
|
||||
$etag = $cacheData['etag'];
|
||||
$propagateETagChange = false;
|
||||
if (empty($etag)) {
|
||||
if (empty($cacheData['etag'])) {
|
||||
$etag = $data['etag'];
|
||||
$propagateETagChange = true;
|
||||
} else {
|
||||
$etag = $cacheData['etag'];
|
||||
$propagateETagChange = false;
|
||||
}
|
||||
// only reuse data if the file hasn't explicitly changed
|
||||
if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class Test_OC_Connector_Sabre_AbortedUploadDetectionPlugin extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
|
@ -18,17 +18,18 @@ class Test_OC_Connector_Sabre_AbortedUploadDetectionPlugin extends PHPUnit_Frame
|
|||
*/
|
||||
private $plugin;
|
||||
|
||||
public function setUp() {
|
||||
private function init($view) {
|
||||
$this->server = new Sabre_DAV_Server();
|
||||
$this->plugin = new OC_Connector_Sabre_AbortedUploadDetectionPlugin();
|
||||
$this->plugin = new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view);
|
||||
$this->plugin->initialize($this->server);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider lengthProvider
|
||||
*/
|
||||
public function testLength($expected, $headers)
|
||||
{
|
||||
public function testLength($expected, $headers) {
|
||||
$this->init(null);
|
||||
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
$length = $this->plugin->getLength();
|
||||
$this->assertEquals($expected, $length);
|
||||
|
@ -37,9 +38,8 @@ class Test_OC_Connector_Sabre_AbortedUploadDetectionPlugin extends PHPUnit_Frame
|
|||
/**
|
||||
* @dataProvider verifyContentLengthProvider
|
||||
*/
|
||||
public function testVerifyContentLength($method, $fileSize, $headers)
|
||||
{
|
||||
$this->plugin->fileView = $this->buildFileViewMock($fileSize);
|
||||
public function testVerifyContentLength($method, $fileSize, $headers) {
|
||||
$this->init($this->buildFileViewMock($fileSize));
|
||||
|
||||
$headers['REQUEST_METHOD'] = $method;
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
|
@ -51,12 +51,11 @@ class Test_OC_Connector_Sabre_AbortedUploadDetectionPlugin extends PHPUnit_Frame
|
|||
* @dataProvider verifyContentLengthFailedProvider
|
||||
* @expectedException Sabre_DAV_Exception_BadRequest
|
||||
*/
|
||||
public function testVerifyContentLengthFailed($method, $fileSize, $headers)
|
||||
{
|
||||
$this->plugin->fileView = $this->buildFileViewMock($fileSize);
|
||||
|
||||
public function testVerifyContentLengthFailed($method, $fileSize, $headers) {
|
||||
$view = $this->buildFileViewMock($fileSize);
|
||||
$this->init($view);
|
||||
// we expect unlink to be called
|
||||
$this->plugin->fileView->expects($this->once())->method('unlink');
|
||||
$view->expects($this->once())->method('unlink');
|
||||
|
||||
$headers['REQUEST_METHOD'] = $method;
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
|
@ -92,7 +91,7 @@ class Test_OC_Connector_Sabre_AbortedUploadDetectionPlugin extends PHPUnit_Frame
|
|||
|
||||
private function buildFileViewMock($fileSize) {
|
||||
// mock filesystem
|
||||
$view = $this->getMock('\OC\Files\View', array('filesize', 'unlink'), array(), '', FALSE);
|
||||
$view = $this->getMock('\OC\Files\View', array('filesize', 'unlink'), array(), '', false);
|
||||
$view->expects($this->any())->method('filesize')->withAnyParameters()->will($this->returnValue($fileSize));
|
||||
|
||||
return $view;
|
||||
|
|
|
@ -1,18 +1,32 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class Test_OC_Connector_Sabre_Directory extends PHPUnit_Framework_TestCase {
|
||||
|
||||
private function getRootDir() {
|
||||
$view = $this->getMock('OC\Files\View', array(), array(), '', false);
|
||||
$view->expects($this->once())
|
||||
->method('getRelativePath')
|
||||
->will($this->returnValue(''));
|
||||
|
||||
$info = $this->getMock('OC\Files\FileInfo', array(), array(), '', false);
|
||||
$info->expects($this->once())
|
||||
->method('getPath')
|
||||
->will($this->returnValue(''));
|
||||
|
||||
return new OC_Connector_Sabre_Directory($view, $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function testCreateSharedFileFails() {
|
||||
$dir = new OC_Connector_Sabre_Directory('');
|
||||
$dir = $this->getRootDir();
|
||||
$dir->createFile('Shared');
|
||||
}
|
||||
|
||||
|
@ -20,7 +34,7 @@ class Test_OC_Connector_Sabre_Directory extends PHPUnit_Framework_TestCase {
|
|||
* @expectedException Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function testCreateSharedFolderFails() {
|
||||
$dir = new OC_Connector_Sabre_Directory('');
|
||||
$dir = $this->getRootDir();
|
||||
$dir->createDirectory('Shared');
|
||||
}
|
||||
|
||||
|
@ -28,7 +42,7 @@ class Test_OC_Connector_Sabre_Directory extends PHPUnit_Framework_TestCase {
|
|||
* @expectedException Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function testDeleteSharedFolderFails() {
|
||||
$dir = new OC_Connector_Sabre_Directory('Shared');
|
||||
$dir = $this->getRootDir();
|
||||
$dir->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,20 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
public function testSimplePutFails() {
|
||||
// setup
|
||||
$file = new OC_Connector_Sabre_File('/test.txt');
|
||||
$file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents'), array(), '', FALSE);
|
||||
$file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(false));
|
||||
$view = $this->getMock('\OC\Files\View', array('file_put_contents', 'getRelativePath'), array(), '', false);
|
||||
$view->expects($this->any())
|
||||
->method('file_put_contents')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$view->expects($this->any())
|
||||
->method('getRelativePath')
|
||||
->will($this->returnValue('/test.txt'));
|
||||
|
||||
$info = new \OC\Files\FileInfo('/test.txt', null, null, array(
|
||||
'permissions'=>\OCP\PERMISSION_ALL
|
||||
));
|
||||
|
||||
$file = new OC_Connector_Sabre_File($view, $info);
|
||||
|
||||
// action
|
||||
$etag = $file->put('test data');
|
||||
|
@ -26,10 +37,25 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
public function testSimplePutFailsOnRename() {
|
||||
// setup
|
||||
$file = new OC_Connector_Sabre_File('/test.txt');
|
||||
$file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents', 'rename'), array(), '', FALSE);
|
||||
$file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(true));
|
||||
$file->fileView->expects($this->any())->method('rename')->withAnyParameters()->will($this->returnValue(false));
|
||||
$view = $this->getMock('\OC\Files\View', array('file_put_contents', 'rename', 'getRelativePath'), array(), '', false);
|
||||
$view->expects($this->any())
|
||||
->method('file_put_contents')
|
||||
->withAnyParameters()
|
||||
->will($this->returnValue(true));
|
||||
$view->expects($this->any())
|
||||
->method('rename')
|
||||
->withAnyParameters()
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$view->expects($this->any())
|
||||
->method('getRelativePath')
|
||||
->will($this->returnValue('/test.txt'));
|
||||
|
||||
$info = new \OC\Files\FileInfo('/test.txt', null, null, array(
|
||||
'permissions' => \OCP\PERMISSION_ALL
|
||||
));
|
||||
|
||||
$file = new OC_Connector_Sabre_File($view, $info);
|
||||
|
||||
// action
|
||||
$etag = $file->put('test data');
|
||||
|
@ -40,9 +66,19 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
public function testSimplePutInvalidChars() {
|
||||
// setup
|
||||
$file = new OC_Connector_Sabre_File('/super*star.txt');
|
||||
$file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents'), array(), '', FALSE);
|
||||
$file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(false));
|
||||
$view = $this->getMock('\OC\Files\View', array('file_put_contents', 'getRelativePath'), array(), '', false);
|
||||
$view->expects($this->any())
|
||||
->method('file_put_contents')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$view->expects($this->any())
|
||||
->method('getRelativePath')
|
||||
->will($this->returnValue('/super*star.txt'));
|
||||
|
||||
$info = new \OC\Files\FileInfo('/super*star.txt', null, null, array(
|
||||
'permissions' => \OCP\PERMISSION_ALL
|
||||
));
|
||||
$file = new OC_Connector_Sabre_File($view, $info);
|
||||
|
||||
// action
|
||||
$etag = $file->put('test data');
|
||||
|
@ -54,17 +90,16 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
public function testSetNameInvalidChars() {
|
||||
// setup
|
||||
$file = new OC_Connector_Sabre_File('/test.txt');
|
||||
$file->fileView = $this->getMock('\OC\Files\View', array('isUpdatable'), array(), '', FALSE);
|
||||
$file->fileView->expects($this->any())->method('isUpdatable')->withAnyParameters()->will($this->returnValue(true));
|
||||
$view = $this->getMock('\OC\Files\View', array('getRelativePath'), array(), '', false);
|
||||
|
||||
$view->expects($this->any())
|
||||
->method('getRelativePath')
|
||||
->will($this->returnValue('/super*star.txt'));
|
||||
|
||||
$info = new \OC\Files\FileInfo('/super*star.txt', null, null, array(
|
||||
'permissions' => \OCP\PERMISSION_ALL
|
||||
));
|
||||
$file = new OC_Connector_Sabre_File($view, $info);
|
||||
$file->setName('/super*star.txt');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabre_DAV_Exception_Forbidden
|
||||
*/
|
||||
public function testDeleteSharedFails() {
|
||||
$file = new OC_Connector_Sabre_File('Shared');
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace Test\OC\Connector\Sabre;
|
||||
|
||||
|
||||
use OC\Files\FileInfo;
|
||||
use OC_Connector_Sabre_Directory;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
use Sabre_DAV_Exception_Forbidden;
|
||||
|
@ -32,6 +33,10 @@ class TestDoubleFileView extends \OC\Files\View{
|
|||
public function rename($path1, $path2) {
|
||||
return $this->canRename;
|
||||
}
|
||||
|
||||
public function getRelativePath($path){
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectTree extends PHPUnit_Framework_TestCase {
|
||||
|
@ -91,10 +96,14 @@ class ObjectTree extends PHPUnit_Framework_TestCase {
|
|||
* @param $updatables
|
||||
*/
|
||||
private function moveTest($source, $dest, $updatables, $deletables) {
|
||||
$rootDir = new OC_Connector_Sabre_Directory('');
|
||||
$view = new TestDoubleFileView($updatables, $deletables);
|
||||
|
||||
$info = new FileInfo('', null, null, array());
|
||||
|
||||
$rootDir = new OC_Connector_Sabre_Directory($view, $info);
|
||||
$objectTree = $this->getMock('\OC\Connector\Sabre\ObjectTree',
|
||||
array('nodeExists', 'getNodeForPath'),
|
||||
array($rootDir));
|
||||
array($rootDir, $view));
|
||||
|
||||
$objectTree->expects($this->once())
|
||||
->method('getNodeForPath')
|
||||
|
@ -102,7 +111,7 @@ class ObjectTree extends PHPUnit_Framework_TestCase {
|
|||
->will($this->returnValue(false));
|
||||
|
||||
/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
|
||||
$objectTree->fileView = new TestDoubleFileView($updatables, $deletables);
|
||||
$objectTree->init($rootDir, $view);
|
||||
$objectTree->move($source, $dest);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
class Test_OC_Connector_Sabre_QuotaPlugin extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
|
@ -18,17 +18,18 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
private $plugin;
|
||||
|
||||
public function setUp() {
|
||||
private function init($quota) {
|
||||
$view = $this->buildFileViewMock($quota);
|
||||
$this->server = new Sabre_DAV_Server();
|
||||
$this->plugin = new OC_Connector_Sabre_QuotaPlugin();
|
||||
$this->plugin = new OC_Connector_Sabre_QuotaPlugin($view);
|
||||
$this->plugin->initialize($this->server);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider lengthProvider
|
||||
*/
|
||||
public function testLength($expected, $headers)
|
||||
{
|
||||
public function testLength($expected, $headers) {
|
||||
$this->init(0);
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
$length = $this->plugin->getLength();
|
||||
$this->assertEquals($expected, $length);
|
||||
|
@ -37,9 +38,8 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends PHPUnit_Framework_TestCase {
|
|||
/**
|
||||
* @dataProvider quotaOkayProvider
|
||||
*/
|
||||
public function testCheckQuota($quota, $headers)
|
||||
{
|
||||
$this->plugin->fileView = $this->buildFileViewMock($quota);
|
||||
public function testCheckQuota($quota, $headers) {
|
||||
$this->init($quota);
|
||||
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
$result = $this->plugin->checkQuota('');
|
||||
|
@ -50,9 +50,8 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends PHPUnit_Framework_TestCase {
|
|||
* @expectedException Sabre_DAV_Exception_InsufficientStorage
|
||||
* @dataProvider quotaExceededProvider
|
||||
*/
|
||||
public function testCheckExceededQuota($quota, $headers)
|
||||
{
|
||||
$this->plugin->fileView = $this->buildFileViewMock($quota);
|
||||
public function testCheckExceededQuota($quota, $headers) {
|
||||
$this->init($quota);
|
||||
|
||||
$this->server->httpRequest = new Sabre_HTTP_Request($headers);
|
||||
$this->plugin->checkQuota('');
|
||||
|
@ -92,7 +91,7 @@ class Test_OC_Connector_Sabre_QuotaPlugin extends PHPUnit_Framework_TestCase {
|
|||
|
||||
private function buildFileViewMock($quota) {
|
||||
// mock filesysten
|
||||
$view = $this->getMock('\OC\Files\View', array('free_space'), array(), '', FALSE);
|
||||
$view = $this->getMock('\OC\Files\View', array('free_space'), array(), '', false);
|
||||
$view->expects($this->any())->method('free_space')->withAnyParameters()->will($this->returnValue($quota));
|
||||
|
||||
return $view;
|
||||
|
|
Loading…
Reference in New Issue