Pass the filesystem view as argument in the sabredav connectors and use the fileinfo object
This commit is contained in:
parent
9b4af31bac
commit
3a21755963
|
@ -34,12 +34,8 @@ $authBackend = new OC_Connector_Sabre_Auth();
|
||||||
$lockBackend = new OC_Connector_Sabre_Locks();
|
$lockBackend = new OC_Connector_Sabre_Locks();
|
||||||
$requestBackend = new OC_Connector_Sabre_Request();
|
$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
|
// Fire up server
|
||||||
$server = new OC_Connector_Sabre_Server($objectTree);
|
$server = new OC_Connector_Sabre_Server();
|
||||||
$server->httpRequest = $requestBackend;
|
$server->httpRequest = $requestBackend;
|
||||||
$server->setBaseUri($baseuri);
|
$server->setBaseUri($baseuri);
|
||||||
|
|
||||||
|
@ -49,10 +45,22 @@ $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, $defaults->getName())
|
||||||
$server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
|
$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 Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload
|
||||||
$server->addPlugin(new OC_Connector_Sabre_FilesPlugin());
|
$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_MaintenancePlugin());
|
||||||
$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
|
$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) {
|
||||||
|
$view = \OC\Files\Filesystem::getView();
|
||||||
|
$rootInfo = $view->getFileInfo('');
|
||||||
|
|
||||||
|
// Create ownCloud Dir
|
||||||
|
$rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo);
|
||||||
|
$objectTree = new \OC\Connector\Sabre\ObjectTree($rootDir, $view);
|
||||||
|
$server->setObjectTree($objectTree);
|
||||||
|
|
||||||
|
$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!
|
// And off we go!
|
||||||
$server->exec();
|
$server->exec();
|
||||||
|
|
|
@ -22,11 +22,16 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
||||||
private $server;
|
private $server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is kept public to allow overwrite for unit testing
|
|
||||||
*
|
|
||||||
* @var \OC\Files\View
|
* @var \OC\Files\View
|
||||||
*/
|
*/
|
||||||
public $fileView;
|
private $fileView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \OC\Files\View $view
|
||||||
|
*/
|
||||||
|
public function __construct($view) {
|
||||||
|
$this->fileView = $view;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This initializes the plugin.
|
* 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
|
// 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +75,9 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
||||||
if (!$expected) {
|
if (!$expected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$actual = $this->getFileView()->filesize($filePath);
|
$actual = $this->fileView->filesize($filePath);
|
||||||
if ($actual != $expected) {
|
if ($actual != $expected) {
|
||||||
$this->getFileView()->unlink($filePath);
|
$this->fileView->unlink($filePath);
|
||||||
throw new Sabre_DAV_Exception_BadRequest('expected filesize ' . $expected . ' got ' . $actual);
|
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
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLength()
|
public function getLength() {
|
||||||
{
|
|
||||||
$req = $this->server->httpRequest;
|
$req = $this->server->httpRequest;
|
||||||
$length = $req->getHeader('X-Expected-Entity-Length');
|
$length = $req->getHeader('X-Expected-Entity-Length');
|
||||||
if (!$length) {
|
if (!$length) {
|
||||||
|
@ -91,17 +95,4 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl
|
||||||
|
|
||||||
return $length;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,20 +60,22 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
|
|
||||||
// exit if we can't create a new file and we don't updatable existing file
|
// exit if we can't create a new file and we don't updatable existing file
|
||||||
$info = OC_FileChunking::decodeName($name);
|
$info = OC_FileChunking::decodeName($name);
|
||||||
if (!\OC\Files\Filesystem::isCreatable($this->path) &&
|
if (!$this->fileView->isCreatable($this->path) &&
|
||||||
!\OC\Files\Filesystem::isUpdatable($this->path . '/' . $info['name'])) {
|
!$this->fileView->isUpdatable($this->path . '/' . $info['name'])) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// For non-chunked upload it is enough to check if we can create a new file
|
// 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();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = $this->path . '/' . $name;
|
$path = $this->path . '/' . $name;
|
||||||
$node = new OC_Connector_Sabre_File($path);
|
// 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);
|
return $node->put($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +92,12 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\OC\Files\Filesystem::isCreatable($this->path)) {
|
if (!$this->fileView->isCreatable($this->path)) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPath = $this->path . '/' . $name;
|
$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);
|
throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +107,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
* Returns a specific child node, referenced by its name
|
* Returns a specific child node, referenced by its name
|
||||||
*
|
*
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
* @param \OCP\Files\FileInfo $info
|
||||||
* @throws Sabre_DAV_Exception_FileNotFound
|
* @throws Sabre_DAV_Exception_FileNotFound
|
||||||
* @return Sabre_DAV_INode
|
* @return Sabre_DAV_INode
|
||||||
*/
|
*/
|
||||||
|
@ -112,7 +115,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
|
|
||||||
$path = $this->path . '/' . $name;
|
$path = $this->path . '/' . $name;
|
||||||
if (is_null($info)) {
|
if (is_null($info)) {
|
||||||
$info = \OC\Files\Filesystem::getFileInfo($path);
|
$info = $this->fileView->getFileInfo($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$info) {
|
if (!$info) {
|
||||||
|
@ -120,12 +123,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info['mimetype'] == 'httpd/unix-directory') {
|
if ($info['mimetype'] == 'httpd/unix-directory') {
|
||||||
$node = new OC_Connector_Sabre_Directory($path);
|
$node = new OC_Connector_Sabre_Directory($this->fileView, $info);
|
||||||
} else {
|
} else {
|
||||||
$node = new OC_Connector_Sabre_File($path);
|
$node = new OC_Connector_Sabre_File($this->fileView, $info);
|
||||||
}
|
}
|
||||||
|
|
||||||
$node->setFileinfoCache($info);
|
|
||||||
return $node;
|
return $node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +137,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
*/
|
*/
|
||||||
public function getChildren() {
|
public function getChildren() {
|
||||||
|
|
||||||
$folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
|
$folder_content = $this->fileView->getDirectoryContent($this->path);
|
||||||
$paths = array();
|
$paths = array();
|
||||||
foreach($folder_content as $info) {
|
foreach($folder_content as $info) {
|
||||||
$paths[] = $this->path.'/'.$info['name'];
|
$paths[] = $this->path.'/'.$info['name'];
|
||||||
|
@ -167,7 +168,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
|
|
||||||
$nodes = array();
|
$nodes = array();
|
||||||
foreach($folder_content as $info) {
|
foreach($folder_content as $info) {
|
||||||
$node = $this->getChild($info['name'], $info);
|
$node = $this->getChild($info->getName(), $info);
|
||||||
$node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
|
$node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
|
||||||
$nodes[] = $node;
|
$nodes[] = $node;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +184,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
public function childExists($name) {
|
public function childExists($name) {
|
||||||
|
|
||||||
$path = $this->path . '/' . $name;
|
$path = $this->path . '/' . $name;
|
||||||
return \OC\Files\Filesystem::file_exists($path);
|
return $this->fileView->file_exists($path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +200,11 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!\OC\Files\Filesystem::isDeletable($this->path)) {
|
if (!$this->info->isDeletable()) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
\OC\Files\Filesystem::rmdir($this->path);
|
$this->fileView->rmdir($this->path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +236,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||||
public function getProperties($properties) {
|
public function getProperties($properties) {
|
||||||
$props = parent::getProperties($properties);
|
$props = parent::getProperties($properties);
|
||||||
if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
|
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;
|
return $props;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,8 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function put($data) {
|
public function put($data) {
|
||||||
|
if ($this->info && $this->fileView->file_exists($this->path) &&
|
||||||
$fs = $this->getFS();
|
!$this->info->isUpdateable()) {
|
||||||
|
|
||||||
if ($fs->file_exists($this->path) &&
|
|
||||||
!$fs->isUpdatable($this->path)) {
|
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,10 +76,10 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$putOkay = $fs->file_put_contents($partpath, $data);
|
$putOkay = $this->fileView->file_put_contents($partpath, $data);
|
||||||
if ($putOkay === false) {
|
if ($putOkay === false) {
|
||||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
|
\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
|
// 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');
|
throw new Sabre_DAV_Exception('Could not write file contents');
|
||||||
}
|
}
|
||||||
|
@ -105,29 +102,30 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
}
|
}
|
||||||
|
|
||||||
// rename to correct path
|
// rename to correct path
|
||||||
$renameOkay = $fs->rename($partpath, $this->path);
|
$renameOkay = $this->fileView->rename($partpath, $this->path);
|
||||||
$fileExists = $fs->file_exists($this->path);
|
$fileExists = $this->fileView->file_exists($this->path);
|
||||||
if ($renameOkay === false || $fileExists === false) {
|
if ($renameOkay === false || $fileExists === false) {
|
||||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
|
\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');
|
throw new Sabre_DAV_Exception('Could not rename part file to final file');
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow sync clients to send the mtime along in a header
|
// allow sync clients to send the mtime along in a header
|
||||||
$mtime = OC_Request::hasModificationTime();
|
$mtime = OC_Request::hasModificationTime();
|
||||||
if ($mtime !== false) {
|
if ($mtime !== false) {
|
||||||
if($fs->touch($this->path, $mtime)) {
|
if($this->fileView->touch($this->path, $mtime)) {
|
||||||
header('X-OC-MTime: accepted');
|
header('X-OC-MTime: accepted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->refreshInfo();
|
||||||
|
|
||||||
return $this->getETagPropertyForPath($this->path);
|
return '"' . $this->info->getEtag() . '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data
|
* Returns the data
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string | resource
|
||||||
*/
|
*/
|
||||||
public function get() {
|
public function get() {
|
||||||
|
|
||||||
|
@ -135,7 +133,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
if (\OC_Util::encryptedFiles()) {
|
if (\OC_Util::encryptedFiles()) {
|
||||||
throw new \Sabre_DAV_Exception_ServiceUnavailable();
|
throw new \Sabre_DAV_Exception_ServiceUnavailable();
|
||||||
} else {
|
} else {
|
||||||
return \OC\Files\Filesystem::fopen($this->path, 'rb');
|
return $this->fileView->fopen($this->path, 'rb');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -147,16 +145,14 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
* @throws Sabre_DAV_Exception_Forbidden
|
* @throws Sabre_DAV_Exception_Forbidden
|
||||||
*/
|
*/
|
||||||
public function delete() {
|
public function delete() {
|
||||||
$fs = $this->getFS();
|
|
||||||
|
|
||||||
if ($this->path === 'Shared') {
|
if ($this->path === 'Shared') {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$fs->isDeletable($this->path)) {
|
if (!$this->info->isDeletable()) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
$fs->unlink($this->path);
|
$this->fileView->unlink($this->path);
|
||||||
|
|
||||||
// remove properties
|
// remove properties
|
||||||
$this->removeProperties();
|
$this->removeProperties();
|
||||||
|
@ -169,12 +165,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getSize() {
|
public function getSize() {
|
||||||
$this->getFileinfoCache();
|
return $this->info->getSize();
|
||||||
if ($this->fileinfo_cache['size'] > -1) {
|
|
||||||
return $this->fileinfo_cache['size'];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,11 +180,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getETag() {
|
public function getETag() {
|
||||||
$properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
|
return $this->info->getEtag();
|
||||||
if (isset($properties[self::GETETAG_PROPERTYNAME])) {
|
|
||||||
return $properties[self::GETETAG_PROPERTYNAME];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,12 +191,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getContentType() {
|
public function getContentType() {
|
||||||
if (isset($this->fileinfo_cache['mimetype'])) {
|
return $this->info->getMimetype();
|
||||||
return $this->fileinfo_cache['mimetype'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return \OC\Files\Filesystem::getMimeType($this->path);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,15 +227,14 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
|
||||||
$chunk_handler->file_assemble($partFile);
|
$chunk_handler->file_assemble($partFile);
|
||||||
|
|
||||||
// here is the final atomic rename
|
// here is the final atomic rename
|
||||||
$fs = $this->getFS();
|
|
||||||
$targetPath = $path . '/' . $info['name'];
|
$targetPath = $path . '/' . $info['name'];
|
||||||
$renameOkay = $fs->rename($partFile, $targetPath);
|
$renameOkay = $this->fileView->rename($partFile, $targetPath);
|
||||||
$fileExists = $fs->file_exists($targetPath);
|
$fileExists = $this->fileView->file_exists($targetPath);
|
||||||
if ($renameOkay === false || $fileExists === false) {
|
if ($renameOkay === false || $fileExists === false) {
|
||||||
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
|
\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
|
// only delete if an error occurred and the target file was already created
|
||||||
if ($fileExists) {
|
if ($fileExists) {
|
||||||
$fs->unlink($targetPath);
|
$this->fileView->unlink($targetPath);
|
||||||
}
|
}
|
||||||
throw new Sabre_DAV_Exception('Could not rename part file assembled from chunks');
|
throw new Sabre_DAV_Exception('Could not rename part file assembled from chunks');
|
||||||
}
|
}
|
||||||
|
@ -261,12 +242,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
|
// allow sync clients to send the mtime along in a header
|
||||||
$mtime = OC_Request::hasModificationTime();
|
$mtime = OC_Request::hasModificationTime();
|
||||||
if ($mtime !== false) {
|
if ($mtime !== false) {
|
||||||
if($fs->touch($targetPath, $mtime)) {
|
if($this->fileView->touch($targetPath, $mtime)) {
|
||||||
header('X-OC-MTime: accepted');
|
header('X-OC-MTime: accepted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OC_Connector_Sabre_Node::getETagPropertyForPath($targetPath);
|
$info = $this->fileView->getFileInfo($targetPath);
|
||||||
|
return $info->getEtag();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* 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 {
|
abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties {
|
||||||
const GETETAG_PROPERTYNAME = '{DAV:}getetag';
|
const GETETAG_PROPERTYNAME = '{DAV:}getetag';
|
||||||
const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
|
const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
|
||||||
|
@ -33,11 +32,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
public static $ETagFunction = null;
|
public static $ETagFunction = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is kept public to allow overwrite for unit testing
|
|
||||||
*
|
|
||||||
* @var \OC\Files\View
|
* @var \OC\Files\View
|
||||||
*/
|
*/
|
||||||
public $fileView;
|
protected $fileView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path to the current node
|
* The path to the current node
|
||||||
|
@ -46,53 +43,53 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
*/
|
*/
|
||||||
protected $path;
|
protected $path;
|
||||||
|
|
||||||
/**
|
|
||||||
* node fileinfo cache
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $fileinfo_cache;
|
|
||||||
/**
|
/**
|
||||||
* node properties cache
|
* node properties cache
|
||||||
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $property_cache = null;
|
protected $property_cache = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets up the node, expects a full path name
|
* @var \OCP\Files\FileInfo
|
||||||
* @param string $path
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function __construct($path) {
|
protected $info;
|
||||||
$this->path = $path;
|
|
||||||
|
/**
|
||||||
|
* @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
|
* @brief Returns the name of the node
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getName() {
|
public function getName() {
|
||||||
|
return $this->info->getName();
|
||||||
list(, $name) = Sabre_DAV_URLUtil::splitPath($this->path);
|
|
||||||
return $name;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Renames the node
|
* @brief Renames the node
|
||||||
* @param string $name The new name
|
* @param string $name The new name
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function setName($name) {
|
public function setName($name) {
|
||||||
$fs = $this->getFS();
|
|
||||||
|
|
||||||
// rename is only allowed if the update privilege is granted
|
// 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();
|
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);
|
list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
|
||||||
|
|
||||||
if (!\OCP\Util::isValidFileName($newName)) {
|
if (!\OCP\Util::isValidFileName($newName)) {
|
||||||
|
@ -102,38 +99,17 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
$newPath = $parentPath . '/' . $newName;
|
$newPath = $parentPath . '/' . $newName;
|
||||||
$oldPath = $this->path;
|
$oldPath = $this->path;
|
||||||
|
|
||||||
$fs->rename($this->path, $newPath);
|
$this->fileView->rename($this->path, $newPath);
|
||||||
|
|
||||||
$this->path = $newPath;
|
$this->path = $newPath;
|
||||||
|
|
||||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
$query = OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||||
$query->execute( array( $newPath, OC_User::getUser(), $oldPath ));
|
$query->execute(array($newPath, OC_User::getUser(), $oldPath));
|
||||||
|
$this->refreshInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFileinfoCache($fileinfo_cache)
|
public function setPropertyCache($property_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)
|
|
||||||
{
|
|
||||||
$this->property_cache = $property_cache;
|
$this->property_cache = $property_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +118,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getLastModified() {
|
public function getLastModified() {
|
||||||
$this->getFileinfoCache();
|
return $this->info->getMtime();
|
||||||
return $this->fileinfo_cache['mtime'];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +128,8 @@ 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.
|
* Even if the modification time is set to a custom value the access time is set to now.
|
||||||
*/
|
*/
|
||||||
public function touch($mtime) {
|
public function touch($mtime) {
|
||||||
\OC\Files\Filesystem::touch($this->path, $mtime);
|
$this->fileView->touch($this->path, $mtime);
|
||||||
|
$this->refreshInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,29 +139,28 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
*/
|
*/
|
||||||
public function updateProperties($properties) {
|
public function updateProperties($properties) {
|
||||||
$existing = $this->getProperties(array());
|
$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 it was null, we need to delete the property
|
||||||
if (is_null($propertyValue)) {
|
if (is_null($propertyValue)) {
|
||||||
if(array_key_exists( $propertyName, $existing )) {
|
if (array_key_exists($propertyName, $existing)) {
|
||||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
|
$query = OC_DB::prepare('DELETE FROM `*PREFIX*properties`'
|
||||||
.' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
. ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?');
|
||||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName ));
|
$query->execute(array(OC_User::getUser(), $this->path, $propertyName));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
if (strcmp($propertyName, self::GETETAG_PROPERTYNAME) === 0) {
|
||||||
if( strcmp( $propertyName, self::GETETAG_PROPERTYNAME) === 0 ) {
|
\OC\Files\Filesystem::putFileInfo($this->path, array('etag' => $propertyValue));
|
||||||
\OC\Files\Filesystem::putFileInfo($this->path, array('etag'=> $propertyValue));
|
} elseif (strcmp($propertyName, self::LASTMODIFIED_PROPERTYNAME) === 0) {
|
||||||
} elseif( strcmp( $propertyName, self::LASTMODIFIED_PROPERTYNAME) === 0 ) {
|
|
||||||
$this->touch($propertyValue);
|
$this->touch($propertyValue);
|
||||||
} else {
|
} else {
|
||||||
if(!array_key_exists( $propertyName, $existing )) {
|
if (!array_key_exists($propertyName, $existing)) {
|
||||||
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties`'
|
$query = OC_DB::prepare('INSERT INTO `*PREFIX*properties`'
|
||||||
.' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
|
. ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)');
|
||||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue ));
|
$query->execute(array(OC_User::getUser(), $this->path, $propertyName, $propertyValue));
|
||||||
} else {
|
} else {
|
||||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'
|
$query = OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'
|
||||||
.' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
. ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?');
|
||||||
$query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName ));
|
$query->execute(array($propertyValue, OC_User::getUser(), $this->path, $propertyName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,9 +174,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
* removes all properties for this node and user
|
* removes all properties for this node and user
|
||||||
*/
|
*/
|
||||||
public function removeProperties() {
|
public function removeProperties() {
|
||||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
|
$query = OC_DB::prepare('DELETE FROM `*PREFIX*properties`'
|
||||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||||
$query->execute( array( OC_User::getUser(), $this->path));
|
$query->execute(array(OC_User::getUser(), $this->path));
|
||||||
|
|
||||||
$this->setPropertyCache(null);
|
$this->setPropertyCache(null);
|
||||||
}
|
}
|
||||||
|
@ -219,29 +194,23 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
|
|
||||||
if (is_null($this->property_cache)) {
|
if (is_null($this->property_cache)) {
|
||||||
$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
|
$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();
|
$this->property_cache = array();
|
||||||
while( $row = $result->fetchRow()) {
|
while ($row = $result->fetchRow()) {
|
||||||
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
|
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't call the static getETagPropertyForPath, its result is not cached
|
$this->property_cache[self::GETETAG_PROPERTYNAME] = '"' . $this->info->getEtag() . '"';
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the array was empty, we need to return everything
|
// if the array was empty, we need to return everything
|
||||||
if(count($properties) == 0) {
|
if (count($properties) == 0) {
|
||||||
return $this->property_cache;
|
return $this->property_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
$props = array();
|
$props = array();
|
||||||
foreach($properties as $property) {
|
foreach ($properties as $property) {
|
||||||
if (isset($this->property_cache[$property])) {
|
if (isset($this->property_cache[$property])) {
|
||||||
$props[$property] = $this->property_cache[$property];
|
$props[$property] = $this->property_cache[$property];
|
||||||
}
|
}
|
||||||
|
@ -250,36 +219,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
return $props;
|
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
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
public function getFileId()
|
public function getFileId() {
|
||||||
{
|
if ($this->info->getId()) {
|
||||||
$this->getFileinfoCache();
|
|
||||||
|
|
||||||
if (isset($this->fileinfo_cache['fileid'])) {
|
|
||||||
$instanceId = OC_Util::getInstanceId();
|
$instanceId = OC_Util::getInstanceId();
|
||||||
$id = sprintf('%08d', $this->fileinfo_cache['fileid']);
|
$id = sprintf('%08d', $this->info->getId());
|
||||||
return $id . $instanceId;
|
return $id . $instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,16 +8,28 @@
|
||||||
|
|
||||||
namespace OC\Connector\Sabre;
|
namespace OC\Connector\Sabre;
|
||||||
|
|
||||||
|
use OC\Files\FileInfo;
|
||||||
use OC\Files\Filesystem;
|
use OC\Files\Filesystem;
|
||||||
|
|
||||||
class ObjectTree extends \Sabre_DAV_ObjectTree {
|
class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* keep this public to allow mock injection during unit test
|
|
||||||
*
|
|
||||||
* @var \OC\Files\View
|
* @var \OC\Files\View
|
||||||
*/
|
*/
|
||||||
public $fileView;
|
protected $fileView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the object
|
||||||
|
*
|
||||||
|
* This method expects the rootObject to be passed as a parameter
|
||||||
|
*
|
||||||
|
* @param \Sabre_DAV_ICollection $rootNode
|
||||||
|
* @param \OC\Files\View $view
|
||||||
|
*/
|
||||||
|
public function __construct(\Sabre_DAV_ICollection $rootNode, $view) {
|
||||||
|
parent::__construct($rootNode);
|
||||||
|
$this->fileView = $view;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the INode object for the requested path
|
* Returns the INode object for the requested path
|
||||||
|
@ -40,31 +52,34 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
|
|
||||||
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
|
if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
|
||||||
// read from storage
|
// read from storage
|
||||||
$absPath = $this->getFileView()->getAbsolutePath($path);
|
$absPath = $this->fileView->getAbsolutePath($path);
|
||||||
list($storage, $internalPath) = Filesystem::resolvePath('/' . $absPath);
|
list($storage, $internalPath) = Filesystem::resolvePath('/' . $absPath);
|
||||||
if ($storage) {
|
if ($storage) {
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\Storage\Storage $storage
|
||||||
|
*/
|
||||||
$scanner = $storage->getScanner($internalPath);
|
$scanner = $storage->getScanner($internalPath);
|
||||||
// get data directly
|
// 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
|
// read from cache
|
||||||
$info = $this->getFileView()->getFileInfo($path);
|
$info = $this->fileView->getFileInfo($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$info) {
|
if (!$info) {
|
||||||
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
|
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info['mimetype'] === 'httpd/unix-directory') {
|
if ($info->getType() === 'dir') {
|
||||||
$node = new \OC_Connector_Sabre_Directory($path);
|
$node = new \OC_Connector_Sabre_Directory($this->fileView, $info);
|
||||||
} else {
|
} else {
|
||||||
$node = new \OC_Connector_Sabre_File($path);
|
$node = new \OC_Connector_Sabre_File($this->fileView, $info);
|
||||||
}
|
}
|
||||||
|
|
||||||
$node->setFileinfoCache($info);
|
|
||||||
|
|
||||||
$this->cache[$path] = $node;
|
$this->cache[$path] = $node;
|
||||||
return $node;
|
return $node;
|
||||||
|
|
||||||
|
@ -88,19 +103,18 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath);
|
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath);
|
||||||
|
|
||||||
// check update privileges
|
// check update privileges
|
||||||
$fs = $this->getFileView();
|
if (!$this->fileView->isUpdatable($sourcePath)) {
|
||||||
if (!$fs->isUpdatable($sourcePath)) {
|
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
if ($sourceDir !== $destinationDir) {
|
if ($sourceDir !== $destinationDir) {
|
||||||
// for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
|
// for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
|
||||||
if (!$fs->isUpdatable($sourceDir)) {
|
if (!$this->fileView->isUpdatable($sourceDir)) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
if (!$fs->isUpdatable($destinationDir)) {
|
if (!$this->fileView->isUpdatable($destinationDir)) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
if (!$fs->isDeletable($sourcePath)) {
|
if (!$this->fileView->isDeletable($sourcePath)) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden();
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,15 +124,15 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
throw new \Sabre_DAV_Exception_BadRequest();
|
throw new \Sabre_DAV_Exception_BadRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
$renameOkay = $fs->rename($sourcePath, $destinationPath);
|
$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
|
||||||
if (!$renameOkay) {
|
if (!$renameOkay) {
|
||||||
throw new \Sabre_DAV_Exception_Forbidden('');
|
throw new \Sabre_DAV_Exception_Forbidden('');
|
||||||
}
|
}
|
||||||
|
|
||||||
// update properties
|
// update properties
|
||||||
$query = \OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
$query = \OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertypath` = ?'
|
||||||
.' WHERE `userid` = ? AND `propertypath` = ?' );
|
. ' WHERE `userid` = ? AND `propertypath` = ?');
|
||||||
$query->execute( array( $destinationPath, \OC_User::getUser(), $sourcePath ));
|
$query->execute(array($destinationPath, \OC_User::getUser(), $sourcePath));
|
||||||
|
|
||||||
$this->markDirty($sourceDir);
|
$this->markDirty($sourceDir);
|
||||||
$this->markDirty($destinationDir);
|
$this->markDirty($destinationDir);
|
||||||
|
@ -137,12 +151,12 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
*/
|
*/
|
||||||
public function copy($source, $destination) {
|
public function copy($source, $destination) {
|
||||||
|
|
||||||
if (Filesystem::is_file($source)) {
|
if ($this->fileView->is_file($source)) {
|
||||||
Filesystem::copy($source, $destination);
|
$this->fileView->copy($source, $destination);
|
||||||
} else {
|
} else {
|
||||||
Filesystem::mkdir($destination);
|
$this->fileView->mkdir($destination);
|
||||||
$dh = Filesystem::opendir($source);
|
$dh = $this->fileView->opendir($source);
|
||||||
if(is_resource($dh)) {
|
if (is_resource($dh)) {
|
||||||
while (($subnode = readdir($dh)) !== false) {
|
while (($subnode = readdir($dh)) !== false) {
|
||||||
|
|
||||||
if ($subnode == '.' || $subnode == '..') continue;
|
if ($subnode == '.' || $subnode == '..') continue;
|
||||||
|
@ -155,14 +169,4 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
|
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
|
||||||
$this->markDirty($destinationDir);
|
$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 {
|
class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \OC\Files\View
|
||||||
|
*/
|
||||||
|
private $view;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to main server object
|
* Reference to main server object
|
||||||
*
|
*
|
||||||
|
@ -17,11 +22,11 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||||
private $server;
|
private $server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* is kept public to allow overwrite for unit testing
|
* @param \OC\Files\View $view
|
||||||
*
|
|
||||||
* @var \OC\Files\View
|
|
||||||
*/
|
*/
|
||||||
public $fileView;
|
public function __construct($view) {
|
||||||
|
$this->view = $view;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This initializes the plugin.
|
* This initializes the plugin.
|
||||||
|
@ -52,8 +57,8 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||||
public function checkQuota($uri, $data = null) {
|
public function checkQuota($uri, $data = null) {
|
||||||
$length = $this->getLength();
|
$length = $this->getLength();
|
||||||
if ($length) {
|
if ($length) {
|
||||||
if (substr($uri, 0, 1)!=='/') {
|
if (substr($uri, 0, 1) !== '/') {
|
||||||
$uri='/'.$uri;
|
$uri = '/' . $uri;
|
||||||
}
|
}
|
||||||
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
|
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
|
||||||
$freeSpace = $this->getFreeSpace($parentUri);
|
$freeSpace = $this->getFreeSpace($parentUri);
|
||||||
|
@ -64,8 +69,7 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLength()
|
public function getLength() {
|
||||||
{
|
|
||||||
$req = $this->server->httpRequest;
|
$req = $this->server->httpRequest;
|
||||||
$length = $req->getHeader('X-Expected-Entity-Length');
|
$length = $req->getHeader('X-Expected-Entity-Length');
|
||||||
if (!$length) {
|
if (!$length) {
|
||||||
|
@ -84,14 +88,8 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||||
* @param $parentUri
|
* @param $parentUri
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getFreeSpace($parentUri)
|
public function getFreeSpace($parentUri) {
|
||||||
{
|
$freeSpace = $this->view->free_space($parentUri);
|
||||||
if (is_null($this->fileView)) {
|
|
||||||
// initialize fileView
|
|
||||||
$this->fileView = \OC\Files\Filesystem::getView();
|
|
||||||
}
|
|
||||||
|
|
||||||
$freeSpace = $this->fileView->free_space($parentUri);
|
|
||||||
return $freeSpace;
|
return $freeSpace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,22 @@
|
||||||
* @see Sabre_DAV_Server
|
* @see Sabre_DAV_Server
|
||||||
*/
|
*/
|
||||||
class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
|
/**
|
||||||
|
* Sets up the server
|
||||||
|
*
|
||||||
|
* Unlike Sabre_DAV_Server's constructor this does not take an INode or ObjectTree as argument,
|
||||||
|
* the object tree needs to be set later with setObjectTree
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->httpResponse = new Sabre_HTTP_Response();
|
||||||
|
$this->httpRequest = new Sabre_HTTP_Request();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setObjectTree($tree) {
|
||||||
|
$this->tree = $tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see Sabre_DAV_Server
|
* @see Sabre_DAV_Server
|
||||||
|
@ -40,22 +56,22 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
// The only two options for the depth of a propfind is 0 or 1
|
// The only two options for the depth of a propfind is 0 or 1
|
||||||
// if ($depth!=0) $depth = 1;
|
// if ($depth!=0) $depth = 1;
|
||||||
|
|
||||||
$newProperties = $this->getPropertiesForPath($uri,$requestedProperties,$depth);
|
$newProperties = $this->getPropertiesForPath($uri, $requestedProperties, $depth);
|
||||||
|
|
||||||
// This is a multi-status response
|
// This is a multi-status response
|
||||||
$this->httpResponse->sendStatus(207);
|
$this->httpResponse->sendStatus(207);
|
||||||
$this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
|
$this->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
|
||||||
$this->httpResponse->setHeader('Vary','Brief,Prefer');
|
$this->httpResponse->setHeader('Vary', 'Brief,Prefer');
|
||||||
|
|
||||||
// Normally this header is only needed for OPTIONS responses, however..
|
// Normally this header is only needed for OPTIONS responses, however..
|
||||||
// iCal seems to also depend on these being set for PROPFIND. Since
|
// iCal seems to also depend on these being set for PROPFIND. Since
|
||||||
// this is not harmful, we'll add it.
|
// this is not harmful, we'll add it.
|
||||||
$features = array('1','3', 'extended-mkcol');
|
$features = array('1', '3', 'extended-mkcol');
|
||||||
foreach($this->plugins as $plugin) {
|
foreach ($this->plugins as $plugin) {
|
||||||
$features = array_merge($features,$plugin->getFeatures());
|
$features = array_merge($features, $plugin->getFeatures());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->httpResponse->setHeader('DAV',implode(', ',$features));
|
$this->httpResponse->setHeader('DAV', implode(', ', $features));
|
||||||
|
|
||||||
$prefer = $this->getHTTPPrefer();
|
$prefer = $this->getHTTPPrefer();
|
||||||
$minimal = $prefer['return-minimal'];
|
$minimal = $prefer['return-minimal'];
|
||||||
|
@ -67,10 +83,11 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small helper to support PROPFIND with DEPTH_INFINITY.
|
* Small helper to support PROPFIND with DEPTH_INFINITY.
|
||||||
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*/
|
*/
|
||||||
private function addPathNodesRecursively(&$nodes, $path) {
|
private function addPathNodesRecursively(&$nodes, $path) {
|
||||||
foreach($this->tree->getChildren($path) as $childNode) {
|
foreach ($this->tree->getChildren($path) as $childNode) {
|
||||||
$nodes[$path . '/' . $childNode->getName()] = $childNode;
|
$nodes[$path . '/' . $childNode->getName()] = $childNode;
|
||||||
if ($childNode instanceof Sabre_DAV_ICollection)
|
if ($childNode instanceof Sabre_DAV_ICollection)
|
||||||
$this->addPathNodesRecursively($nodes, $path . '/' . $childNode->getName());
|
$this->addPathNodesRecursively($nodes, $path . '/' . $childNode->getName());
|
||||||
|
@ -81,7 +98,7 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
|
|
||||||
// if ($depth!=0) $depth = 1;
|
// if ($depth!=0) $depth = 1;
|
||||||
|
|
||||||
$path = rtrim($path,'/');
|
$path = rtrim($path, '/');
|
||||||
|
|
||||||
$returnPropertyList = array();
|
$returnPropertyList = array();
|
||||||
|
|
||||||
|
@ -89,9 +106,10 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
$nodes = array(
|
$nodes = array(
|
||||||
$path => $parentNode
|
$path => $parentNode
|
||||||
);
|
);
|
||||||
if ($depth==1 && $parentNode instanceof Sabre_DAV_ICollection) {
|
if ($depth == 1 && $parentNode instanceof Sabre_DAV_ICollection) {
|
||||||
foreach($this->tree->getChildren($path) as $childNode)
|
foreach ($this->tree->getChildren($path) as $childNode) {
|
||||||
$nodes[$path . '/' . $childNode->getName()] = $childNode;
|
$nodes[$path . '/' . $childNode->getName()] = $childNode;
|
||||||
|
}
|
||||||
} else if ($depth == self::DEPTH_INFINITY && $parentNode instanceof Sabre_DAV_ICollection) {
|
} else if ($depth == self::DEPTH_INFINITY && $parentNode instanceof Sabre_DAV_ICollection) {
|
||||||
$this->addPathNodesRecursively($nodes, $path);
|
$this->addPathNodesRecursively($nodes, $path);
|
||||||
}
|
}
|
||||||
|
@ -99,9 +117,9 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
// If the propertyNames array is empty, it means all properties are requested.
|
// If the propertyNames array is empty, it means all properties are requested.
|
||||||
// We shouldn't actually return everything we know though, and only return a
|
// We shouldn't actually return everything we know though, and only return a
|
||||||
// sensible list.
|
// sensible list.
|
||||||
$allProperties = count($propertyNames)==0;
|
$allProperties = count($propertyNames) == 0;
|
||||||
|
|
||||||
foreach($nodes as $myPath=>$node) {
|
foreach ($nodes as $myPath => $node) {
|
||||||
|
|
||||||
$currentPropertyNames = $propertyNames;
|
$currentPropertyNames = $propertyNames;
|
||||||
|
|
||||||
|
@ -128,15 +146,15 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
// to make certain decisions about the entry.
|
// to make certain decisions about the entry.
|
||||||
// WebDAV dictates we should add a / and the end of href's for collections
|
// WebDAV dictates we should add a / and the end of href's for collections
|
||||||
$removeRT = false;
|
$removeRT = false;
|
||||||
if (!in_array('{DAV:}resourcetype',$currentPropertyNames)) {
|
if (!in_array('{DAV:}resourcetype', $currentPropertyNames)) {
|
||||||
$currentPropertyNames[] = '{DAV:}resourcetype';
|
$currentPropertyNames[] = '{DAV:}resourcetype';
|
||||||
$removeRT = true;
|
$removeRT = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->broadcastEvent('beforeGetProperties',array($myPath, $node, &$currentPropertyNames, &$newProperties));
|
$result = $this->broadcastEvent('beforeGetProperties', array($myPath, $node, &$currentPropertyNames, &$newProperties));
|
||||||
// If this method explicitly returned false, we must ignore this
|
// If this method explicitly returned false, we must ignore this
|
||||||
// node as it is inaccessible.
|
// node as it is inaccessible.
|
||||||
if ($result===false) continue;
|
if ($result === false) continue;
|
||||||
|
|
||||||
if (count($currentPropertyNames) > 0) {
|
if (count($currentPropertyNames) > 0) {
|
||||||
|
|
||||||
|
@ -149,7 +167,7 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
// So as we loop through this list, we will only take the
|
// So as we loop through this list, we will only take the
|
||||||
// properties that were actually requested and discard the
|
// properties that were actually requested and discard the
|
||||||
// rest.
|
// rest.
|
||||||
foreach($currentPropertyNames as $k=>$currentPropertyName) {
|
foreach ($currentPropertyNames as $k => $currentPropertyName) {
|
||||||
if (isset($nodeProperties[$currentPropertyName])) {
|
if (isset($nodeProperties[$currentPropertyName])) {
|
||||||
unset($currentPropertyNames[$k]);
|
unset($currentPropertyNames[$k]);
|
||||||
$newProperties[200][$currentPropertyName] = $nodeProperties[$currentPropertyName];
|
$newProperties[200][$currentPropertyName] = $nodeProperties[$currentPropertyName];
|
||||||
|
@ -160,12 +178,14 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($currentPropertyNames as $prop) {
|
foreach ($currentPropertyNames as $prop) {
|
||||||
|
|
||||||
if (isset($newProperties[200][$prop])) continue;
|
if (isset($newProperties[200][$prop])) continue;
|
||||||
|
|
||||||
switch($prop) {
|
switch ($prop) {
|
||||||
case '{DAV:}getlastmodified' : if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified()); break;
|
case '{DAV:}getlastmodified' :
|
||||||
|
if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified());
|
||||||
|
break;
|
||||||
case '{DAV:}getcontentlength' :
|
case '{DAV:}getcontentlength' :
|
||||||
if ($node instanceof Sabre_DAV_IFile) {
|
if ($node instanceof Sabre_DAV_IFile) {
|
||||||
$size = $node->getSize();
|
$size = $node->getSize();
|
||||||
|
@ -186,18 +206,22 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
$newProperties[200][$prop] = $quotaInfo[1];
|
$newProperties[200][$prop] = $quotaInfo[1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '{DAV:}getetag' : if ($node instanceof Sabre_DAV_IFile && $etag = $node->getETag()) $newProperties[200][$prop] = $etag; break;
|
case '{DAV:}getetag' :
|
||||||
case '{DAV:}getcontenttype' : if ($node instanceof Sabre_DAV_IFile && $ct = $node->getContentType()) $newProperties[200][$prop] = $ct; break;
|
if ($node instanceof Sabre_DAV_IFile && $etag = $node->getETag()) $newProperties[200][$prop] = $etag;
|
||||||
|
break;
|
||||||
|
case '{DAV:}getcontenttype' :
|
||||||
|
if ($node instanceof Sabre_DAV_IFile && $ct = $node->getContentType()) $newProperties[200][$prop] = $ct;
|
||||||
|
break;
|
||||||
case '{DAV:}supported-report-set' :
|
case '{DAV:}supported-report-set' :
|
||||||
$reports = array();
|
$reports = array();
|
||||||
foreach($this->plugins as $plugin) {
|
foreach ($this->plugins as $plugin) {
|
||||||
$reports = array_merge($reports, $plugin->getSupportedReportSet($myPath));
|
$reports = array_merge($reports, $plugin->getSupportedReportSet($myPath));
|
||||||
}
|
}
|
||||||
$newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports);
|
$newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports);
|
||||||
break;
|
break;
|
||||||
case '{DAV:}resourcetype' :
|
case '{DAV:}resourcetype' :
|
||||||
$newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType();
|
$newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType();
|
||||||
foreach($this->resourceTypeMapping as $className => $resourceType) {
|
foreach ($this->resourceTypeMapping as $className => $resourceType) {
|
||||||
if ($node instanceof $className) $newProperties[200]['{DAV:}resourcetype']->add($resourceType);
|
if ($node instanceof $className) $newProperties[200]['{DAV:}resourcetype']->add($resourceType);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -209,16 +233,16 @@ class OC_Connector_Sabre_Server extends Sabre_DAV_Server {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties, $node));
|
$this->broadcastEvent('afterGetProperties', array(trim($myPath, '/'), &$newProperties, $node));
|
||||||
|
|
||||||
$newProperties['href'] = trim($myPath,'/');
|
$newProperties['href'] = trim($myPath, '/');
|
||||||
|
|
||||||
// Its is a WebDAV recommendation to add a trailing slash to collectionnames.
|
// Its is a WebDAV recommendation to add a trailing slash to collectionnames.
|
||||||
// Apple's iCal also requires a trailing slash for principals (rfc 3744), though this is non-standard.
|
// Apple's iCal also requires a trailing slash for principals (rfc 3744), though this is non-standard.
|
||||||
if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype'])) {
|
if ($myPath != '' && isset($newProperties[200]['{DAV:}resourcetype'])) {
|
||||||
$rt = $newProperties[200]['{DAV:}resourcetype'];
|
$rt = $newProperties[200]['{DAV:}resourcetype'];
|
||||||
if ($rt->is('{DAV:}collection') || $rt->is('{DAV:}principal')) {
|
if ($rt->is('{DAV:}collection') || $rt->is('{DAV:}principal')) {
|
||||||
$newProperties['href'] .='/';
|
$newProperties['href'] .= '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue