mirror of
https://github.com/nextcloud/server.git
synced 2026-03-04 06:21:07 -05:00
Convert StorageNotAvailableException to SabreDAV exception
Convert \OCP\Files\StorageNotAvailableException to \Sabre\DAV\Exception\ServiceUnavailable for every file/directory operation happening inside of SabreDAV. This is necessary to avoid having the exception bubble up to remote.php which would return an exception page instead of an appropriate response.
This commit is contained in:
parent
0d00e247c3
commit
cccedf6f30
4 changed files with 155 additions and 113 deletions
|
|
@ -51,29 +51,33 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
|||
*/
|
||||
public function createFile($name, $data = null) {
|
||||
|
||||
// for chunked upload also updating a existing file is a "createFile"
|
||||
// because we create all the chunks before re-assemble them to the existing file.
|
||||
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
|
||||
try {
|
||||
// for chunked upload also updating a existing file is a "createFile"
|
||||
// because we create all the chunks before re-assemble them to the existing file.
|
||||
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
|
||||
|
||||
// exit if we can't create a new file and we don't updatable existing file
|
||||
$info = OC_FileChunking::decodeName($name);
|
||||
if (!$this->fileView->isCreatable($this->path) &&
|
||||
!$this->fileView->isUpdatable($this->path . '/' . $info['name'])) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
// exit if we can't create a new file and we don't updatable existing file
|
||||
$info = OC_FileChunking::decodeName($name);
|
||||
if (!$this->fileView->isCreatable($this->path) &&
|
||||
!$this->fileView->isUpdatable($this->path . '/' . $info['name'])) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
|
||||
} else {
|
||||
// For non-chunked upload it is enough to check if we can create a new file
|
||||
if (!$this->fileView->isCreatable($this->path)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// For non-chunked upload it is enough to check if we can create a new file
|
||||
if (!$this->fileView->isCreatable($this->path)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
$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);
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,15 +88,18 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
|||
* @return void
|
||||
*/
|
||||
public function createDirectory($name) {
|
||||
if (!$this->info->isCreatable()) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
try {
|
||||
if (!$this->info->isCreatable()) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
|
||||
$newPath = $this->path . '/' . $name;
|
||||
if(!$this->fileView->mkdir($newPath)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath);
|
||||
$newPath = $this->path . '/' . $name;
|
||||
if(!$this->fileView->mkdir($newPath)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden('Could not create directory '.$newPath);
|
||||
}
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,10 +111,13 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node
|
|||
* @return \Sabre\DAV\INode
|
||||
*/
|
||||
public function getChild($name, $info = null) {
|
||||
|
||||
$path = $this->path . '/' . $name;
|
||||
if (is_null($info)) {
|
||||
$info = $this->fileView->getFileInfo($path);
|
||||
try {
|
||||
$info = $this->fileView->getFileInfo($path);
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (!$info) {
|
||||
|
|
|
|||
|
|
@ -50,9 +50,13 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
|||
* @return string|null
|
||||
*/
|
||||
public function put($data) {
|
||||
if ($this->info && $this->fileView->file_exists($this->path) &&
|
||||
!$this->info->isUpdateable()) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
try {
|
||||
if ($this->info && $this->fileView->file_exists($this->path) &&
|
||||
!$this->info->isUpdateable()) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
// throw an exception if encryption was disabled but the files are still encrypted
|
||||
|
|
@ -102,43 +106,49 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
|||
throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e);
|
||||
} catch (\OCA\Encryption\Exceptions\EncryptionException $e) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
// if content length is sent by client:
|
||||
// double check if the file was fully received
|
||||
// compare expected and actual size
|
||||
if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] !== 'LOCK') {
|
||||
$expected = $_SERVER['CONTENT_LENGTH'];
|
||||
$actual = $this->fileView->filesize($partFilePath);
|
||||
if ($actual != $expected) {
|
||||
$this->fileView->unlink($partFilePath);
|
||||
throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual);
|
||||
}
|
||||
}
|
||||
|
||||
// rename to correct path
|
||||
try {
|
||||
$renameOkay = $this->fileView->rename($partFilePath, $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);
|
||||
$this->fileView->unlink($partFilePath);
|
||||
throw new \Sabre\DAV\Exception('Could not rename part file to final file');
|
||||
// if content length is sent by client:
|
||||
// double check if the file was fully received
|
||||
// compare expected and actual size
|
||||
if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] !== 'LOCK') {
|
||||
$expected = $_SERVER['CONTENT_LENGTH'];
|
||||
$actual = $this->fileView->filesize($partFilePath);
|
||||
if ($actual != $expected) {
|
||||
$this->fileView->unlink($partFilePath);
|
||||
throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\OCP\Files\LockNotAcquiredException $e) {
|
||||
// the file is currently being written to by another process
|
||||
throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($this->fileView->touch($this->path, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
// rename to correct path
|
||||
try {
|
||||
$renameOkay = $this->fileView->rename($partFilePath, $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);
|
||||
$this->fileView->unlink($partFilePath);
|
||||
throw new \Sabre\DAV\Exception('Could not rename part file to final file');
|
||||
}
|
||||
}
|
||||
catch (\OCP\Files\LockNotAcquiredException $e) {
|
||||
// the file is currently being written to by another process
|
||||
throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($this->fileView->touch($this->path, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
}
|
||||
}
|
||||
$this->refreshInfo();
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
$this->refreshInfo();
|
||||
|
||||
return '"' . $this->info->getEtag() . '"';
|
||||
}
|
||||
|
|
@ -158,6 +168,8 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
|||
return $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
|
||||
} catch (\OCA\Encryption\Exceptions\EncryptionException $e) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,9 +186,13 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
|||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
|
||||
if (!$this->fileView->unlink($this->path)) {
|
||||
// assume it wasn't possible to delete due to permissions
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
try {
|
||||
if (!$this->fileView->unlink($this->path)) {
|
||||
// assume it wasn't possible to delete due to permissions
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
// remove properties
|
||||
|
|
@ -235,33 +251,37 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\
|
|||
|
||||
if ($chunk_handler->isComplete()) {
|
||||
|
||||
// we first assembly the target file as a part file
|
||||
$partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
|
||||
$chunk_handler->file_assemble($partFile);
|
||||
try {
|
||||
// we first assembly the target file as a part file
|
||||
$partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
|
||||
$chunk_handler->file_assemble($partFile);
|
||||
|
||||
// here is the final atomic rename
|
||||
$targetPath = $path . '/' . $info['name'];
|
||||
$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) {
|
||||
$this->fileView->unlink($targetPath);
|
||||
// here is the final atomic rename
|
||||
$targetPath = $path . '/' . $info['name'];
|
||||
$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) {
|
||||
$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');
|
||||
}
|
||||
|
||||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($this->fileView->touch($targetPath, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
// allow sync clients to send the mtime along in a header
|
||||
$mtime = OC_Request::hasModificationTime();
|
||||
if ($mtime !== false) {
|
||||
if($this->fileView->touch($targetPath, $mtime)) {
|
||||
header('X-OC-MTime: accepted');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$info = $this->fileView->getFileInfo($targetPath);
|
||||
return $info->getEtag();
|
||||
$info = $this->fileView->getFileInfo($targetPath);
|
||||
return $info->getEtag();
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -138,27 +138,31 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
|||
$isMovableMount = true;
|
||||
}
|
||||
|
||||
// check update privileges
|
||||
if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
if ($sourceDir !== $destinationDir) {
|
||||
if (!$this->fileView->isCreatable($destinationDir)) {
|
||||
try {
|
||||
// check update privileges
|
||||
if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
if ($sourceDir !== $destinationDir) {
|
||||
if (!$this->fileView->isCreatable($destinationDir)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fileName = basename($destinationPath);
|
||||
if (!\OCP\Util::isValidFileName($fileName)) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest();
|
||||
}
|
||||
$fileName = basename($destinationPath);
|
||||
if (!\OCP\Util::isValidFileName($fileName)) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest();
|
||||
}
|
||||
|
||||
$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
|
||||
if (!$renameOkay) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden('');
|
||||
$renameOkay = $this->fileView->rename($sourcePath, $destinationPath);
|
||||
if (!$renameOkay) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden('');
|
||||
}
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
// update properties
|
||||
|
|
@ -188,19 +192,23 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
|||
throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
|
||||
}
|
||||
|
||||
if ($this->fileView->is_file($source)) {
|
||||
$this->fileView->copy($source, $destination);
|
||||
} else {
|
||||
$this->fileView->mkdir($destination);
|
||||
$dh = $this->fileView->opendir($source);
|
||||
if (is_resource($dh)) {
|
||||
while (($subNode = readdir($dh)) !== false) {
|
||||
try {
|
||||
if ($this->fileView->is_file($source)) {
|
||||
$this->fileView->copy($source, $destination);
|
||||
} else {
|
||||
$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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
|
||||
list($destinationDir,) = \Sabre\DAV\URLUtil::splitPath($destination);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,11 @@ class OC_Connector_Sabre_QuotaPlugin extends \Sabre\DAV\ServerPlugin {
|
|||
* @return mixed
|
||||
*/
|
||||
public function getFreeSpace($parentUri) {
|
||||
$freeSpace = $this->view->free_space($parentUri);
|
||||
return $freeSpace;
|
||||
try {
|
||||
$freeSpace = $this->view->free_space($parentUri);
|
||||
return $freeSpace;
|
||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue