In case of encryption exceptions we return 503 - this will allow the client to retry

This commit is contained in:
Thomas Müller 2015-04-07 14:17:28 +02:00
parent 54a3bdf1c5
commit 161d80da5b
1 changed files with 68 additions and 54 deletions

View File

@ -35,9 +35,24 @@
namespace OC\Connector\Sabre;
use OC\Connector\Sabre\Exception\EntityTooLarge;
use OC\Connector\Sabre\Exception\FileLocked;
use OC\Connector\Sabre\Exception\UnsupportedMediaType;
use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\Files\EntityTooLargeException;
use OCP\Files\InvalidContentException;
use OCP\Files\InvalidPathException;
use OCP\Files\LockNotAcquiredException;
use OCP\Files\NotPermittedException;
use OCP\Files\StorageNotAvailableException;
use Sabre\DAV\Exception;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotImplemented;
use Sabre\DAV\Exception\ServiceUnavailable;
use Sabre\DAV\IFile;
class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
class File extends Node implements IFile {
/**
* Updates the data
@ -58,22 +73,22 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
*
* @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
* @throws Forbidden
* @throws UnsupportedMediaType
* @throws BadRequest
* @throws Exception
* @throws EntityTooLarge
* @throws ServiceUnavailable
* @return string|null
*/
public function put($data) {
try {
if ($this->info && $this->fileView->file_exists($this->path) &&
!$this->info->isUpdateable()) {
throw new \Sabre\DAV\Exception\Forbidden();
throw new Forbidden();
}
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("File is not updatable: ".$e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("File is not updatable: ".$e->getMessage());
}
// verify path of the target
@ -101,31 +116,29 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
\OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
$this->fileView->unlink($partFilePath);
// 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 Exception('Could not write file contents');
}
} catch (\OCP\Files\NotPermittedException $e) {
} catch (NotPermittedException $e) {
// a more general case - due to whatever reason the content could not be written
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
} catch (\OCP\Files\EntityTooLargeException $e) {
throw new Forbidden($e->getMessage());
} catch (EntityTooLargeException $e) {
// the file is too big to be stored
throw new \OC\Connector\Sabre\Exception\EntityTooLarge($e->getMessage());
} catch (\OCP\Files\InvalidContentException $e) {
throw new EntityTooLarge($e->getMessage());
} catch (InvalidContentException $e) {
// the file content is not permitted
throw new \OC\Connector\Sabre\Exception\UnsupportedMediaType($e->getMessage());
} catch (\OCP\Files\InvalidPathException $e) {
throw new UnsupportedMediaType($e->getMessage());
} catch (InvalidPathException $e) {
// the path for the file was not valid
// TODO: find proper http status code for this case
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
} catch (\OCP\Files\LockNotAcquiredException $e) {
throw new Forbidden($e->getMessage());
} catch (LockNotAcquiredException $e) {
// the file is currently being written to by another process
throw new \OC\Connector\Sabre\Exception\FileLocked($e->getMessage(), $e->getCode(), $e);
throw new FileLocked($e->getMessage(), $e->getCode(), $e);
} catch (GenericEncryptionException $e) {
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to write file contents: ".$e->getMessage());
// returning 503 will allow retry of the operation at a later point in time
throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to write file contents: ".$e->getMessage());
}
try {
@ -137,7 +150,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$actual = $this->fileView->filesize($partFilePath);
if ($actual != $expected) {
$this->fileView->unlink($partFilePath);
throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual);
throw new BadRequest('expected filesize ' . $expected . ' got ' . $actual);
}
}
@ -149,12 +162,12 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
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');
throw new Exception('Could not rename part file to final file');
}
}
catch (\OCP\Files\LockNotAcquiredException $e) {
catch (LockNotAcquiredException $e) {
// the file is currently being written to by another process
throw new \OC\Connector\Sabre\Exception\FileLocked($e->getMessage(), $e->getCode(), $e);
throw new FileLocked($e->getMessage(), $e->getCode(), $e);
}
}
@ -166,8 +179,8 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
}
}
$this->refreshInfo();
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to check file size: ".$e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to check file size: ".$e->getMessage());
}
return '"' . $this->info->getEtag() . '"';
@ -176,38 +189,39 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
/**
* Returns the data
* @return string|resource
* @throws \Sabre\DAV\Exception\Forbidden
* @throws \Sabre\DAV\Exception\ServiceUnavailable
* @throws Forbidden
* @throws ServiceUnavailable
*/
public function get() {
//throw exception if encryption is disabled but files are still encrypted
try {
return $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
} catch (\OCP\Encryption\Exceptions\GenericEncryptionException $e) {
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to open file: ".$e->getMessage());
} catch (GenericEncryptionException $e) {
// returning 503 will allow retry of the operation at a later point in time
throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to open file: ".$e->getMessage());
}
}
/**
* Delete the current file
* @throws \Sabre\DAV\Exception\Forbidden
* @throws \Sabre\DAV\Exception\ServiceUnavailable
* @throws Forbidden
* @throws ServiceUnavailable
*/
public function delete() {
if (!$this->info->isDeletable()) {
throw new \Sabre\DAV\Exception\Forbidden();
throw new Forbidden();
}
try {
if (!$this->fileView->unlink($this->path)) {
// assume it wasn't possible to delete due to permissions
throw new \Sabre\DAV\Exception\Forbidden();
throw new Forbidden();
}
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to unlink: ".$e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to unlink: ".$e->getMessage());
}
}
@ -247,10 +261,10 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
/**
* @param resource $data
* @return null|string
* @throws \Sabre\DAV\Exception
* @throws \Sabre\DAV\Exception\BadRequest
* @throws \Sabre\DAV\Exception\NotImplemented
* @throws \Sabre\DAV\Exception\ServiceUnavailable
* @throws Exception
* @throws BadRequest
* @throws NotImplemented
* @throws ServiceUnavailable
*/
private function createFileChunked($data)
{
@ -258,7 +272,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$info = \OC_FileChunking::decodeName($name);
if (empty($info)) {
throw new \Sabre\DAV\Exception\NotImplemented();
throw new NotImplemented();
}
$chunk_handler = new \OC_FileChunking($info);
$bytesWritten = $chunk_handler->store($info['index'], $data);
@ -269,7 +283,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$expected = $_SERVER['CONTENT_LENGTH'];
if ($bytesWritten != $expected) {
$chunk_handler->remove($info['index']);
throw new \Sabre\DAV\Exception\BadRequest(
throw new BadRequest(
'expected filesize ' . $expected . ' got ' . $bytesWritten);
}
}
@ -295,7 +309,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
if ($fileExists) {
$this->fileView->unlink($targetPath);
}
throw new \Sabre\DAV\Exception('Could not rename part file assembled from chunks');
throw new Exception('Could not rename part file assembled from chunks');
}
} else {
// assemble directly into the final file
@ -312,8 +326,8 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$info = $this->fileView->getFileInfo($targetPath);
return $info->getEtag();
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to put file: ".$e->getMessage());
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable("Failed to put file: ".$e->getMessage());
}
}