Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2016-01-11 14:38:13 +0300
committerVincent Petry <pvince81@owncloud.com>2016-02-17 13:52:49 +0300
commit53eff9792f1ae5ece49dfe79b40d1d73ae530688 (patch)
tree72ae6ed17502d332dd4a539fc5699be05a11d49d
parent7b0f83b616246c5274b551ab46b923b0989c464e (diff)
Check the quota on the actual file's storage in dav quota plugin
Fix quota plugin to use the correct file name when chunking When chunking, the file name is the compound name, so need to convert it to the correct final file name before doing the free space check. This ensures that in the case of shared files, the correct storage is used for the quota check.
-rw-r--r--apps/dav/lib/connector/sabre/quotaplugin.php17
-rw-r--r--apps/dav/tests/unit/connector/sabre/quotaplugin.php109
2 files changed, 116 insertions, 10 deletions
diff --git a/apps/dav/lib/connector/sabre/quotaplugin.php b/apps/dav/lib/connector/sabre/quotaplugin.php
index a02827da499..b1c3bbfbbb9 100644
--- a/apps/dav/lib/connector/sabre/quotaplugin.php
+++ b/apps/dav/lib/connector/sabre/quotaplugin.php
@@ -95,12 +95,14 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
$req = $this->server->httpRequest;
if ($req->getHeader('OC-Chunked')) {
$info = \OC_FileChunking::decodeName($newName);
- $chunkHandler = new \OC_FileChunking($info);
+ $chunkHandler = $this->getFileChunking($info);
// subtract the already uploaded size to see whether
// there is still enough space for the remaining chunks
$length -= $chunkHandler->getCurrentSize();
+ // use target file name for free space check in case of shared files
+ $uri = rtrim($parentUri, '/') . '/' . $info['name'];
}
- $freeSpace = $this->getFreeSpace($parentUri);
+ $freeSpace = $this->getFreeSpace($uri);
if ($freeSpace !== \OCP\Files\FileInfo::SPACE_UNKNOWN && $length > $freeSpace) {
if (isset($chunkHandler)) {
$chunkHandler->cleanup();
@@ -111,6 +113,11 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
return true;
}
+ public function getFileChunking($info) {
+ // FIXME: need a factory for better mocking support
+ return new \OC_FileChunking($info);
+ }
+
public function getLength() {
$req = $this->server->httpRequest;
$length = $req->getHeader('X-Expected-Entity-Length');
@@ -127,12 +134,12 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
}
/**
- * @param string $parentUri
+ * @param string $uri
* @return mixed
*/
- public function getFreeSpace($parentUri) {
+ public function getFreeSpace($uri) {
try {
- $freeSpace = $this->view->free_space($parentUri);
+ $freeSpace = $this->view->free_space(ltrim($uri, '/'));
return $freeSpace;
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
diff --git a/apps/dav/tests/unit/connector/sabre/quotaplugin.php b/apps/dav/tests/unit/connector/sabre/quotaplugin.php
index cc4339ecc1a..b5a8bfef31c 100644
--- a/apps/dav/tests/unit/connector/sabre/quotaplugin.php
+++ b/apps/dav/tests/unit/connector/sabre/quotaplugin.php
@@ -39,10 +39,13 @@ class QuotaPlugin extends \Test\TestCase {
*/
private $plugin;
- private function init($quota) {
- $view = $this->buildFileViewMock($quota);
+ private function init($quota, $checkedPath = '') {
+ $view = $this->buildFileViewMock($quota, $checkedPath);
$this->server = new \Sabre\DAV\Server();
- $this->plugin = new \OCA\DAV\Connector\Sabre\QuotaPlugin($view);
+ $this->plugin = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\QuotaPlugin')
+ ->setConstructorArgs([$view])
+ ->setMethods(['getFileChunking'])
+ ->getMock();
$this->plugin->initialize($this->server);
}
@@ -51,6 +54,8 @@ class QuotaPlugin extends \Test\TestCase {
*/
public function testLength($expected, $headers) {
$this->init(0);
+ $this->plugin->expects($this->never())
+ ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
$length = $this->plugin->getLength();
$this->assertEquals($expected, $length);
@@ -61,6 +66,8 @@ class QuotaPlugin extends \Test\TestCase {
*/
public function testCheckQuota($quota, $headers) {
$this->init($quota);
+ $this->plugin->expects($this->never())
+ ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
$result = $this->plugin->checkQuota('');
@@ -73,11 +80,26 @@ class QuotaPlugin extends \Test\TestCase {
*/
public function testCheckExceededQuota($quota, $headers) {
$this->init($quota);
+ $this->plugin->expects($this->never())
+ ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
$this->plugin->checkQuota('');
}
+ /**
+ * @dataProvider quotaOkayProvider
+ */
+ public function testCheckQuotaOnPath($quota, $headers) {
+ $this->init($quota, 'sub/test.txt');
+ $this->plugin->expects($this->never())
+ ->method('getFileChunking');
+
+ $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
+ $result = $this->plugin->checkQuota('/sub/test.txt');
+ $this->assertTrue($result);
+ }
+
public function quotaOkayProvider() {
return array(
array(1024, array()),
@@ -110,12 +132,89 @@ class QuotaPlugin extends \Test\TestCase {
);
}
- private function buildFileViewMock($quota) {
+ public function quotaChunkedOkProvider() {
+ return array(
+ array(1024, 0, array('X-EXPECTED-ENTITY-LENGTH' => '1024')),
+ array(1024, 0, array('CONTENT-LENGTH' => '512')),
+ array(1024, 0, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')),
+ // with existing chunks (allowed size = total length - chunk total size)
+ array(400, 128, array('X-EXPECTED-ENTITY-LENGTH' => '512')),
+ array(400, 128, array('CONTENT-LENGTH' => '512')),
+ array(400, 128, array('OC-TOTAL-LENGTH' => '512', 'CONTENT-LENGTH' => '500')),
+ // \OCP\Files\FileInfo::SPACE-UNKNOWN = -2
+ array(-2, 0, array('X-EXPECTED-ENTITY-LENGTH' => '1024')),
+ array(-2, 0, array('CONTENT-LENGTH' => '512')),
+ array(-2, 0, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')),
+ array(-2, 128, array('X-EXPECTED-ENTITY-LENGTH' => '1024')),
+ array(-2, 128, array('CONTENT-LENGTH' => '512')),
+ array(-2, 128, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')),
+ );
+ }
+
+ /**
+ * @dataProvider quotaChunkedOkProvider
+ */
+ public function testCheckQuotaChunkedOk($quota, $chunkTotalSize, $headers) {
+ $this->init($quota, 'sub/test.txt');
+
+ $mockChunking = $this->getMockBuilder('\OC_FileChunking')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockChunking->expects($this->once())
+ ->method('getCurrentSize')
+ ->will($this->returnValue($chunkTotalSize));
+
+ $this->plugin->expects($this->once())
+ ->method('getFileChunking')
+ ->will($this->returnValue($mockChunking));
+
+ $headers['OC-CHUNKED'] = 1;
+ $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
+ $result = $this->plugin->checkQuota('/sub/test.txt-chunking-12345-3-1');
+ $this->assertTrue($result);
+ }
+
+ public function quotaChunkedFailProvider() {
+ return array(
+ array(400, 0, array('X-EXPECTED-ENTITY-LENGTH' => '1024')),
+ array(400, 0, array('CONTENT-LENGTH' => '512')),
+ array(400, 0, array('OC-TOTAL-LENGTH' => '1024', 'CONTENT-LENGTH' => '512')),
+ // with existing chunks (allowed size = total length - chunk total size)
+ array(380, 128, array('X-EXPECTED-ENTITY-LENGTH' => '512')),
+ array(380, 128, array('CONTENT-LENGTH' => '512')),
+ array(380, 128, array('OC-TOTAL-LENGTH' => '512', 'CONTENT-LENGTH' => '500')),
+ );
+ }
+
+ /**
+ * @dataProvider quotaChunkedFailProvider
+ * @expectedException \Sabre\DAV\Exception\InsufficientStorage
+ */
+ public function testCheckQuotaChunkedFail($quota, $chunkTotalSize, $headers) {
+ $this->init($quota, 'sub/test.txt');
+
+ $mockChunking = $this->getMockBuilder('\OC_FileChunking')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockChunking->expects($this->once())
+ ->method('getCurrentSize')
+ ->will($this->returnValue($chunkTotalSize));
+
+ $this->plugin->expects($this->once())
+ ->method('getFileChunking')
+ ->will($this->returnValue($mockChunking));
+
+ $headers['OC-CHUNKED'] = 1;
+ $this->server->httpRequest = new \Sabre\HTTP\Request(null, null, $headers);
+ $this->plugin->checkQuota('/sub/test.txt-chunking-12345-3-1');
+ }
+
+ private function buildFileViewMock($quota, $checkedPath) {
// mock filesysten
$view = $this->getMock('\OC\Files\View', array('free_space'), array(), '', false);
$view->expects($this->any())
->method('free_space')
- ->with($this->identicalTo(''))
+ ->with($this->identicalTo($checkedPath))
->will($this->returnValue($quota));
return $view;